]> git.proxmox.com Git - rustc.git/blobdiff - vendor/semver/src/version_req.rs
Update upstream source from tag 'upstream/1.52.1+dfsg1'
[rustc.git] / vendor / semver / src / version_req.rs
diff --git a/vendor/semver/src/version_req.rs b/vendor/semver/src/version_req.rs
new file mode 100644 (file)
index 0000000..1db109b
--- /dev/null
@@ -0,0 +1,1092 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT\r
+// file at the top-level directory of this distribution and at\r
+// http://rust-lang.org/COPYRIGHT.\r
+//\r
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\r
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\r
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\r
+// option. This file may not be copied, modified, or distributed\r
+// except according to those terms.\r
+\r
+use std::error::Error;\r
+use std::fmt;\r
+use std::str;\r
+\r
+use semver_parser;\r
+use semver_parser::{Compat, RangeSet};\r
+use version::Identifier;\r
+use Version;\r
+\r
+#[cfg(feature = "serde")]\r
+use serde::de::{self, Deserialize, Deserializer, Visitor};\r
+#[cfg(feature = "serde")]\r
+use serde::ser::{Serialize, Serializer};\r
+\r
+use self::Op::{Ex, Gt, GtEq, Lt, LtEq};\r
+use self::ReqParseError::*;\r
+\r
+/// A `VersionReq` is a struct containing a list of ranges that can apply to ranges of version\r
+/// numbers. Matching operations can then be done with the `VersionReq` against a particular\r
+/// version to see if it satisfies some or all of the constraints.\r
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
+#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]\r
+#[cfg_attr(feature = "diesel", sql_type = "diesel::sql_types::Text")]\r
+pub struct VersionReq {\r
+    ranges: Vec<Range>,\r
+    compat: Compat, // defaults to Cargo\r
+}\r
+\r
+impl From<semver_parser::RangeSet> for VersionReq {\r
+    fn from(range_set: semver_parser::RangeSet) -> VersionReq {\r
+        VersionReq {\r
+            ranges: range_set.ranges.into_iter().map(From::from).collect(),\r
+            compat: range_set.compat,\r
+        }\r
+    }\r
+}\r
+\r
+#[cfg(feature = "serde")]\r
+impl Serialize for VersionReq {\r
+    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>\r
+    where\r
+        S: Serializer,\r
+    {\r
+        // Serialize VersionReq as a string.\r
+        serializer.collect_str(self)\r
+    }\r
+}\r
+\r
+// TODO: how to implement deserialize with compatibility?\r
+#[cfg(feature = "serde")]\r
+impl<'de> Deserialize<'de> for VersionReq {\r
+    fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>\r
+    where\r
+        D: Deserializer<'de>,\r
+    {\r
+        struct VersionReqVisitor;\r
+\r
+        /// Deserialize `VersionReq` from a string.\r
+        impl<'de> Visitor<'de> for VersionReqVisitor {\r
+            type Value = VersionReq;\r
+\r
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\r
+                formatter.write_str("a SemVer version requirement as a string")\r
+            }\r
+\r
+            fn visit_str<E>(self, v: &str) -> ::std::result::Result<Self::Value, E>\r
+            where\r
+                E: de::Error,\r
+            {\r
+                VersionReq::parse(v).map_err(de::Error::custom)\r
+            }\r
+        }\r
+\r
+        deserializer.deserialize_str(VersionReqVisitor)\r
+    }\r
+}\r
+\r
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
+enum Op {\r
+    Ex,   // Exact\r
+    Gt,   // Greater than\r
+    GtEq, // Greater than or equal to\r
+    Lt,   // Less than\r
+    LtEq, // Less than or equal to\r
+}\r
+\r
+impl From<semver_parser::Op> for Op {\r
+    fn from(op: semver_parser::Op) -> Op {\r
+        match op {\r
+            semver_parser::Op::Eq => Op::Ex,\r
+            semver_parser::Op::Gt => Op::Gt,\r
+            semver_parser::Op::Gte => Op::GtEq,\r
+            semver_parser::Op::Lt => Op::Lt,\r
+            semver_parser::Op::Lte => Op::LtEq,\r
+        }\r
+    }\r
+}\r
+\r
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
+struct Range {\r
+    predicates: Vec<Predicate>,\r
+    compat: Compat,\r
+}\r
+\r
+impl From<semver_parser::Range> for Range {\r
+    fn from(range: semver_parser::Range) -> Range {\r
+        Range {\r
+            predicates: range.comparator_set.into_iter().map(From::from).collect(),\r
+            compat: range.compat,\r
+        }\r
+    }\r
+}\r
+\r
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]\r
+struct Predicate {\r
+    op: Op,\r
+    major: u64,\r
+    minor: u64,\r
+    patch: u64,\r
+    pre: Vec<Identifier>,\r
+}\r
+\r
+impl From<semver_parser::Comparator> for Predicate {\r
+    fn from(comparator: semver_parser::Comparator) -> Predicate {\r
+        Predicate {\r
+            op: From::from(comparator.op),\r
+            major: comparator.major,\r
+            minor: comparator.minor,\r
+            patch: comparator.patch,\r
+            pre: comparator.pre.into_iter().map(From::from).collect(),\r
+        }\r
+    }\r
+}\r
+\r
+impl From<semver_parser::Identifier> for Identifier {\r
+    fn from(identifier: semver_parser::Identifier) -> Identifier {\r
+        match identifier {\r
+            semver_parser::Identifier::Numeric(n) => Identifier::Numeric(n),\r
+            semver_parser::Identifier::AlphaNumeric(s) => Identifier::AlphaNumeric(s),\r
+        }\r
+    }\r
+}\r
+\r
+/// A `ReqParseError` is returned from methods which parse a string into a [`VersionReq`]. Each\r
+/// enumeration is one of the possible errors that can occur.\r
+/// [`VersionReq`]: struct.VersionReq.html\r
+#[derive(Clone, Debug, PartialEq)]\r
+pub enum ReqParseError {\r
+    /// The given version requirement is invalid.\r
+    InvalidVersionRequirement,\r
+    /// You have already provided an operation, such as `=`, `~`, or `^`. Only use one.\r
+    OpAlreadySet,\r
+    /// The sigil you have written is not correct.\r
+    InvalidSigil,\r
+    /// All components of a version must be numeric.\r
+    VersionComponentsMustBeNumeric,\r
+    /// There was an error parsing an identifier.\r
+    InvalidIdentifier,\r
+    /// At least a major version is required.\r
+    MajorVersionRequired,\r
+    /// An unimplemented version requirement.\r
+    UnimplementedVersionRequirement,\r
+    /// This form of requirement is deprecated.\r
+    DeprecatedVersionRequirement(VersionReq),\r
+}\r
+\r
+impl fmt::Display for ReqParseError {\r
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r
+        let msg = match self {\r
+            InvalidVersionRequirement => "the given version requirement is invalid",\r
+            OpAlreadySet => {\r
+                "you have already provided an operation, such as =, ~, or ^; only use one"\r
+            }\r
+            InvalidSigil => "the sigil you have written is not correct",\r
+            VersionComponentsMustBeNumeric => "version components must be numeric",\r
+            InvalidIdentifier => "invalid identifier",\r
+            MajorVersionRequired => "at least a major version number is required",\r
+            UnimplementedVersionRequirement => {\r
+                "the given version requirement is not implemented, yet"\r
+            }\r
+            DeprecatedVersionRequirement(_) => "This requirement is deprecated",\r
+        };\r
+        msg.fmt(f)\r
+    }\r
+}\r
+\r
+impl Error for ReqParseError {}\r
+\r
+impl From<String> for ReqParseError {\r
+    fn from(other: String) -> ReqParseError {\r
+        match &*other {\r
+            "Null is not a valid VersionReq" => ReqParseError::InvalidVersionRequirement,\r
+            "VersionReq did not parse properly." => ReqParseError::OpAlreadySet,\r
+            _ => ReqParseError::InvalidVersionRequirement,\r
+        }\r
+    }\r
+}\r
+\r
+impl VersionReq {\r
+    /// `any()` is a factory method which creates a `VersionReq` with no constraints. In other\r
+    /// words, any version will match against it.\r
+    ///\r
+    /// # Examples\r
+    ///\r
+    /// ```\r
+    /// use semver::VersionReq;\r
+    ///\r
+    /// let anything = VersionReq::any();\r
+    /// ```\r
+    pub fn any() -> VersionReq {\r
+        VersionReq {\r
+            ranges: vec![],\r
+            compat: Compat::Cargo,\r
+        }\r
+    }\r
+\r
+    /// `parse()` is the main constructor of a `VersionReq`. It takes a string like `"^1.2.3"`\r
+    /// and turns it into a `VersionReq` that matches that particular constraint.\r
+    ///\r
+    /// A `Result` is returned which contains a [`ReqParseError`] if there was a problem parsing the\r
+    /// `VersionReq`.\r
+    /// [`ReqParseError`]: enum.ReqParseError.html\r
+    ///\r
+    /// # Examples\r
+    ///\r
+    /// ```\r
+    /// use semver::VersionReq;\r
+    ///\r
+    /// let version = VersionReq::parse("=1.2.3");\r
+    /// let version = VersionReq::parse(">1.2.3");\r
+    /// let version = VersionReq::parse("<1.2.3");\r
+    /// let version = VersionReq::parse("~1.2.3");\r
+    /// let version = VersionReq::parse("^1.2.3");\r
+    /// let version = VersionReq::parse("1.2.3"); // synonym for ^1.2.3\r
+    /// let version = VersionReq::parse("<=1.2.3");\r
+    /// let version = VersionReq::parse(">=1.2.3");\r
+    /// ```\r
+    ///\r
+    /// This example demonstrates error handling, and will panic.\r
+    ///\r
+    /// ```should_panic\r
+    /// use semver::VersionReq;\r
+    ///\r
+    /// let version = match VersionReq::parse("not a version") {\r
+    ///     Ok(version) => version,\r
+    ///     Err(e) => panic!("There was a problem parsing: {}", e),\r
+    /// };\r
+    /// ```\r
+    ///\r
+    /// # Errors\r
+    ///\r
+    /// Returns an error variant if the input could not be parsed as a semver requirement.\r
+    ///\r
+    /// Examples of common error causes are as follows:\r
+    ///\r
+    /// * `\0` - an invalid version requirement is used.\r
+    /// * `>= >= 1.2.3` - multiple operations are used. Only use one.\r
+    /// * `>== 1.2.3` - an invalid operation is used.\r
+    /// * `a.0.0` - version components are not numeric.\r
+    /// * `1.2.3-` - an invalid identifier is present.\r
+    /// * `>=` - major version was not specified. At least a major version is required.\r
+    /// * `0.2*` - deprecated requirement syntax. Equivalent would be `0.2.*`.\r
+    ///\r
+    /// You may also encounter an `UnimplementedVersionRequirement` error, which indicates that a\r
+    /// given requirement syntax is not yet implemented in this crate.\r
+    pub fn parse(input: &str) -> Result<VersionReq, ReqParseError> {\r
+        let range_set = input.parse::<RangeSet>();\r
+\r
+        if let Ok(v) = range_set {\r
+            return Ok(From::from(v));\r
+        }\r
+\r
+        match VersionReq::parse_deprecated(input) {\r
+            Some(v) => Err(ReqParseError::DeprecatedVersionRequirement(v)),\r
+            None => Err(From::from(range_set.err().unwrap())),\r
+        }\r
+    }\r
+\r
+    // TODO: better docs for this\r
+    /// `parse_compat()` is like `parse()`, but it takes an extra argument for compatibility with\r
+    /// other semver implementations, and turns that into a `VersionReq` that matches the\r
+    /// particular constraint and compatibility.\r
+    ///\r
+    /// A `Result` is returned which contains a [`ReqParseError`] if there was a problem parsing the\r
+    /// `VersionReq`.\r
+    /// [`ReqParseError`]: enum.ReqParseError.html\r
+    ///\r
+    /// # Examples\r
+    ///\r
+    /// ```\r
+    /// extern crate semver_parser;\r
+    /// use semver::VersionReq;\r
+    /// use semver_parser::Compat;\r
+    ///\r
+    /// # fn main() {\r
+    ///     let cargo_version = VersionReq::parse_compat("1.2.3", Compat::Cargo);\r
+    ///     let npm_version = VersionReq::parse_compat("1.2.3", Compat::Npm);\r
+    /// # }\r
+    /// ```\r
+    pub fn parse_compat(input: &str, compat: Compat) -> Result<VersionReq, ReqParseError> {\r
+        let range_set = RangeSet::parse(input, compat);\r
+\r
+        if let Ok(v) = range_set {\r
+            return Ok(From::from(v));\r
+        }\r
+\r
+        match VersionReq::parse_deprecated(input) {\r
+            Some(v) => Err(ReqParseError::DeprecatedVersionRequirement(v)),\r
+            None => Err(From::from(range_set.err().unwrap())),\r
+        }\r
+    }\r
+\r
+    fn parse_deprecated(version: &str) -> Option<VersionReq> {\r
+        match version {\r
+            ".*" => Some(VersionReq::any()),\r
+            "0.1.0." => Some(VersionReq::parse("0.1.0").unwrap()),\r
+            "0.3.1.3" => Some(VersionReq::parse("0.3.13").unwrap()),\r
+            "0.2*" => Some(VersionReq::parse("0.2.*").unwrap()),\r
+            "*.0" => Some(VersionReq::any()),\r
+            _ => None,\r
+        }\r
+    }\r
+\r
+    /// `exact()` is a factory method which creates a `VersionReq` with one exact constraint.\r
+    ///\r
+    /// # Examples\r
+    ///\r
+    /// ```\r
+    /// use semver::VersionReq;\r
+    /// use semver::Version;\r
+    ///\r
+    /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] };\r
+    /// let exact = VersionReq::exact(&version);\r
+    /// ```\r
+    pub fn exact(version: &Version) -> VersionReq {\r
+        VersionReq {\r
+            ranges: vec![Range {\r
+                predicates: vec![Predicate::exact(version)],\r
+                compat: Compat::Cargo,\r
+            }],\r
+            compat: Compat::Cargo,\r
+        }\r
+    }\r
+\r
+    /// `matches()` matches a given [`Version`] against this `VersionReq`.\r
+    /// [`Version`]: struct.Version.html\r
+    ///\r
+    /// # Examples\r
+    ///\r
+    /// ```\r
+    /// use semver::VersionReq;\r
+    /// use semver::Version;\r
+    ///\r
+    /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] };\r
+    /// let exact = VersionReq::exact(&version);\r
+    ///\r
+    /// assert!(exact.matches(&version));\r
+    /// ```\r
+    pub fn matches(&self, version: &Version) -> bool {\r
+        // no ranges means anything matches\r
+        if self.ranges.is_empty() {\r
+            return true;\r
+        }\r
+\r
+        self.ranges\r
+            .iter()\r
+            .any(|r| r.matches(version) && r.pre_tag_is_compatible(version))\r
+    }\r
+\r
+    /// `is_exact()` returns `true` if there is exactly one version which could match this\r
+    /// `VersionReq`. If `false` is returned, it is possible that there may still only be exactly\r
+    /// one version which could match this `VersionReq`. This function is intended do allow\r
+    /// short-circuiting more complex logic where being able to handle only the possibility of a\r
+    /// single exact version may be cheaper.\r
+    ///\r
+    /// # Examples\r
+    ///\r
+    /// ```\r
+    /// use semver::ReqParseError;\r
+    /// use semver::VersionReq;\r
+    ///\r
+    /// fn use_is_exact() -> Result<(), ReqParseError> {\r
+    ///   assert!(VersionReq::parse("=1.0.0")?.is_exact());\r
+    ///   assert!(!VersionReq::parse("=1.0")?.is_exact());\r
+    ///   assert!(!VersionReq::parse(">=1.0.0")?.is_exact());\r
+    ///   Ok(())\r
+    /// }\r
+    ///\r
+    /// use_is_exact().unwrap();\r
+    /// ```\r
+    pub fn is_exact(&self) -> bool {\r
+        if let [range] = self.ranges.as_slice() {\r
+            if let [predicate] = range.predicates.as_slice() {\r
+                return predicate.has_exactly_one_match();\r
+            }\r
+        }\r
+\r
+        false\r
+    }\r
+}\r
+\r
+impl str::FromStr for VersionReq {\r
+    type Err = ReqParseError;\r
+\r
+    fn from_str(s: &str) -> Result<VersionReq, ReqParseError> {\r
+        VersionReq::parse(s)\r
+    }\r
+}\r
+\r
+impl Range {\r
+    fn matches(&self, ver: &Version) -> bool {\r
+        self.predicates.iter().all(|p| p.matches(ver))\r
+    }\r
+\r
+    fn pre_tag_is_compatible(&self, ver: &Version) -> bool {\r
+        self.predicates.iter().any(|p| p.pre_tag_is_compatible(ver))\r
+    }\r
+}\r
+\r
+impl Predicate {\r
+    fn exact(version: &Version) -> Predicate {\r
+        Predicate {\r
+            op: Ex,\r
+            major: version.major,\r
+            minor: version.minor,\r
+            patch: version.patch,\r
+            pre: version.pre.clone(),\r
+        }\r
+    }\r
+\r
+    /// `matches()` takes a `Version` and determines if it matches this particular `Predicate`.\r
+    pub fn matches(&self, ver: &Version) -> bool {\r
+        match self.op {\r
+            Ex => self.matches_exact(ver),\r
+            Gt => self.matches_greater(ver),\r
+            GtEq => self.matches_exact(ver) || self.matches_greater(ver),\r
+            Lt => !self.matches_exact(ver) && !self.matches_greater(ver),\r
+            LtEq => !self.matches_greater(ver),\r
+        }\r
+    }\r
+\r
+    fn matches_exact(&self, ver: &Version) -> bool {\r
+        self.major == ver.major\r
+            && self.minor == ver.minor\r
+            && self.patch == ver.patch\r
+            && self.pre == ver.pre\r
+    }\r
+\r
+    // https://docs.npmjs.com/misc/semver#prerelease-tags\r
+    fn pre_tag_is_compatible(&self, ver: &Version) -> bool {\r
+        // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it will\r
+        // only be\r
+        // allowed to satisfy comparator sets if at least one comparator with the same\r
+        // [major,\r
+        // minor, patch] tuple also has a prerelease tag.\r
+        !ver.is_prerelease()\r
+            || (self.major == ver.major\r
+                && self.minor == ver.minor\r
+                && self.patch == ver.patch\r
+                && !self.pre.is_empty())\r
+    }\r
+\r
+    fn matches_greater(&self, ver: &Version) -> bool {\r
+        if self.major != ver.major {\r
+            return ver.major > self.major;\r
+        }\r
+\r
+        if self.minor != ver.minor {\r
+            return ver.minor > self.minor;\r
+        }\r
+\r
+        if self.patch != ver.patch {\r
+            return ver.patch > self.patch;\r
+        }\r
+\r
+        if !self.pre.is_empty() {\r
+            return ver.pre.is_empty() || ver.pre > self.pre;\r
+        }\r
+\r
+        false\r
+    }\r
+\r
+    fn has_exactly_one_match(&self) -> bool {\r
+        self.op == Ex\r
+    }\r
+}\r
+\r
+impl fmt::Display for VersionReq {\r
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
+        if self.ranges.is_empty() {\r
+            write!(fmt, "*")?;\r
+        } else {\r
+            for (i, ref pred) in self.ranges.iter().enumerate() {\r
+                if i == 0 {\r
+                    write!(fmt, "{}", pred)?;\r
+                } else {\r
+                    write!(fmt, " || {}", pred)?;\r
+                }\r
+            }\r
+        }\r
+\r
+        Ok(())\r
+    }\r
+}\r
+\r
+impl fmt::Display for Range {\r
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
+        for (i, ref pred) in self.predicates.iter().enumerate() {\r
+            if i == 0 {\r
+                write!(fmt, "{}", pred)?;\r
+            } else if self.compat == Compat::Npm {\r
+                // Node does not expect commas between predicates\r
+                write!(fmt, " {}", pred)?;\r
+            } else {\r
+                write!(fmt, ", {}", pred)?;\r
+            }\r
+        }\r
+        Ok(())\r
+    }\r
+}\r
+\r
+impl fmt::Display for Predicate {\r
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
+        write!(\r
+            fmt,\r
+            "{}{}.{}.{}",\r
+            self.op, self.major, self.minor, self.patch\r
+        )?;\r
+\r
+        if !self.pre.is_empty() {\r
+            write!(fmt, "-")?;\r
+            for (i, x) in self.pre.iter().enumerate() {\r
+                if i != 0 {\r
+                    write!(fmt, ".")?\r
+                }\r
+                write!(fmt, "{}", x)?;\r
+            }\r
+        }\r
+\r
+        Ok(())\r
+    }\r
+}\r
+\r
+impl fmt::Display for Op {\r
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
+        match *self {\r
+            Ex => write!(fmt, "=")?,\r
+            Gt => write!(fmt, ">")?,\r
+            GtEq => write!(fmt, ">=")?,\r
+            Lt => write!(fmt, "<")?,\r
+            LtEq => write!(fmt, "<=")?,\r
+        }\r
+        Ok(())\r
+    }\r
+}\r
+\r
+#[cfg(test)]\r
+mod test {\r
+    use super::super::version::Version;\r
+    use super::{Compat, Op, VersionReq};\r
+    use std::hash::{Hash, Hasher};\r
+\r
+    fn req(s: &str) -> VersionReq {\r
+        VersionReq::parse(s).unwrap()\r
+    }\r
+\r
+    fn req_npm(s: &str) -> VersionReq {\r
+        VersionReq::parse_compat(s, Compat::Npm).unwrap()\r
+    }\r
+\r
+    fn version(s: &str) -> Version {\r
+        match Version::parse(s) {\r
+            Ok(v) => v,\r
+            Err(e) => panic!("`{}` is not a valid version. Reason: {:?}", s, e),\r
+        }\r
+    }\r
+\r
+    fn assert_match(req: &VersionReq, vers: &[&str]) {\r
+        for ver in vers.iter() {\r
+            assert!(req.matches(&version(*ver)), "did not match {}", ver);\r
+        }\r
+    }\r
+\r
+    fn assert_not_match(req: &VersionReq, vers: &[&str]) {\r
+        for ver in vers.iter() {\r
+            assert!(!req.matches(&version(*ver)), "matched {}", ver);\r
+        }\r
+    }\r
+\r
+    fn calculate_hash<T: Hash>(t: T) -> u64 {\r
+        use std::collections::hash_map::DefaultHasher;\r
+\r
+        let mut s = DefaultHasher::new();\r
+        t.hash(&mut s);\r
+        s.finish()\r
+    }\r
+\r
+    #[test]\r
+    fn test_parsing_default() {\r
+        let r = req("1.0.0");\r
+\r
+        assert_eq!(r.to_string(), ">=1.0.0, <2.0.0".to_string());\r
+\r
+        assert_match(&r, &["1.0.0", "1.0.1"]);\r
+        assert_not_match(&r, &["0.9.9", "0.10.0", "0.1.0"]);\r
+    }\r
+\r
+    #[test]\r
+    fn test_parsing_default_npm() {\r
+        let r = req_npm("1.0.0");\r
+\r
+        assert_eq!(r.to_string(), "=1.0.0".to_string());\r
+\r
+        assert_match(&r, &["1.0.0"]);\r
+        assert_not_match(&r, &["0.9.9", "0.10.0", "0.1.0", "1.0.1"]);\r
+    }\r
+\r
+    #[test]\r
+    fn test_parsing_exact() {\r
+        let r = req("=1.0.0");\r
+\r
+        assert!(r.to_string() == "=1.0.0".to_string());\r
+        assert_eq!(r.to_string(), "=1.0.0".to_string());\r
+\r
+        assert_match(&r, &["1.0.0"]);\r
+        assert_not_match(&r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]);\r
+\r
+        let r = req("=0.9.0");\r
+\r
+        assert_eq!(r.to_string(), "=0.9.0".to_string());\r
+\r
+        assert_match(&r, &["0.9.0"]);\r
+        assert_not_match(&r, &["0.9.1", "1.9.0", "0.0.9"]);\r
+\r
+        let r = req("=0.1.0-beta2.a");\r
+\r
+        assert_eq!(r.to_string(), "=0.1.0-beta2.a".to_string());\r
+\r
+        assert_match(&r, &["0.1.0-beta2.a"]);\r
+        assert_not_match(&r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]);\r
+    }\r
+\r
+    #[test]\r
+    fn test_parse_metadata_see_issue_88_see_issue_88() {\r
+        for op in &[Op::Ex, Op::Gt, Op::GtEq, Op::Lt, Op::LtEq] {\r
+            println!("{} 1.2.3+meta", op);\r
+            req(&format!("{} 1.2.3+meta", op));\r
+        }\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_parsing_greater_than() {\r
+        let r = req(">= 1.0.0");\r
+\r
+        assert_eq!(r.to_string(), ">=1.0.0".to_string());\r
+\r
+        assert_match(&r, &["1.0.0", "2.0.0"]);\r
+        assert_not_match(&r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]);\r
+\r
+        // https://github.com/steveklabnik/semver/issues/53\r
+        let r = req(">= 2.1.0-alpha2");\r
+\r
+        assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]);\r
+        assert_not_match(\r
+            &r,\r
+            &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"],\r
+        );\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_parsing_less_than() {\r
+        let r = req("< 1.0.0");\r
+\r
+        assert_eq!(r.to_string(), "<1.0.0".to_string());\r
+\r
+        assert_match(&r, &["0.1.0", "0.0.1"]);\r
+        assert_not_match(&r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]);\r
+\r
+        let r = req("<= 2.1.0-alpha2");\r
+\r
+        assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]);\r
+        assert_not_match(\r
+            &r,\r
+            &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"],\r
+        );\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_multiple() {\r
+        let r = req("> 0.0.9, <= 2.5.3");\r
+        assert_eq!(r.to_string(), ">0.0.9, <=2.5.3".to_string());\r
+        assert_match(&r, &["0.0.10", "1.0.0", "2.5.3"]);\r
+        assert_not_match(&r, &["0.0.8", "2.5.4"]);\r
+\r
+        let r = req("0.3.0, 0.4.0");\r
+        assert_eq!(\r
+            r.to_string(),\r
+            ">=0.3.0, <0.4.0, >=0.4.0, <0.5.0".to_string()\r
+        );\r
+        assert_not_match(&r, &["0.0.8", "0.3.0", "0.4.0"]);\r
+\r
+        let r = req("<= 0.2.0, >= 0.5.0");\r
+        assert_eq!(r.to_string(), "<=0.2.0, >=0.5.0".to_string());\r
+        assert_not_match(&r, &["0.0.8", "0.3.0", "0.5.1"]);\r
+\r
+        let r = req("0.1.0, 0.1.4, 0.1.6");\r
+        assert_eq!(\r
+            r.to_string(),\r
+            ">=0.1.0, <0.2.0, >=0.1.4, <0.2.0, >=0.1.6, <0.2.0".to_string()\r
+        );\r
+        assert_match(&r, &["0.1.6", "0.1.9"]);\r
+        assert_not_match(&r, &["0.1.0", "0.1.4", "0.2.0"]);\r
+\r
+        assert!(VersionReq::parse("> 0.1.0,").is_err());\r
+        assert!(VersionReq::parse("> 0.3.0, ,").is_err());\r
+\r
+        let r = req(">=0.5.1-alpha3, <0.6");\r
+        assert_eq!(r.to_string(), ">=0.5.1-alpha3, <0.6.0".to_string());\r
+        assert_match(\r
+            &r,\r
+            &[\r
+                "0.5.1-alpha3",\r
+                "0.5.1-alpha4",\r
+                "0.5.1-beta",\r
+                "0.5.1",\r
+                "0.5.5",\r
+            ],\r
+        );\r
+        assert_not_match(\r
+            &r,\r
+            &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"],\r
+        );\r
+        assert_not_match(&r, &["0.6.0", "0.6.0-pre"]);\r
+\r
+        // https://github.com/steveklabnik/semver/issues/56\r
+        let r = req("1.2.3 - 2.3.4");\r
+        assert_eq!(r.to_string(), ">=1.2.3, <=2.3.4");\r
+        assert_match(&r, &["1.2.3", "1.2.10", "2.0.0", "2.3.4"]);\r
+        assert_not_match(&r, &["1.0.0", "1.2.2", "1.2.3-alpha1", "2.3.5"]);\r
+    }\r
+\r
+    // https://github.com/steveklabnik/semver/issues/55\r
+    #[test]\r
+    pub fn test_whitespace_delimited_comparator_sets() {\r
+        let r = req("> 0.0.9 <= 2.5.3");\r
+        assert_eq!(r.to_string(), ">0.0.9, <=2.5.3".to_string());\r
+        assert_match(&r, &["0.0.10", "1.0.0", "2.5.3"]);\r
+        assert_not_match(&r, &["0.0.8", "2.5.4"]);\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_multiple_npm() {\r
+        let r = req_npm("> 0.0.9, <= 2.5.3");\r
+        assert_eq!(r.to_string(), ">0.0.9 <=2.5.3".to_string());\r
+        assert_match(&r, &["0.0.10", "1.0.0", "2.5.3"]);\r
+        assert_not_match(&r, &["0.0.8", "2.5.4"]);\r
+\r
+        let r = req_npm("0.3.0, 0.4.0");\r
+        assert_eq!(r.to_string(), "=0.3.0 =0.4.0".to_string());\r
+        assert_not_match(&r, &["0.0.8", "0.3.0", "0.4.0"]);\r
+\r
+        let r = req_npm("<= 0.2.0, >= 0.5.0");\r
+        assert_eq!(r.to_string(), "<=0.2.0 >=0.5.0".to_string());\r
+        assert_not_match(&r, &["0.0.8", "0.3.0", "0.5.1"]);\r
+\r
+        let r = req_npm("0.1.0, 0.1.4, 0.1.6");\r
+        assert_eq!(r.to_string(), "=0.1.0 =0.1.4 =0.1.6".to_string());\r
+        assert_not_match(&r, &["0.1.0", "0.1.4", "0.1.6", "0.2.0"]);\r
+\r
+        assert!(VersionReq::parse("> 0.1.0,").is_err());\r
+        assert!(VersionReq::parse("> 0.3.0, ,").is_err());\r
+\r
+        let r = req_npm(">=0.5.1-alpha3, <0.6");\r
+        assert_eq!(r.to_string(), ">=0.5.1-alpha3 <0.6.0".to_string());\r
+        assert_match(\r
+            &r,\r
+            &[\r
+                "0.5.1-alpha3",\r
+                "0.5.1-alpha4",\r
+                "0.5.1-beta",\r
+                "0.5.1",\r
+                "0.5.5",\r
+            ],\r
+        );\r
+        assert_not_match(\r
+            &r,\r
+            &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"],\r
+        );\r
+        assert_not_match(&r, &["0.6.0", "0.6.0-pre"]);\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_parsing_tilde() {\r
+        let r = req("~1");\r
+        assert_match(&r, &["1.0.0", "1.0.1", "1.1.1"]);\r
+        assert_not_match(&r, &["0.9.1", "2.9.0", "0.0.9"]);\r
+\r
+        let r = req("~1.2");\r
+        assert_match(&r, &["1.2.0", "1.2.1"]);\r
+        assert_not_match(&r, &["1.1.1", "1.3.0", "0.0.9"]);\r
+\r
+        let r = req("~1.2.2");\r
+        assert_match(&r, &["1.2.2", "1.2.4"]);\r
+        assert_not_match(&r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
+\r
+        let r = req("~1.2.3-beta.2");\r
+        assert_match(&r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]);\r
+        assert_not_match(&r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]);\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_parsing_compatible() {\r
+        let r = req("^1");\r
+        assert_match(&r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]);\r
+        assert_not_match(&r, &["0.9.1", "2.9.0", "0.1.4"]);\r
+        assert_not_match(&r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]);\r
+\r
+        let r = req("^1.1");\r
+        assert_match(&r, &["1.1.2", "1.1.0", "1.2.1"]);\r
+        assert_not_match(&r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]);\r
+\r
+        let r = req("^1.1.2");\r
+        assert_match(&r, &["1.1.2", "1.1.4", "1.2.1"]);\r
+        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);\r
+        assert_not_match(&r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]);\r
+\r
+        let r = req("^0.1.2");\r
+        assert_match(&r, &["0.1.2", "0.1.4"]);\r
+        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);\r
+        assert_not_match(&r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]);\r
+\r
+        let r = req("^0.5.1-alpha3");\r
+        assert_match(\r
+            &r,\r
+            &[\r
+                "0.5.1-alpha3",\r
+                "0.5.1-alpha4",\r
+                "0.5.1-beta",\r
+                "0.5.1",\r
+                "0.5.5",\r
+            ],\r
+        );\r
+        assert_not_match(\r
+            &r,\r
+            &[\r
+                "0.5.1-alpha1",\r
+                "0.5.2-alpha3",\r
+                "0.5.5-pre",\r
+                "0.5.0-pre",\r
+                "0.6.0",\r
+            ],\r
+        );\r
+\r
+        let r = req("^0.0.2");\r
+        assert_match(&r, &["0.0.2"]);\r
+        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]);\r
+\r
+        let r = req("^0.0");\r
+        assert_match(&r, &["0.0.2", "0.0.0"]);\r
+        assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]);\r
+\r
+        let r = req("^0");\r
+        assert_match(&r, &["0.9.1", "0.0.2", "0.0.0"]);\r
+        assert_not_match(&r, &["2.9.0", "1.1.1"]);\r
+\r
+        let r = req("^1.4.2-beta.5");\r
+        assert_match(\r
+            &r,\r
+            &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"],\r
+        );\r
+        assert_not_match(\r
+            &r,\r
+            &[\r
+                "0.9.9",\r
+                "2.0.0",\r
+                "1.4.2-alpha",\r
+                "1.4.2-beta.4",\r
+                "1.4.3-beta.5",\r
+            ],\r
+        );\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_parsing_wildcard() {\r
+        let r = req("");\r
+        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
+        assert_not_match(&r, &[]);\r
+        let r = req("*");\r
+        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
+        assert_not_match(&r, &[]);\r
+        let r = req("x");\r
+        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
+        assert_not_match(&r, &[]);\r
+        let r = req("X");\r
+        assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);\r
+        assert_not_match(&r, &[]);\r
+\r
+        let r = req("1.*");\r
+        assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);\r
+        assert_not_match(&r, &["0.0.9"]);\r
+        let r = req("1.x");\r
+        assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);\r
+        assert_not_match(&r, &["0.0.9"]);\r
+        let r = req("1.X");\r
+        assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);\r
+        assert_not_match(&r, &["0.0.9"]);\r
+\r
+        let r = req("1.2.*");\r
+        assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);\r
+        assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
+        let r = req("1.2.x");\r
+        assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);\r
+        assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
+        let r = req("1.2.X");\r
+        assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]);\r
+        assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]);\r
+    }\r
+\r
+    // https://github.com/steveklabnik/semver/issues/57\r
+    #[test]\r
+    pub fn test_parsing_logical_or() {\r
+        let r = req("=1.2.3 || =2.3.4");\r
+        assert_eq!(r.to_string(), "=1.2.3 || =2.3.4".to_string());\r
+        assert_match(&r, &["1.2.3", "2.3.4"]);\r
+        assert_not_match(&r, &["1.0.0", "2.9.0", "0.1.4"]);\r
+        assert_not_match(&r, &["1.2.3-beta1", "2.3.4-alpha", "1.2.3-pre"]);\r
+\r
+        let r = req("1.1 || =1.2.3");\r
+        assert_eq!(r.to_string(), ">=1.1.0, <1.2.0 || =1.2.3".to_string());\r
+        assert_match(&r, &["1.1.0", "1.1.12", "1.2.3"]);\r
+        assert_not_match(&r, &["1.0.0", "1.2.2", "1.3.0"]);\r
+\r
+        let r = req("6.* || 8.* || >= 10.*");\r
+        assert_eq!(\r
+            r.to_string(),\r
+            ">=6.0.0, <7.0.0 || >=8.0.0, <9.0.0 || >=10.0.0".to_string()\r
+        );\r
+        assert_match(&r, &["6.0.0", "6.1.2"]);\r
+        assert_match(&r, &["8.0.0", "8.2.4"]);\r
+        assert_match(&r, &["10.1.2", "11.3.4"]);\r
+        assert_not_match(&r, &["5.0.0", "7.0.0", "9.0.0"]);\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_parsing_logical_or_npm() {\r
+        let r = req_npm("=1.2.3 || =2.3.4");\r
+        assert_eq!(r.to_string(), "=1.2.3 || =2.3.4".to_string());\r
+        assert_match(&r, &["1.2.3", "2.3.4"]);\r
+        assert_not_match(&r, &["1.0.0", "2.9.0", "0.1.4"]);\r
+        assert_not_match(&r, &["1.2.3-beta1", "2.3.4-alpha", "1.2.3-pre"]);\r
+\r
+        let r = req_npm("1.1 || =1.2.3");\r
+        assert_eq!(r.to_string(), ">=1.1.0 <1.2.0 || =1.2.3".to_string());\r
+        assert_match(&r, &["1.1.0", "1.1.12", "1.2.3"]);\r
+        assert_not_match(&r, &["1.0.0", "1.2.2", "1.3.0"]);\r
+\r
+        let r = req_npm("6.* || 8.* || >= 10.*");\r
+        assert_eq!(\r
+            r.to_string(),\r
+            ">=6.0.0 <7.0.0 || >=8.0.0 <9.0.0 || >=10.0.0".to_string()\r
+        );\r
+        assert_match(&r, &["6.0.0", "6.1.2"]);\r
+        assert_match(&r, &["8.0.0", "8.2.4"]);\r
+        assert_match(&r, &["10.1.2", "11.3.4"]);\r
+        assert_not_match(&r, &["5.0.0", "7.0.0", "9.0.0"]);\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_any() {\r
+        let r = VersionReq::any();\r
+        assert_match(&r, &["0.0.1", "0.1.0", "1.0.0"]);\r
+    }\r
+\r
+    #[test]\r
+    pub fn test_pre() {\r
+        let r = req("=2.1.1-really.0");\r
+        assert_match(&r, &["2.1.1-really.0"]);\r
+    }\r
+\r
+    // #[test]\r
+    // pub fn test_parse_errors() {\r
+    //    assert_eq!(Err(InvalidVersionRequirement), VersionReq::parse("\0"));\r
+    //    assert_eq!(Err(OpAlreadySet), VersionReq::parse(">= >= 0.0.2"));\r
+    //    assert_eq!(Err(InvalidSigil), VersionReq::parse(">== 0.0.2"));\r
+    //    assert_eq!(Err(VersionComponentsMustBeNumeric),\r
+    //               VersionReq::parse("a.0.0"));\r
+    //    assert_eq!(Err(InvalidIdentifier), VersionReq::parse("1.0.0-"));\r
+    //    assert_eq!(Err(MajorVersionRequired), VersionReq::parse(">="));\r
+    // }\r
+\r
+    #[test]\r
+    pub fn test_from_str() {\r
+        assert_eq!(\r
+            "1.0.0".parse::<VersionReq>().unwrap().to_string(),\r
+            ">=1.0.0, <2.0.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "=1.0.0".parse::<VersionReq>().unwrap().to_string(),\r
+            "=1.0.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "~1".parse::<VersionReq>().unwrap().to_string(),\r
+            ">=1.0.0, <2.0.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "~1.2".parse::<VersionReq>().unwrap().to_string(),\r
+            ">=1.2.0, <1.3.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "^1".parse::<VersionReq>().unwrap().to_string(),\r
+            ">=1.0.0, <2.0.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "^1.1".parse::<VersionReq>().unwrap().to_string(),\r
+            ">=1.1.0, <2.0.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "*".parse::<VersionReq>().unwrap().to_string(),\r
+            ">=0.0.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "1.*".parse::<VersionReq>().unwrap().to_string(),\r
+            ">=1.0.0, <2.0.0".to_string()\r
+        );\r
+        assert_eq!(\r
+            "< 1.0.0".parse::<VersionReq>().unwrap().to_string(),\r
+            "<1.0.0".to_string()\r
+        );\r
+    }\r
+\r
+    // #[test]\r
+    // pub fn test_from_str_errors() {\r
+    //    assert_eq!(Err(InvalidVersionRequirement), "\0".parse::<VersionReq>());\r
+    //    assert_eq!(Err(OpAlreadySet), ">= >= 0.0.2".parse::<VersionReq>());\r
+    //    assert_eq!(Err(InvalidSigil), ">== 0.0.2".parse::<VersionReq>());\r
+    //    assert_eq!(Err(VersionComponentsMustBeNumeric),\r
+    //               "a.0.0".parse::<VersionReq>());\r
+    //    assert_eq!(Err(InvalidIdentifier), "1.0.0-".parse::<VersionReq>());\r
+    //    assert_eq!(Err(MajorVersionRequired), ">=".parse::<VersionReq>());\r
+    // }\r
+\r
+    #[test]\r
+    fn test_cargo3202() {\r
+        let v = "0.*.*".parse::<VersionReq>().unwrap();\r
+        assert_eq!(">=0.0.0, <1.0.0", format!("{}", v.ranges[0]));\r
+\r
+        let v = "0.0.*".parse::<VersionReq>().unwrap();\r
+        assert_eq!(">=0.0.0, <0.1.0", format!("{}", v.ranges[0]));\r
+\r
+        let r = req("0.*.*");\r
+        assert_match(&r, &["0.5.0"]);\r
+    }\r
+\r
+    #[test]\r
+    fn test_eq_hash() {\r
+        assert!(req("^1") == req("^1"));\r
+        assert!(calculate_hash(req("^1")) == calculate_hash(req("^1")));\r
+        assert!(req("^1") != req("^2"));\r
+    }\r
+\r
+    #[test]\r
+    fn test_ordering() {\r
+        assert!(req("=1") > req("*"));\r
+        assert!(req(">1") < req("*"));\r
+        assert!(req(">=1") > req("*"));\r
+        assert!(req("<1") > req("*"));\r
+        assert!(req("<=1") > req("*"));\r
+        assert!(req("~1") > req("*"));\r
+        assert!(req("^1") > req("*"));\r
+        assert!(req("*") == req("*"));\r
+    }\r
+\r
+    #[test]\r
+    fn is_exact() {\r
+        assert!(req("=1.0.0").is_exact());\r
+        assert!(req("=1.0.0-alpha").is_exact());\r
+\r
+        assert!(!req("=1").is_exact());\r
+        assert!(!req(">=1.0.0").is_exact());\r
+        assert!(!req(">=1.0.0, <2.0.0").is_exact());\r
+    }\r
+}\r