1use self::Op::{Compatible, Ex, Gt, GtEq, Lt, LtEq, Tilde, Wildcard};
12use self::WildcardVersion::{Minor, Patch};
13use errors::Error;
14use parser;
15#[cfg(feature = "serde")]
16use serde::de::{self, Deserialize, Deserializer, Visitor};
17#[cfg(feature = "serde")]
18use serde::ser::{Serialize, Serializer};
19use std::fmt;
20use std::str;
21use version::{Identifier, Version};
22
23#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
27pub struct Range {
28 pub predicates: Vec<Predicate>,
29}
30
31#[cfg(feature = "serde")]
32impl Serialize for Range {
33 fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
34 where
35 S: Serializer,
36 {
37 serializer.collect_str(self)
39 }
40}
41
42#[cfg(feature = "serde")]
43impl<'de> Deserialize<'de> for Range {
44 fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
45 where
46 D: Deserializer<'de>,
47 {
48 struct RangeVisitor;
49
50 impl<'de> Visitor<'de> for RangeVisitor {
52 type Value = Range;
53
54 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
55 formatter.write_str("a semver range without a string")
56 }
57
58 fn visit_str<E>(self, v: &str) -> ::std::result::Result<Self::Value, E>
59 where
60 E: de::Error,
61 {
62 Range::parse(v).map_err(de::Error::custom)
63 }
64 }
65
66 deserializer.deserialize_str(RangeVisitor)
67 }
68}
69
70#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
71pub enum WildcardVersion {
72 Minor,
73 Patch,
74}
75
76#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
77pub enum Op {
78 Ex, Gt, GtEq, Lt, LtEq, Tilde, Compatible, Wildcard(WildcardVersion), }
87
88#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
89pub struct Predicate {
90 pub op: Op,
91 pub major: u64,
92 pub minor: Option<u64>,
93 pub patch: Option<u64>,
94 pub pre: Vec<Identifier>,
95}
96
97impl Range {
98 pub fn any() -> Range {
109 Range { predicates: vec![] }
110 }
111
112 pub fn parse(input: &str) -> Result<Range, Error> {
143 let mut parser = parser::Parser::new(input)?;
144 let range = parser.range()?;
145
146 if !parser.is_eof() {
147 return Err(Error::MoreInput);
148 }
149
150 Ok(range)
151 }
152
153 pub fn exact(version: &Version) -> Range {
165 Range {
166 predicates: vec![Predicate::exact(version)],
167 }
168 }
169
170 pub fn matches(&self, version: &Version) -> bool {
184 if self.predicates.is_empty() {
186 return true;
187 }
188
189 self.predicates.iter().all(|p| p.matches(version))
190 && self.predicates
191 .iter()
192 .any(|p| p.pre_tag_is_compatible(version))
193 }
194
195 pub fn matches_any(&self) -> bool {
197 self.predicates.is_empty()
198 }
199}
200
201impl Predicate {
202 fn exact(version: &Version) -> Predicate {
203 Predicate {
204 op: Ex,
205 major: version.major,
206 minor: Some(version.minor),
207 patch: Some(version.patch),
208 pre: version.pre.clone(),
209 }
210 }
211
212 pub fn matches(&self, ver: &Version) -> bool {
214 match self.op {
215 Ex => self.is_exact(ver),
216 Gt => self.is_greater(ver),
217 GtEq => self.is_exact(ver) || self.is_greater(ver),
218 Lt => !self.is_exact(ver) && !self.is_greater(ver),
219 LtEq => !self.is_greater(ver),
220 Tilde => self.matches_tilde(ver),
221 Compatible => self.is_compatible(ver),
222 Wildcard(_) => self.matches_wildcard(ver),
223 }
224 }
225
226 fn is_exact(&self, ver: &Version) -> bool {
227 if self.major != ver.major {
228 return false;
229 }
230
231 match self.minor {
232 Some(minor) => {
233 if minor != ver.minor {
234 return false;
235 }
236 }
237 None => return true,
238 }
239
240 match self.patch {
241 Some(patch) => {
242 if patch != ver.patch {
243 return false;
244 }
245 }
246 None => return true,
247 }
248
249 if self.pre != ver.pre {
250 return false;
251 }
252
253 true
254 }
255
256 fn pre_tag_is_compatible(&self, ver: &Version) -> bool {
258 !ver.is_prerelease()
264 || (self.major == ver.major && self.minor == Some(ver.minor)
265 && self.patch == Some(ver.patch) && !self.pre.is_empty())
266 }
267
268 fn is_greater(&self, ver: &Version) -> bool {
269 if self.major != ver.major {
270 return ver.major > self.major;
271 }
272
273 match self.minor {
274 Some(minor) => {
275 if minor != ver.minor {
276 return ver.minor > minor;
277 }
278 }
279 None => return false,
280 }
281
282 match self.patch {
283 Some(patch) => {
284 if patch != ver.patch {
285 return ver.patch > patch;
286 }
287 }
288 None => return false,
289 }
290
291 if !self.pre.is_empty() {
292 return ver.pre.is_empty() || ver.pre > self.pre;
293 }
294
295 false
296 }
297
298 fn matches_tilde(&self, ver: &Version) -> bool {
300 let minor = match self.minor {
301 Some(n) => n,
302 None => return self.major == ver.major,
303 };
304
305 match self.patch {
306 Some(patch) => {
307 self.major == ver.major && minor == ver.minor
308 && (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver)))
309 }
310 None => self.major == ver.major && minor == ver.minor,
311 }
312 }
313
314 fn is_compatible(&self, ver: &Version) -> bool {
316 if self.major != ver.major {
317 return false;
318 }
319
320 let minor = match self.minor {
321 Some(n) => n,
322 None => return self.major == ver.major,
323 };
324
325 match self.patch {
326 Some(patch) => {
327 if self.major == 0 {
328 if minor == 0 {
329 ver.minor == minor && ver.patch == patch && self.pre_is_compatible(ver)
330 } else {
331 ver.minor == minor
332 && (ver.patch > patch
333 || (ver.patch == patch && self.pre_is_compatible(ver)))
334 }
335 } else {
336 ver.minor > minor
337 || (ver.minor == minor
338 && (ver.patch > patch
339 || (ver.patch == patch && self.pre_is_compatible(ver))))
340 }
341 }
342 None => {
343 if self.major == 0 {
344 ver.minor == minor
345 } else {
346 ver.minor >= minor
347 }
348 }
349 }
350 }
351
352 fn pre_is_compatible(&self, ver: &Version) -> bool {
353 ver.pre.is_empty() || ver.pre >= self.pre
354 }
355
356 fn matches_wildcard(&self, ver: &Version) -> bool {
358 match self.op {
359 Wildcard(Minor) => self.major == ver.major,
360 Wildcard(Patch) => {
361 match self.minor {
362 Some(minor) => self.major == ver.major && minor == ver.minor,
363 None => {
364 self.major == ver.major
366 }
367 }
368 }
369 _ => false, }
371 }
372}
373
374impl fmt::Display for Range {
375 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
376 if self.predicates.is_empty() {
377 try!(write!(fmt, "*"));
378 } else {
379 for (i, ref pred) in self.predicates.iter().enumerate() {
380 if i == 0 {
381 try!(write!(fmt, "{}", pred));
382 } else {
383 try!(write!(fmt, ", {}", pred));
384 }
385 }
386 }
387
388 Ok(())
389 }
390}
391
392impl fmt::Display for Predicate {
393 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
394 match self.op {
395 Wildcard(Minor) => try!(write!(fmt, "{}.*", self.major)),
396 Wildcard(Patch) => {
397 if let Some(minor) = self.minor {
398 try!(write!(fmt, "{}.{}.*", self.major, minor))
399 } else {
400 try!(write!(fmt, "{}.*.*", self.major))
401 }
402 }
403 _ => {
404 try!(write!(fmt, "{}{}", self.op, self.major));
405
406 match self.minor {
407 Some(v) => try!(write!(fmt, ".{}", v)),
408 None => (),
409 }
410
411 match self.patch {
412 Some(v) => try!(write!(fmt, ".{}", v)),
413 None => (),
414 }
415
416 if !self.pre.is_empty() {
417 try!(write!(fmt, "-"));
418 for (i, x) in self.pre.iter().enumerate() {
419 if i != 0 {
420 try!(write!(fmt, "."))
421 }
422 try!(write!(fmt, "{}", x));
423 }
424 }
425 }
426 }
427
428 Ok(())
429 }
430}
431
432impl fmt::Display for Op {
433 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
434 match *self {
435 Ex => try!(write!(fmt, "= ")),
436 Gt => try!(write!(fmt, "> ")),
437 GtEq => try!(write!(fmt, ">= ")),
438 Lt => try!(write!(fmt, "< ")),
439 LtEq => try!(write!(fmt, "<= ")),
440 Tilde => try!(write!(fmt, "~")),
441 Compatible => try!(write!(fmt, "^")),
442 Wildcard(_) => try!(write!(fmt, "")),
444 }
445 Ok(())
446 }
447}
448
449#[cfg(test)]
450mod test {
451 use super::super::version::Version;
452 use super::{Op, Range};
453 use std::hash::{Hash, Hasher};
454
455 fn range(s: &str) -> Range {
456 Range::parse(s).unwrap()
457 }
458
459 fn version(s: &str) -> Version {
460 match Version::parse(s) {
461 Ok(v) => v,
462 Err(e) => panic!("`{}` is not a valid version. Reason: {:?}", s, e),
463 }
464 }
465
466 fn assert_match(range: &Range, vers: &[&str]) {
467 for ver in vers.iter() {
468 assert!(range.matches(&version(*ver)), "did not match {}", ver);
469 }
470 }
471
472 fn assert_not_match(range: &Range, vers: &[&str]) {
473 for ver in vers.iter() {
474 assert!(!range.matches(&version(*ver)), "matched {}", ver);
475 }
476 }
477
478 fn calculate_hash<T: Hash>(t: T) -> u64 {
479 use std::collections::hash_map::DefaultHasher;
480
481 let mut s = DefaultHasher::new();
482 t.hash(&mut s);
483 s.finish()
484 }
485
486 #[test]
487 fn test_parsing_default() {
488 let r = range("1.0.0");
489
490 assert_eq!(r.to_string(), "^1.0.0".to_string());
491
492 assert_match(&r, &["1.0.0", "1.0.1"]);
493 assert_not_match(&r, &["0.9.9", "0.10.0", "0.1.0"]);
494 }
495
496 #[test]
497 fn test_parsing_exact() {
498 let r = range("=1.0.0");
499
500 assert!(r.to_string() == "= 1.0.0".to_string());
501 assert_eq!(r.to_string(), "= 1.0.0".to_string());
502
503 assert_match(&r, &["1.0.0"]);
504 assert_not_match(&r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]);
505
506 let r = range("=0.9.0");
507
508 assert_eq!(r.to_string(), "= 0.9.0".to_string());
509
510 assert_match(&r, &["0.9.0"]);
511 assert_not_match(&r, &["0.9.1", "1.9.0", "0.0.9"]);
512
513 let r = range("=0.1.0-beta2.a");
514
515 assert_eq!(r.to_string(), "= 0.1.0-beta2.a".to_string());
516
517 assert_match(&r, &["0.1.0-beta2.a"]);
518 assert_not_match(&r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]);
519 }
520
521 #[test]
522 fn test_parse_metadata_see_issue_88_see_issue_88() {
523 for op in &[
524 Op::Compatible,
525 Op::Ex,
526 Op::Gt,
527 Op::GtEq,
528 Op::Lt,
529 Op::LtEq,
530 Op::Tilde,
531 ] {
532 range(&format!("{} 1.2.3+meta", op));
533 }
534 }
535
536 #[test]
537 pub fn test_parsing_greater_than() {
538 let r = range(">= 1.0.0");
539
540 assert_eq!(r.to_string(), ">= 1.0.0".to_string());
541
542 assert_match(&r, &["1.0.0", "2.0.0"]);
543 assert_not_match(&r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]);
544
545 let r = range(">= 2.1.0-alpha2");
546
547 assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]);
548 assert_not_match(
549 &r,
550 &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"],
551 );
552 }
553
554 #[test]
555 pub fn test_parsing_less_than() {
556 let r = range("< 1.0.0");
557
558 assert_eq!(r.to_string(), "< 1.0.0".to_string());
559
560 assert_match(&r, &["0.1.0", "0.0.1"]);
561 assert_not_match(&r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]);
562
563 let r = range("<= 2.1.0-alpha2");
564
565 assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]);
566 assert_not_match(
567 &r,
568 &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"],
569 );
570 }
571
572 #[test]
573 pub fn test_multiple() {
574 let r = range("> 0.0.9, <= 2.5.3");
575 assert_eq!(r.to_string(), "> 0.0.9, <= 2.5.3".to_string());
576 assert_match(&r, &["0.0.10", "1.0.0", "2.5.3"]);
577 assert_not_match(&r, &["0.0.8", "2.5.4"]);
578
579 let r = range("0.3.0, 0.4.0");
580 assert_eq!(r.to_string(), "^0.3.0, ^0.4.0".to_string());
581 assert_not_match(&r, &["0.0.8", "0.3.0", "0.4.0"]);
582
583 let r = range("<= 0.2.0, >= 0.5.0");
584 assert_eq!(r.to_string(), "<= 0.2.0, >= 0.5.0".to_string());
585 assert_not_match(&r, &["0.0.8", "0.3.0", "0.5.1"]);
586
587 let r = range("0.1.0, 0.1.4, 0.1.6");
588 assert_eq!(r.to_string(), "^0.1.0, ^0.1.4, ^0.1.6".to_string());
589 assert_match(&r, &["0.1.6", "0.1.9"]);
590 assert_not_match(&r, &["0.1.0", "0.1.4", "0.2.0"]);
591
592 assert!(Range::parse("> 0.1.0,").is_err());
593 assert!(Range::parse("> 0.3.0, ,").is_err());
594
595 let r = range(">=0.5.1-alpha3, <0.6");
596 assert_eq!(r.to_string(), ">= 0.5.1-alpha3, < 0.6".to_string());
597 assert_match(
598 &r,
599 &[
600 "0.5.1-alpha3",
601 "0.5.1-alpha4",
602 "0.5.1-beta",
603 "0.5.1",
604 "0.5.5",
605 ],
606 );
607 assert_not_match(
608 &r,
609 &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"],
610 );
611 assert_not_match(&r, &["0.6.0", "0.6.0-pre"]);
612 }
613
614 #[test]
615 pub fn test_parsing_tilde() {
616 let r = range("~1");
617 assert_match(&r, &["1.0.0", "1.0.1", "1.1.1"]);
618 assert_not_match(&r, &["0.9.1", "2.9.0", "0.0.9"]);
619
620 let r = range("~1.2");
621 assert_match(&r, &["1.2.0", "1.2.1"]);
622 assert_not_match(&r, &["1.1.1", "1.3.0", "0.0.9"]);
623
624 let r = range("~1.2.2");
625 assert_match(&r, &["1.2.2", "1.2.4"]);
626 assert_not_match(&r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]);
627
628 let r = range("~1.2.3-beta.2");
629 assert_match(&r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]);
630 assert_not_match(&r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]);
631 }
632
633 #[test]
634 pub fn test_parsing_compatible() {
635 let r = range("^1");
636 assert_match(&r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]);
637 assert_not_match(&r, &["0.9.1", "2.9.0", "0.1.4"]);
638 assert_not_match(&r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]);
639
640 let r = range("^1.1");
641 assert_match(&r, &["1.1.2", "1.1.0", "1.2.1"]);
642 assert_not_match(&r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]);
643
644 let r = range("^1.1.2");
645 assert_match(&r, &["1.1.2", "1.1.4", "1.2.1"]);
646 assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);
647 assert_not_match(&r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]);
648
649 let r = range("^0.1.2");
650 assert_match(&r, &["0.1.2", "0.1.4"]);
651 assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);
652 assert_not_match(&r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]);
653
654 let r = range("^0.5.1-alpha3");
655 assert_match(
656 &r,
657 &[
658 "0.5.1-alpha3",
659 "0.5.1-alpha4",
660 "0.5.1-beta",
661 "0.5.1",
662 "0.5.5",
663 ],
664 );
665 assert_not_match(
666 &r,
667 &[
668 "0.5.1-alpha1",
669 "0.5.2-alpha3",
670 "0.5.5-pre",
671 "0.5.0-pre",
672 "0.6.0",
673 ],
674 );
675
676 let r = range("^0.0.2");
677 assert_match(&r, &["0.0.2"]);
678 assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]);
679
680 let r = range("^0.0");
681 assert_match(&r, &["0.0.2", "0.0.0"]);
682 assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]);
683
684 let r = range("^0");
685 assert_match(&r, &["0.9.1", "0.0.2", "0.0.0"]);
686 assert_not_match(&r, &["2.9.0", "1.1.1"]);
687
688 let r = range("^1.4.2-beta.5");
689 assert_match(
690 &r,
691 &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"],
692 );
693 assert_not_match(
694 &r,
695 &[
696 "0.9.9",
697 "2.0.0",
698 "1.4.2-alpha",
699 "1.4.2-beta.4",
700 "1.4.3-beta.5",
701 ],
702 );
703 }
704
705 #[test]
706 pub fn test_parsing_wildcard() {
707 let r = range("");
708 assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);
709 assert_not_match(&r, &[]);
710 let r = range("*");
711 assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);
712 assert_not_match(&r, &[]);
713 let r = range("x");
714 assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);
715 assert_not_match(&r, &[]);
716 let r = range("X");
717 assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);
718 assert_not_match(&r, &[]);
719
720 let r = range("1.*");
721 assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);
722 assert_not_match(&r, &["0.0.9"]);
723 let r = range("1.x");
724 assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);
725 assert_not_match(&r, &["0.0.9"]);
726 let r = range("1.X");
727 assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);
728 assert_not_match(&r, &["0.0.9"]);
729
730 let r = range("1.2.*");
731 assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);
732 assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);
733 let r = range("1.2.x");
734 assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);
735 assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);
736 let r = range("1.2.X");
737 assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);
738 assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);
739 }
740
741 #[test]
742 pub fn test_any() {
743 let r = Range::any();
744 assert_match(&r, &["0.0.1", "0.1.0", "1.0.0"]);
745 }
746
747 #[test]
748 pub fn test_pre() {
749 let r = range("=2.1.1-really.0");
750 assert_match(&r, &["2.1.1-really.0"]);
751 }
752
753 #[test]
754 pub fn test_from_str() {
755 assert_eq!(
756 Range::parse("1.0.0").unwrap().to_string(),
757 "^1.0.0".to_string()
758 );
759 assert_eq!(
760 Range::parse("=1.0.0").unwrap().to_string(),
761 "= 1.0.0".to_string()
762 );
763 assert_eq!(Range::parse("~1").unwrap().to_string(), "~1".to_string());
764 assert_eq!(
765 Range::parse("~1.2").unwrap().to_string(),
766 "~1.2".to_string()
767 );
768 assert_eq!(Range::parse("^1").unwrap().to_string(), "^1".to_string());
769 assert_eq!(
770 Range::parse("^1.1").unwrap().to_string(),
771 "^1.1".to_string()
772 );
773 assert_eq!(Range::parse("*").unwrap().to_string(), "*".to_string());
774 assert_eq!(Range::parse("1.*").unwrap().to_string(), "1.*".to_string());
775 assert_eq!(
776 Range::parse("< 1.0.0").unwrap().to_string(),
777 "< 1.0.0".to_string()
778 );
779 }
780
781 #[test]
782 fn test_cargo3202() {
783 let v = Range::parse("0.*.*").unwrap();
784 assert_eq!("0.*.*", format!("{}", v.predicates[0]));
785
786 let v = Range::parse("0.0.*").unwrap();
787 assert_eq!("0.0.*", format!("{}", v.predicates[0]));
788
789 let r = range("0.*.*");
790 assert_match(&r, &["0.5.0"]);
791 }
792
793 #[test]
794 fn test_eq_hash() {
795 assert!(range("^1") == range("^1"));
796 assert!(calculate_hash(range("^1")) == calculate_hash(range("^1")));
797 assert!(range("^1") != range("^2"));
798 }
799
800 #[test]
801 fn test_ordering() {
802 assert!(range("=1") > range("*"));
803 assert!(range(">1") > range("*"));
804 assert!(range(">=1") > range("*"));
805 assert!(range("<1") > range("*"));
806 assert!(range("<=1") > range("*"));
807 assert!(range("~1") > range("*"));
808 assert!(range("^1") > range("*"));
809 assert!(range("*") == range("*"));
810 }
811}