1 use crate::*;
2
3 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
4 pub struct Range {
5 pub comparator_set: Vec<Comparator>,
6 pub compat: range_set::Compat,
7 }
8
9 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
10 pub struct Comparator {
11 pub op: Op,
12 pub major: u64,
13 pub minor: u64,
14 pub patch: u64,
15 pub pre: Vec<Identifier>,
16 }
17
18 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
19 pub enum Op {
20 Lt,
21 Lte,
22 Gt,
23 Gte,
24 Eq,
25 }
26
27 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
28 pub enum Identifier {
29 Numeric(u64),
30 AlphaNumeric(String),
31 }
32
33 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
34 pub struct Partial {
35 major: Option<u64>,
36 minor: Option<u64>,
37 patch: Option<u64>,
38 pre: Vec<Identifier>,
39 kind: PartialKind,
40 }
41
42 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
43 pub enum PartialKind {
44 XRangeOnly,
45 MajorOnly,
46 MajorMinor,
47 MajorMinorPatch,
48 }
49
50 impl Partial {
new() -> Self51 pub fn new() -> Self {
52 Self {
53 major: None,
54 minor: None,
55 patch: None,
56 pre: Vec::new(),
57 kind: PartialKind::XRangeOnly,
58 }
59 }
60
as_comparator(&self, op: Op) -> Comparator61 pub fn as_comparator(&self, op: Op) -> Comparator {
62 Comparator {
63 op,
64 major: self.major.unwrap_or(0),
65 minor: self.minor.unwrap_or(0),
66 patch: self.patch.unwrap_or(0),
67 pre: self.pre.clone(),
68 }
69 }
70
inc_major(&mut self) -> &mut Self71 pub fn inc_major(&mut self) -> &mut Self {
72 self.major = Some(self.major.unwrap_or(0) + 1);
73 self
74 }
75
inc_minor(&mut self) -> &mut Self76 pub fn inc_minor(&mut self) -> &mut Self {
77 self.minor = Some(self.minor.unwrap_or(0) + 1);
78 self
79 }
80
inc_patch(&mut self) -> &mut Self81 pub fn inc_patch(&mut self) -> &mut Self {
82 self.patch = Some(self.patch.unwrap_or(0) + 1);
83 self
84 }
85
zero_missing(&mut self) -> &mut Self86 pub fn zero_missing(&mut self) -> &mut Self {
87 self.major = Some(self.major.unwrap_or(0));
88 self.minor = Some(self.minor.unwrap_or(0));
89 self.patch = Some(self.patch.unwrap_or(0));
90 self
91 }
92
zero_minor(&mut self) -> &mut Self93 pub fn zero_minor(&mut self) -> &mut Self {
94 self.minor = Some(0);
95 self
96 }
97
zero_patch(&mut self) -> &mut Self98 pub fn zero_patch(&mut self) -> &mut Self {
99 self.patch = Some(0);
100 self
101 }
102
no_pre(&mut self) -> &mut Self103 pub fn no_pre(&mut self) -> &mut Self {
104 self.pre = Vec::new();
105 self
106 }
107 }
108
from_pair_iterator( parsed_range: pest::iterators::Pair<'_, Rule>, compat: range_set::Compat, ) -> Result<Range, String>109 pub fn from_pair_iterator(
110 parsed_range: pest::iterators::Pair<'_, Rule>,
111 compat: range_set::Compat,
112 ) -> Result<Range, String> {
113 // First of all, do we have the correct iterator?
114 if parsed_range.as_rule() != Rule::range {
115 return Err(String::from("Error parsing range"));
116 }
117
118 let mut comparator_set = Vec::new();
119
120 // Now we need to parse each comparator set out of the range
121 for record in parsed_range.into_inner() {
122 match record.as_rule() {
123 Rule::hyphen => {
124 let mut hyphen_set = simple::from_hyphen_range(record)?;
125 comparator_set.append(&mut hyphen_set);
126 }
127 Rule::simple => {
128 let mut comparators = simple::from_pair_iterator(record, compat)?;
129 comparator_set.append(&mut comparators);
130 }
131 Rule::empty => {
132 comparator_set.push(Partial::new().zero_missing().as_comparator(Op::Gte));
133 }
134 _ => unreachable!(),
135 }
136 }
137
138 Ok(Range {
139 comparator_set,
140 compat,
141 })
142 }
143
144 pub mod simple {
145 use super::*;
146
from_pair_iterator( parsed_simple: pest::iterators::Pair<'_, Rule>, compat: range_set::Compat, ) -> Result<Vec<Comparator>, String>147 pub fn from_pair_iterator(
148 parsed_simple: pest::iterators::Pair<'_, Rule>,
149 compat: range_set::Compat,
150 ) -> Result<Vec<Comparator>, String> {
151 // First of all, do we have the correct iterator?
152 if parsed_simple.as_rule() != Rule::simple {
153 return Err(String::from("Error parsing comparator set"));
154 }
155
156 let mut comparators = Vec::new();
157
158 // Now we need to parse each comparator set out of the range
159 for record in parsed_simple.into_inner() {
160 match record.as_rule() {
161 Rule::partial => {
162 let components: Vec<_> = record.into_inner().collect();
163
164 let mut partial = parse_partial(components);
165
166 match partial.kind {
167 PartialKind::XRangeOnly => {
168 // '*', 'x', 'X' --> ">=0.0.0"
169 comparators.push(partial.zero_missing().as_comparator(Op::Gte));
170 }
171 PartialKind::MajorOnly => {
172 // "1", "1.*", or "1.*.*" --> ">=1.0.0 <2.0.0"
173 // "1.*.3" == "1.*"
174 comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte));
175 comparators
176 .push(partial.inc_major().zero_missing().as_comparator(Op::Lt));
177 }
178 PartialKind::MajorMinor => {
179 // "1.2" or "1.2.*" --> ">=1.2.0 <1.3.0"
180 comparators.push(partial.clone().zero_patch().as_comparator(Op::Gte));
181 comparators
182 .push(partial.inc_minor().zero_patch().as_comparator(Op::Lt));
183 }
184 PartialKind::MajorMinorPatch => {
185 match compat {
186 range_set::Compat::Npm => {
187 // for node, "1.2.3" is "=1.2.3"
188 comparators.push(partial.as_comparator(Op::Eq));
189 }
190 range_set::Compat::Cargo => {
191 // for cargo, "1.2.3" is parsed as "^1.2.3"
192 handle_caret_range(partial, &mut comparators);
193 }
194 }
195 }
196 }
197 }
198 Rule::primitive => {
199 let mut components: Vec<_> = record.into_inner().collect();
200 let op_component = components.remove(0);
201
202 let op = match op_component.as_str() {
203 "=" => Op::Eq,
204 "<" => Op::Lt,
205 "<=" => Op::Lte,
206 ">" => Op::Gt,
207 ">=" => Op::Gte,
208 _ => unreachable!(),
209 };
210
211 let partial_component = components.remove(0);
212 let components: Vec<_> = partial_component.into_inner().collect();
213 let mut partial = parse_partial(components);
214
215 // equal is different because it can be a range with 2 comparators
216 if op == Op::Eq {
217 match partial.kind {
218 PartialKind::XRangeOnly => {
219 // '=*' --> ">=0.0.0"
220 comparators.push(partial.zero_missing().as_comparator(Op::Gte));
221 }
222 PartialKind::MajorOnly => {
223 // "=1", "=1.*", or "=1.*.*" --> ">=1.0.0 <2.0.0"
224 comparators
225 .push(partial.clone().zero_missing().as_comparator(Op::Gte));
226 comparators
227 .push(partial.inc_major().zero_missing().as_comparator(Op::Lt));
228 }
229 PartialKind::MajorMinor => {
230 // "=1.2" or "=1.2.*" --> ">=1.2.0 <1.3.0"
231 comparators
232 .push(partial.clone().zero_patch().as_comparator(Op::Gte));
233 comparators
234 .push(partial.inc_minor().zero_patch().as_comparator(Op::Lt));
235 }
236 PartialKind::MajorMinorPatch => {
237 comparators.push(partial.as_comparator(Op::Eq));
238 }
239 }
240 } else {
241 match partial.kind {
242 PartialKind::XRangeOnly => {
243 match op {
244 Op::Eq => comparators
245 .push(partial.zero_missing().as_comparator(Op::Gte)),
246 Op::Lt => comparators
247 .push(partial.zero_missing().as_comparator(Op::Lt)),
248 Op::Lte => comparators
249 .push(partial.zero_missing().as_comparator(Op::Gte)),
250 Op::Gt => comparators
251 .push(partial.zero_missing().as_comparator(Op::Lt)),
252 Op::Gte => comparators
253 .push(partial.zero_missing().as_comparator(Op::Gte)),
254 }
255 }
256 PartialKind::MajorOnly => {
257 // ">1", "=1", etc.
258 // ">1.*.3" == ">1.*"
259 match op {
260 Op::Lte => comparators.push(
261 partial
262 .inc_major()
263 .zero_minor()
264 .zero_patch()
265 .as_comparator(Op::Lt),
266 ),
267 _ => comparators.push(partial.zero_missing().as_comparator(op)),
268 }
269 }
270 PartialKind::MajorMinor => {
271 // ">1.2", "<1.2.*", etc.
272 match op {
273 Op::Lte => comparators.push(
274 partial.inc_minor().zero_patch().as_comparator(Op::Lt),
275 ),
276 _ => comparators.push(partial.zero_patch().as_comparator(op)),
277 }
278 }
279 PartialKind::MajorMinorPatch => {
280 comparators.push(partial.as_comparator(op));
281 }
282 }
283 }
284 }
285 Rule::caret => {
286 let mut components: Vec<_> = record.into_inner().collect();
287
288 let partial_component = components.remove(0);
289 let components: Vec<_> = partial_component.into_inner().collect();
290 let partial = parse_partial(components);
291
292 handle_caret_range(partial, &mut comparators);
293 }
294 Rule::tilde => {
295 let mut components: Vec<_> = record.into_inner().collect();
296
297 let partial_component = components.remove(0);
298 let components: Vec<_> = partial_component.into_inner().collect();
299 let mut partial = parse_partial(components);
300
301 comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte));
302
303 match partial.kind {
304 PartialKind::XRangeOnly => {
305 // "~*" --> ">=0.0.0"
306 // which has already been added, so nothing to do here
307 }
308 PartialKind::MajorOnly => {
309 // "~0" --> ">=0.0.0 <1.0.0"
310 comparators.push(
311 partial
312 .inc_major()
313 .zero_missing()
314 .no_pre()
315 .as_comparator(Op::Lt),
316 );
317 }
318 PartialKind::MajorMinor | PartialKind::MajorMinorPatch => {
319 // "~1.2" --> ">=1.2.0 <1.3.0"
320 // "~1.2.3" --> ">=1.2.3 <1.3.0"
321 comparators.push(
322 partial
323 .inc_minor()
324 .zero_patch()
325 .no_pre()
326 .as_comparator(Op::Lt),
327 );
328 }
329 }
330 }
331 _ => unreachable!(),
332 }
333 }
334
335 Ok(comparators)
336 }
337
handle_caret_range(mut partial: Partial, comparators: &mut Vec<Comparator>)338 fn handle_caret_range(mut partial: Partial, comparators: &mut Vec<Comparator>) {
339 // major version 0 is a special case for caret
340 if partial.major == Some(0) {
341 match partial.kind {
342 PartialKind::XRangeOnly => unreachable!(),
343 PartialKind::MajorOnly => {
344 // "^0", "^0.*" --> ">=0.0.0 <1.0.0"
345 comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte));
346 comparators.push(
347 partial
348 .inc_major()
349 .zero_missing()
350 .no_pre()
351 .as_comparator(Op::Lt),
352 );
353 }
354 PartialKind::MajorMinor => {
355 // "^0.2", "^0.2.*" --> ">=0.2.0 <0.3.0"
356 comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte));
357 comparators.push(
358 partial
359 .inc_minor()
360 .zero_patch()
361 .no_pre()
362 .as_comparator(Op::Lt),
363 );
364 }
365 PartialKind::MajorMinorPatch => {
366 if partial.minor == Some(0) {
367 // "^0.0.1" --> ">=0.0.1 <0.0.2"
368 comparators.push(partial.as_comparator(Op::Gte));
369 comparators.push(partial.inc_patch().no_pre().as_comparator(Op::Lt));
370 } else {
371 // "^0.2.3" --> ">=0.2.3 <0.3.0"
372 comparators.push(partial.as_comparator(Op::Gte));
373 comparators.push(
374 partial
375 .inc_minor()
376 .zero_patch()
377 .no_pre()
378 .as_comparator(Op::Lt),
379 );
380 }
381 }
382 }
383 } else {
384 match partial.kind {
385 PartialKind::XRangeOnly => {
386 // "^*" --> ">=0.0.0"
387 comparators.push(partial.zero_missing().as_comparator(Op::Gte));
388 }
389 _ => {
390 // "^1", "^1.*" --> ">=1.0.0 <2.0.0"
391 // "^1.2", "^1.2.*" --> ">=1.2.0 <2.0.0"
392 // "^1.2.3" --> ">=1.2.3 <2.0.0"
393 comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte));
394 comparators.push(
395 partial
396 .inc_major()
397 .zero_minor()
398 .zero_patch()
399 .no_pre()
400 .as_comparator(Op::Lt),
401 );
402 }
403 }
404 }
405 }
406
from_hyphen_range( parsed_simple: pest::iterators::Pair<'_, Rule>, ) -> Result<Vec<Comparator>, String>407 pub fn from_hyphen_range(
408 parsed_simple: pest::iterators::Pair<'_, Rule>,
409 ) -> Result<Vec<Comparator>, String> {
410 // First of all, do we have the correct iterator?
411 if parsed_simple.as_rule() != Rule::hyphen {
412 return Err(String::from("Error parsing comparator set"));
413 }
414
415 let mut comparators = Vec::new();
416
417 // At this point, we have 2 partial records
418 let mut records = parsed_simple.into_inner();
419
420 let components1: Vec<_> = records.next().unwrap().into_inner().collect();
421 let mut partial1 = parse_partial(components1);
422 match partial1.kind {
423 PartialKind::XRangeOnly => {
424 // don't need to include this - the range will be limited by the 2nd part of hyphen
425 // range
426 }
427 _ => comparators.push(partial1.zero_missing().as_comparator(Op::Gte)),
428 }
429
430 let components2: Vec<_> = records.next().unwrap().into_inner().collect();
431 let mut partial2 = parse_partial(components2);
432
433 match partial2.kind {
434 PartialKind::XRangeOnly => {
435 // only include this if the first part of the hyphen range was also '*'
436 if partial1.kind == PartialKind::XRangeOnly {
437 comparators.push(partial2.zero_missing().as_comparator(Op::Gte));
438 }
439 }
440 PartialKind::MajorOnly => {
441 // "1.2.3 - 2" --> ">=1.2.3 <3.0.0"
442 comparators.push(
443 partial2
444 .inc_major()
445 .zero_minor()
446 .zero_patch()
447 .as_comparator(Op::Lt),
448 );
449 }
450 PartialKind::MajorMinor => {
451 // "1.2.3 - 2.3.x" --> ">=1.2.3 <2.4.0"
452 comparators.push(partial2.inc_minor().zero_patch().as_comparator(Op::Lt));
453 }
454 PartialKind::MajorMinorPatch => {
455 // "1.2.3 - 2.3.4" --> ">=1.2.3 <=2.3.4"
456 comparators.push(partial2.as_comparator(Op::Lte));
457 }
458 }
459
460 Ok(comparators)
461 }
462
parse_partial(mut components: Vec<pest::iterators::Pair<'_, Rule>>) -> Partial463 fn parse_partial(mut components: Vec<pest::iterators::Pair<'_, Rule>>) -> Partial {
464 let mut partial = Partial::new();
465
466 // there will be at least one component
467 let one = components.remove(0);
468
469 match one.as_rule() {
470 Rule::xr => {
471 let inner = one.into_inner().next().unwrap();
472 match inner.as_rule() {
473 Rule::xr_op => {
474 // for "*", ">=*", etc.
475 partial.major = None;
476 partial.kind = PartialKind::XRangeOnly;
477 // end the pattern here
478 return partial;
479 }
480 Rule::nr => {
481 partial.major = Some(inner.as_str().parse::<u64>().unwrap());
482 }
483 _ => unreachable!(),
484 }
485 }
486 _ => unreachable!(),
487 }
488
489 if components.is_empty() {
490 // only the major has been given
491 partial.kind = PartialKind::MajorOnly;
492 return partial;
493 } else {
494 let two = components.remove(0);
495
496 match two.as_rule() {
497 Rule::xr => {
498 let inner = two.into_inner().next().unwrap();
499 match inner.as_rule() {
500 Rule::xr_op => {
501 partial.minor = None;
502 // only the major has been given, minor is xrange (ignore anything after)
503 partial.kind = PartialKind::MajorOnly;
504 return partial;
505 }
506 Rule::nr => {
507 partial.minor = Some(inner.as_str().parse::<u64>().unwrap());
508 }
509 _ => unreachable!(),
510 }
511 }
512 _ => unreachable!(),
513 }
514 }
515
516 if components.is_empty() {
517 // only major and minor have been given
518 partial.kind = PartialKind::MajorMinor;
519 return partial;
520 } else {
521 let three = components.remove(0);
522
523 match three.as_rule() {
524 Rule::xr => {
525 let inner = three.into_inner().next().unwrap();
526 match inner.as_rule() {
527 Rule::xr_op => {
528 partial.patch = None;
529 // only major and minor have been given, patch is xrange
530 partial.kind = PartialKind::MajorMinor;
531 return partial;
532 }
533 Rule::nr => {
534 partial.patch = Some(inner.as_str().parse::<u64>().unwrap());
535 }
536 _ => unreachable!(),
537 }
538 }
539 _ => unreachable!(),
540 }
541 }
542
543 // at this point we at least have all three fields
544 partial.kind = PartialKind::MajorMinorPatch;
545
546 if !components.is_empty() {
547 // there's only going to be one, let's move it out
548 let pre = components.remove(0);
549 // now we want to look at the inner bit, so that we don't have the leading -
550 let mut pre: Vec<_> = pre.into_inner().collect();
551 let pre = pre.remove(0);
552 let pre = pre.as_str();
553
554 // now we have all of the stuff in pre, so we split by . to get each bit
555 for bit in pre.split('.') {
556 let identifier = match bit.parse::<u64>() {
557 Ok(num) => Identifier::Numeric(num),
558 Err(_) => Identifier::AlphaNumeric(bit.to_string()),
559 };
560
561 partial.pre.push(identifier);
562 }
563 }
564
565 partial
566 }
567 }
568
569 #[cfg(test)]
570 mod tests {
571 use super::*;
572 use pest::Parser;
573
parse_range(input: &str) -> pest::iterators::Pair<'_, Rule>574 fn parse_range(input: &str) -> pest::iterators::Pair<'_, Rule> {
575 match SemverParser::parse(Rule::range, input) {
576 Ok(mut parsed) => match parsed.next() {
577 Some(parsed) => parsed,
578 None => panic!("Could not parse {}", input),
579 },
580 Err(e) => panic!("Parse error:\n{}", e),
581 }
582 }
583
584 // macros to handle the test boilerplate
585
586 macro_rules! range_tests {
587 ( $( $name:ident: $value:expr, )* ) => {
588 $(
589 #[test]
590 fn $name() {
591 let (input, expected_range) = $value;
592
593 let parsed_range = parse_range(input);
594 let range = from_pair_iterator(parsed_range, range_set::Compat::Cargo).expect("parsing failed");
595
596 // get the expected length from the input range
597 let num_comparators = range.comparator_set.len();
598 let expected_comparators = expected_range.comparator_set.len();
599 assert_eq!(expected_comparators, num_comparators, "expected number of comparators: {}, got: {}", expected_comparators, num_comparators);
600
601 assert_eq!(range, expected_range);
602 }
603 )*
604 };
605 }
606
607 macro_rules! range_tests_nodecompat {
608 ( $( $name:ident: $value:expr, )* ) => {
609 $(
610 #[test]
611 fn $name() {
612 let (input, expected_range) = $value;
613
614 let parsed_range = parse_range(input);
615 let range = from_pair_iterator(parsed_range, range_set::Compat::Npm).expect("parsing failed");
616
617 // get the expected length from the input range
618 let num_comparators = range.comparator_set.len();
619 let expected_comparators = expected_range.comparator_set.len();
620 assert_eq!(expected_comparators, num_comparators, "expected number of comparators: {}, got: {}", expected_comparators, num_comparators);
621
622 assert_eq!(range, expected_range);
623 }
624 )*
625 };
626 }
627
628 macro_rules! comp_sets {
629 ( $( [$op:expr, $major:expr, $minor:expr, $patch:expr] ),* ) => {
630 Range {
631 comparator_set: vec![
632 $(
633 Comparator {
634 op: $op,
635 major: $major,
636 minor: $minor,
637 patch: $patch,
638 pre: pre!(None),
639 },
640 )*
641 ],
642 compat: range_set::Compat::Cargo
643 }
644 };
645 // if you specify pre for one item, you have to do it for all of them
646 ( $( [$op:expr, $major:expr, $minor:expr, $patch:expr, $pre:expr] ),* ) => {
647 Range {
648 comparator_set: vec![
649 $(
650 Comparator {
651 op: $op,
652 major: $major,
653 minor: $minor,
654 patch: $patch,
655 pre: $pre,
656 },
657 )*
658 ],
659 compat: range_set::Compat::Cargo
660 }
661 };
662 }
663
664 // for node compatibility
665 macro_rules! comp_sets_node {
666 ( $( [$op:expr, $major:expr, $minor:expr, $patch:expr] ),* ) => {
667 Range {
668 comparator_set: vec![
669 $(
670 Comparator {
671 op: $op,
672 major: $major,
673 minor: $minor,
674 patch: $patch,
675 pre: pre!(None),
676 },
677 )*
678 ],
679 compat: range_set::Compat::Npm
680 }
681 };
682 }
683
684 macro_rules! id_num {
685 ( $num:expr ) => {
686 Identifier::Numeric($num)
687 };
688 }
689
690 macro_rules! id_alpha {
691 ( $alpha:expr ) => {
692 Identifier::AlphaNumeric(String::from($alpha))
693 };
694 }
695
696 macro_rules! pre {
697 ( None ) => {
698 Vec::new()
699 };
700 ( $( $e:expr ),* ) => {
701 vec![
702 $(
703 $e,
704 )*
705 ]
706 };
707 }
708
709 macro_rules! op {
710 ( "=" ) => {
711 Op::Eq
712 };
713 ( "<" ) => {
714 Op::Lt
715 };
716 ( "<=" ) => {
717 Op::Lte
718 };
719 ( ">" ) => {
720 Op::Gt
721 };
722 ( ">=" ) => {
723 Op::Gte
724 };
725 }
726
727 // tests
728
729 range_tests! {
730 major: ("1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
731 major_minor: ("1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
732 major_minor_patch: ("1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 2, 0, 0] )),
733 major_0_minor_patch: ("0.2.3", comp_sets!( [op!(">="), 0, 2, 3], [op!("<"), 0, 3, 0] )),
734 major_0_minor_0_patch: ("0.0.1", comp_sets!( [op!(">="), 0, 0, 1], [op!("<"), 0, 0, 2] )),
735
736 eq_major: ("=1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
737 eq_major_minor: ("=1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
738 eq_major_minor_patch: ("=1.2.3", comp_sets!( [op!("="), 1, 2, 3] )),
739 eq_all: ("=*", comp_sets!( [op!(">="), 0, 0, 0] )),
740 eq_major_star: ("=1.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
741 eq_major_minor_star: ("=1.2.*", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
742
743 lt_major: ("<1", comp_sets!( [op!("<"), 1, 0, 0] )),
744 lt_major_minor: ("<1.2", comp_sets!( [op!("<"), 1, 2, 0] )),
745 lt_major_minor_patch: ("<1.2.3", comp_sets!( [op!("<"), 1, 2, 3] )),
746 lt_all: ("<*", comp_sets!( [op!("<"), 0, 0, 0] )),
747 lt_major_star: ("<1.*", comp_sets!( [op!("<"), 1, 0, 0] )),
748 lt_major_minor_star: ("<1.2.*", comp_sets!( [op!("<"), 1, 2, 0] )),
749
750 lte_major: ("<=1", comp_sets!( [op!("<"), 2, 0, 0] )),
751 lte_major_minor: ("<=1.2", comp_sets!( [op!("<"), 1, 3, 0] )),
752 lte_major_minor_patch: ("<=1.2.3", comp_sets!( [op!("<="), 1, 2, 3] )),
753 lte_all: ("<=*", comp_sets!( [op!(">="), 0, 0, 0] )),
754 lte_major_star: ("<=1.*", comp_sets!( [op!("<"), 2, 0, 0] )),
755 lte_major_minor_star: ("<=1.2.*", comp_sets!( [op!("<"), 1, 3, 0] )),
756
757 gt_major: (">1", comp_sets!( [op!(">"), 1, 0, 0] )),
758 gt_major_minor: (">1.2", comp_sets!( [op!(">"), 1, 2, 0] )),
759 gt_major_minor_patch: (">1.2.3", comp_sets!( [op!(">"), 1, 2, 3] )),
760 gt_all: (">*", comp_sets!( [op!("<"), 0, 0, 0] )),
761 gt_major_star: (">1.*", comp_sets!( [op!(">"), 1, 0, 0] )),
762 gt_major_minor_star: (">1.2.*", comp_sets!( [op!(">"), 1, 2, 0] )),
763
764 gte_major: (">=1", comp_sets!( [op!(">="), 1, 0, 0] )),
765 gte_major_minor: (">=1.2", comp_sets!( [op!(">="), 1, 2, 0] )),
766 gte_major_minor_patch: (">=1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )),
767 gte_all: (">=*", comp_sets!( [op!(">="), 0, 0, 0] )),
768 gte_major_star: (">=1.*", comp_sets!( [op!(">="), 1, 0, 0] )),
769 gte_major_minor_star: (">=1.2.*", comp_sets!( [op!(">="), 1, 2, 0] )),
770
771 tilde_major: ("~1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
772 tilde_major_0: ("~0", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 1, 0, 0] )),
773 tilde_major_xrange: ("~1.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
774 tilde_major_2: ("~>1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
775 tilde_major_minor: ("~1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
776 tilde_major_minor_xrange: ("~1.2.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
777 tilde_major_minor_2: ("~>1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
778 tilde_major_minor_patch: ("~1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 1, 3, 0] )),
779 tilde_major_minor_patch_pre: ("~1.2.3-beta", comp_sets!( [op!(">="), 1, 2, 3, pre!(id_alpha!("beta"))], [op!("<"), 1, 3, 0, pre!()] )),
780 tilde_major_minor_patch_2: ("~>1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 1, 3, 0] )),
781 tilde_major_0_minor_patch: ("~0.2.3", comp_sets!( [op!(">="), 0, 2, 3], [op!("<"), 0, 3, 0] )),
782 tilde_all: ("~*", comp_sets!( [op!(">="), 0, 0, 0] )),
783
784 caret_major: ("^1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
785 caret_major_xrange: ("^1.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
786 caret_major_minor: ("^1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 2, 0, 0] )),
787 caret_major_minor_xrange: ("^1.2.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 2, 0, 0] )),
788 caret_major_minor_patch: ("^1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 2, 0, 0] )),
789 caret_major_minor_patch_pre: ("^1.2.3-beta.4", comp_sets!( [op!(">="), 1, 2, 3, pre!(id_alpha!("beta"), id_num!(4))], [op!("<"), 2, 0, 0, pre!()] )),
790
791 caret_major_0: ("^0", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 1, 0, 0] )),
792 caret_major_0_xrange: ("^0.x", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 1, 0, 0] )),
793 caret_major_0_minor_0: ("^0.0", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 0, 1, 0] )),
794 caret_major_0_minor_0_xrange: ("^0.0.x", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 0, 1, 0] )),
795 caret_major_0_minor: ("^0.1", comp_sets!( [op!(">="), 0, 1, 0], [op!("<"), 0, 2, 0] )),
796 caret_major_0_minor_xrange: ("^0.1.x", comp_sets!( [op!(">="), 0, 1, 0], [op!("<"), 0, 2, 0] )),
797 caret_major_0_minor_patch: ("^0.1.2", comp_sets!( [op!(">="), 0, 1, 2], [op!("<"), 0, 2, 0] )),
798 caret_major_0_minor_0_patch: ("^0.0.1", comp_sets!( [op!(">="), 0, 0, 1], [op!("<"), 0, 0, 2] )),
799 caret_major_0_minor_0_pre: ("^0.0.1-beta", comp_sets!( [op!(">="), 0, 0, 1, pre!(id_alpha!("beta"))], [op!("<"), 0, 0, 2, pre!()] )),
800 caret_all: ("^*", comp_sets!( [op!(">="), 0, 0, 0] )),
801
802 two_comparators_1: (">1.2.3 <4.5.6", comp_sets!( [op!(">"), 1, 2, 3], [op!("<"), 4, 5, 6] )),
803 two_comparators_2: ("^1.2 ^1", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 2, 0, 0], [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
804
805 comparator_with_pre: ("=1.2.3-rc.1", comp_sets!( [op!("="), 1, 2, 3, pre!(id_alpha!("rc"), id_num!(1))] )),
806
807 hyphen_major: ("1 - 4", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 5, 0, 0] )),
808 hyphen_major_x: ("1.* - 4.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 5, 0, 0] )),
809 hyphen_major_minor_x: ("1.2.x - 4.5.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 4, 6, 0] )),
810 hyphen_major_minor_patch: ("1.2.3 - 4.5.6", comp_sets!( [op!(">="), 1, 2, 3], [op!("<="), 4, 5, 6] )),
811 hyphen_with_pre: ("1.2.3-rc1 - 4.5.6", comp_sets!( [op!(">="), 1, 2, 3, pre!(id_alpha!("rc1"))], [op!("<="), 4, 5, 6, pre!()] )),
812 hyphen_xrange_minor_only1: ("1.*.3 - 3.4.5", comp_sets!( [op!(">="), 1, 0, 0], [op!("<="), 3, 4, 5] )),
813 hyphen_xrange_minor_only2: ("1.2.3 - 3.*.5", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 4, 0, 0] )),
814
815 hyphen_all_to_something: ("* - 3.4.5", comp_sets!( [op!("<="), 3, 4, 5] )),
816 hyphen_to_all: ("1.2.3 - *", comp_sets!( [op!(">="), 1, 2, 3] )),
817 hyphen_all_to_all: ("* - *", comp_sets!( [op!(">="), 0, 0, 0] )),
818
819 gte_space: (">= 1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )),
820 gte_tab: (">=\t1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )),
821 gte_two_spaces: (">= 1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )),
822 gt_space: ("> 1.2.3", comp_sets!( [op!(">"), 1, 2, 3] )),
823 gt_two_spaces: ("> 1.2.3", comp_sets!( [op!(">"), 1, 2, 3] )),
824 lte_space: ("<= 1.2.3", comp_sets!( [op!("<="), 1, 2, 3] )),
825 lte_two_spaces: ("<= 1.2.3", comp_sets!( [op!("<="), 1, 2, 3] )),
826 lt_space: ("< 1.2.3", comp_sets!( [op!("<"), 1, 2, 3] )),
827 lt_two_spaces: ("< 1.2.3", comp_sets!( [op!("<"), 1, 2, 3] )),
828 eq_space: ("= 1.2.3", comp_sets!( [op!("="), 1, 2, 3] )),
829 eq_two_spaces: ("= 1.2.3", comp_sets!( [op!("="), 1, 2, 3] )),
830 caret_space: ("^ 1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 2, 0, 0] )),
831 tilde_space: ("~ 1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 1, 3, 0] )),
832 hyphen_spacing: ("1.2.3 - 4.5.6", comp_sets!( [op!(">="), 1, 2, 3], [op!("<="), 4, 5, 6] )),
833
834 // digit options
835 digits: ("=0.2.3", comp_sets!( [op!("="), 0, 2, 3] )),
836 digits_2: ("=11.2.3", comp_sets!( [op!("="), 11, 2, 3] )),
837 digits_3: ("=1.12.3", comp_sets!( [op!("="), 1, 12, 3] )),
838 digits_4: ("=1.2.13", comp_sets!( [op!("="), 1, 2, 13] )),
839 digits_5: ("=1.2.5678", comp_sets!( [op!("="), 1, 2, 5678] )),
840
841 xrange_major_x: ("1.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
842 xrange_major_x_x: ("1.x.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
843 xrange_major_minor_x: ("1.2.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
844 xrange_major_xx: ("1.X", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
845 xrange_major_xx_xx: ("1.X.X", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
846 xrange_major_minor_xx: ("1.2.X", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
847 xrange_star: ("*", comp_sets!( [op!(">="), 0, 0, 0] )),
848 xrange_x: ("x", comp_sets!( [op!(">="), 0, 0, 0] )),
849 xrange_xx: ("X", comp_sets!( [op!(">="), 0, 0, 0] )),
850 xrange_major_star: ("1.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
851 xrange_major_star_star: ("1.*.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
852 xrange_major_minor_star: ("1.2.*", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )),
853 xrange_with_pre: ("1.*.*-beta", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
854 // this is handled as "1.*":
855 xrange_minor_only: ("1.*.3", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )),
856
857 // special cases
858 gte_star: (">=*", comp_sets!( [op!(">="), 0, 0, 0] )),
859 empty: ("", comp_sets!( [op!(">="), 0, 0, 0] )),
860 }
861
862 range_tests_nodecompat! {
863 node_major_minor_patch: ("1.2.3", comp_sets_node!( [op!("="), 1, 2, 3] )),
864 }
865 }
866