1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 
11 //! The `version` module gives you tools to create and compare SemVer-compliant
12 //! versions.
13 
14 use std::cmp::{self, Ordering};
15 use std::fmt;
16 use std::hash;
17 use std::error::Error;
18 
19 use std::result;
20 use std::str;
21 
22 use semver_parser;
23 
24 #[cfg(feature = "serde")]
25 use serde::ser::{Serialize, Serializer};
26 #[cfg(feature = "serde")]
27 use serde::de::{self, Deserialize, Deserializer, Visitor};
28 
29 /// An identifier in the pre-release or build metadata.
30 ///
31 /// See sections 9 and 10 of the spec for more about pre-release identifers and
32 /// build metadata.
33 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
34 pub enum Identifier {
35     /// An identifier that's solely numbers.
36     Numeric(u64),
37     /// An identifier with letters and numbers.
38     AlphaNumeric(String),
39 }
40 
41 impl From<semver_parser::version::Identifier> for Identifier {
from(other: semver_parser::version::Identifier) -> Identifier42     fn from(other: semver_parser::version::Identifier) -> Identifier {
43         match other {
44             semver_parser::version::Identifier::Numeric(n) => Identifier::Numeric(n),
45             semver_parser::version::Identifier::AlphaNumeric(s) => Identifier::AlphaNumeric(s),
46         }
47     }
48 }
49 
50 impl fmt::Display for Identifier {
51     #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result52     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53         match *self {
54             Identifier::Numeric(ref n) => fmt::Display::fmt(n, f),
55             Identifier::AlphaNumeric(ref s) => fmt::Display::fmt(s, f),
56         }
57     }
58 }
59 
60 #[cfg(feature = "serde")]
61 impl Serialize for Identifier {
serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error> where S: Serializer62     fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
63         where S: Serializer
64     {
65         // Serialize Identifier as a number or string.
66         match *self {
67             Identifier::Numeric(n) => serializer.serialize_u64(n),
68             Identifier::AlphaNumeric(ref s) => serializer.serialize_str(s),
69         }
70     }
71 }
72 
73 #[cfg(feature = "serde")]
74 impl<'de> Deserialize<'de> for Identifier {
deserialize<D>(deserializer: D) -> result::Result<Self, D::Error> where D: Deserializer<'de>75     fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
76         where D: Deserializer<'de>
77     {
78         struct IdentifierVisitor;
79 
80         // Deserialize Identifier from a number or string.
81         impl<'de> Visitor<'de> for IdentifierVisitor {
82             type Value = Identifier;
83 
84             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
85                 formatter.write_str("a SemVer pre-release or build identifier")
86             }
87 
88             fn visit_u64<E>(self, numeric: u64) -> result::Result<Self::Value, E>
89                 where E: de::Error
90             {
91                 Ok(Identifier::Numeric(numeric))
92             }
93 
94             fn visit_str<E>(self, alphanumeric: &str) -> result::Result<Self::Value, E>
95                 where E: de::Error
96             {
97                 Ok(Identifier::AlphaNumeric(alphanumeric.to_owned()))
98             }
99         }
100 
101         deserializer.deserialize_any(IdentifierVisitor)
102     }
103 }
104 
105 /// Represents a version number conforming to the semantic versioning scheme.
106 #[derive(Clone, Eq, Debug)]
107 pub struct Version {
108     /// The major version, to be incremented on incompatible changes.
109     pub major: u64,
110     /// The minor version, to be incremented when functionality is added in a
111     /// backwards-compatible manner.
112     pub minor: u64,
113     /// The patch version, to be incremented when backwards-compatible bug
114     /// fixes are made.
115     pub patch: u64,
116     /// The pre-release version identifier, if one exists.
117     pub pre: Vec<Identifier>,
118     /// The build metadata, ignored when determining version precedence.
119     pub build: Vec<Identifier>,
120 }
121 
122 impl From<semver_parser::version::Version> for Version {
from(other: semver_parser::version::Version) -> Version123     fn from(other: semver_parser::version::Version) -> Version {
124         Version {
125             major: other.major,
126             minor: other.minor,
127             patch: other.patch,
128             pre: other.pre.into_iter().map(From::from).collect(),
129             build: other.build.into_iter().map(From::from).collect(),
130         }
131     }
132 }
133 
134 #[cfg(feature = "serde")]
135 impl Serialize for Version {
serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error> where S: Serializer136     fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
137         where S: Serializer
138     {
139         // Serialize Version as a string.
140         serializer.collect_str(self)
141     }
142 }
143 
144 #[cfg(feature = "serde")]
145 impl<'de> Deserialize<'de> for Version {
deserialize<D>(deserializer: D) -> result::Result<Self, D::Error> where D: Deserializer<'de>146     fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
147         where D: Deserializer<'de>
148     {
149         struct VersionVisitor;
150 
151         // Deserialize Version from a string.
152         impl<'de> Visitor<'de> for VersionVisitor {
153             type Value = Version;
154 
155             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
156                 formatter.write_str("a SemVer version as a string")
157             }
158 
159             fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E>
160                 where E: de::Error
161             {
162                 Version::parse(v).map_err(de::Error::custom)
163             }
164         }
165 
166         deserializer.deserialize_str(VersionVisitor)
167     }
168 }
169 
170 /// An error type for this crate
171 ///
172 /// Currently, just a generic error. Will make this nicer later.
173 #[derive(Clone,PartialEq,Debug,PartialOrd)]
174 pub enum SemVerError {
175     /// An error ocurred while parsing.
176     ParseError(String),
177 }
178 
179 impl fmt::Display for SemVerError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result180     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181         match self {
182             &SemVerError::ParseError(ref m) => write!(f, "{}", m),
183         }
184     }
185 }
186 
187 impl Error for SemVerError {
description(&self) -> &str188     fn description(&self) -> &str {
189         match self {
190             &SemVerError::ParseError(ref m) => m,
191         }
192     }
193 }
194 
195 /// A Result type for errors
196 pub type Result<T> = result::Result<T, SemVerError>;
197 
198 impl Version {
199 
200     /// Contructs the simple case without pre or build.
new(major: u64, minor: u64, patch: u64) -> Version201     pub fn new(major: u64, minor: u64, patch: u64) -> Version {
202         Version {
203             major: major,
204             minor: minor,
205             patch: patch,
206             pre: Vec::new(),
207             build: Vec::new()
208         }
209     }
210 
211     /// Parse a string into a semver object.
parse(version: &str) -> Result<Version>212     pub fn parse(version: &str) -> Result<Version> {
213         let res = semver_parser::version::parse(version);
214 
215         match res {
216             // Convert plain String error into proper ParseError
217             Err(e) => Err(SemVerError::ParseError(e)),
218             Ok(v) => Ok(From::from(v)),
219         }
220     }
221 
222     /// Clears the build metadata
clear_metadata(&mut self)223     fn clear_metadata(&mut self) {
224         self.build = Vec::new();
225         self.pre = Vec::new();
226     }
227 
228     /// Increments the patch number for this Version (Must be mutable)
increment_patch(&mut self)229     pub fn increment_patch(&mut self) {
230         self.patch += 1;
231         self.clear_metadata();
232     }
233 
234     /// Increments the minor version number for this Version (Must be mutable)
235     ///
236     /// As instructed by section 7 of the spec, the patch number is reset to 0.
increment_minor(&mut self)237     pub fn increment_minor(&mut self) {
238         self.minor += 1;
239         self.patch = 0;
240         self.clear_metadata();
241     }
242 
243     /// Increments the major version number for this Version (Must be mutable)
244     ///
245     /// As instructed by section 8 of the spec, the minor and patch numbers are
246     /// reset to 0
increment_major(&mut self)247     pub fn increment_major(&mut self) {
248         self.major += 1;
249         self.minor = 0;
250         self.patch = 0;
251         self.clear_metadata();
252     }
253 
254     /// Checks to see if the current Version is in pre-release status
is_prerelease(&self) -> bool255     pub fn is_prerelease(&self) -> bool {
256         !self.pre.is_empty()
257     }
258 }
259 
260 impl str::FromStr for Version {
261     type Err = SemVerError;
262 
from_str(s: &str) -> Result<Version>263     fn from_str(s: &str) -> Result<Version> {
264         Version::parse(s)
265     }
266 }
267 
268 impl fmt::Display for Version {
269     #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result270     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
271         try!(write!(f, "{}.{}.{}", self.major, self.minor, self.patch));
272         if !self.pre.is_empty() {
273             try!(write!(f, "-"));
274             for (i, x) in self.pre.iter().enumerate() {
275                 if i != 0 {
276                     try!(write!(f, "."))
277                 }
278                 try!(write!(f, "{}", x));
279             }
280         }
281         if !self.build.is_empty() {
282             try!(write!(f, "+"));
283             for (i, x) in self.build.iter().enumerate() {
284                 if i != 0 {
285                     try!(write!(f, "."))
286                 }
287                 try!(write!(f, "{}", x));
288             }
289         }
290         Ok(())
291     }
292 }
293 
294 impl cmp::PartialEq for Version {
295     #[inline]
eq(&self, other: &Version) -> bool296     fn eq(&self, other: &Version) -> bool {
297         // We should ignore build metadata here, otherwise versions v1 and v2
298         // can exist such that !(v1 < v2) && !(v1 > v2) && v1 != v2, which
299         // violate strict total ordering rules.
300         self.major == other.major && self.minor == other.minor && self.patch == other.patch &&
301         self.pre == other.pre
302     }
303 }
304 
305 impl cmp::PartialOrd for Version {
partial_cmp(&self, other: &Version) -> Option<Ordering>306     fn partial_cmp(&self, other: &Version) -> Option<Ordering> {
307         Some(self.cmp(other))
308     }
309 }
310 
311 impl cmp::Ord for Version {
cmp(&self, other: &Version) -> Ordering312     fn cmp(&self, other: &Version) -> Ordering {
313         match self.major.cmp(&other.major) {
314             Ordering::Equal => {}
315             r => return r,
316         }
317 
318         match self.minor.cmp(&other.minor) {
319             Ordering::Equal => {}
320             r => return r,
321         }
322 
323         match self.patch.cmp(&other.patch) {
324             Ordering::Equal => {}
325             r => return r,
326         }
327 
328         // NB: semver spec says 0.0.0-pre < 0.0.0
329         // but the version of ord defined for vec
330         // says that [] < [pre] so we alter it here
331         match (self.pre.len(), other.pre.len()) {
332             (0, 0) => Ordering::Equal,
333             (0, _) => Ordering::Greater,
334             (_, 0) => Ordering::Less,
335             (_, _) => self.pre.cmp(&other.pre),
336         }
337     }
338 }
339 
340 impl hash::Hash for Version {
hash<H: hash::Hasher>(&self, into: &mut H)341     fn hash<H: hash::Hasher>(&self, into: &mut H) {
342         self.major.hash(into);
343         self.minor.hash(into);
344         self.patch.hash(into);
345         self.pre.hash(into);
346     }
347 }
348 
349 impl From<(u64,u64,u64)> for Version {
from(tuple: (u64,u64,u64)) -> Version350     fn from(tuple: (u64,u64,u64)) -> Version {
351         let (major, minor, patch) = tuple;
352         Version::new(major, minor, patch)
353     }
354 }
355 
356 #[cfg(test)]
357 mod tests {
358     use std::result;
359     use super::Version;
360     use super::Identifier;
361     use super::SemVerError;
362 
363     #[test]
test_parse()364     fn test_parse() {
365         fn parse_error(e: &str) -> result::Result<Version, SemVerError> {
366             return Err(SemVerError::ParseError(e.to_string()));
367         }
368 
369         assert_eq!(Version::parse(""),
370                    parse_error("Error parsing major identifier"));
371         assert_eq!(Version::parse("  "),
372                    parse_error("Error parsing major identifier"));
373         assert_eq!(Version::parse("1"),
374                    parse_error("Expected dot"));
375         assert_eq!(Version::parse("1.2"),
376                    parse_error("Expected dot"));
377         assert_eq!(Version::parse("1.2.3-"),
378                    parse_error("Error parsing prerelease"));
379         assert_eq!(Version::parse("a.b.c"),
380                    parse_error("Error parsing major identifier"));
381         assert_eq!(Version::parse("1.2.3 abc"),
382                    parse_error("Extra junk after valid version:  abc"));
383 
384         assert_eq!(Version::parse("1.2.3"),
385                    Ok(Version {
386                        major: 1,
387                        minor: 2,
388                        patch: 3,
389                        pre: Vec::new(),
390                        build: Vec::new(),
391                    }));
392 
393         assert_eq!(Version::parse("1.2.3"),
394                    Ok(Version::new(1,2,3)));
395 
396         assert_eq!(Version::parse("  1.2.3  "),
397                    Ok(Version {
398                        major: 1,
399                        minor: 2,
400                        patch: 3,
401                        pre: Vec::new(),
402                        build: Vec::new(),
403                    }));
404         assert_eq!(Version::parse("1.2.3-alpha1"),
405                    Ok(Version {
406                        major: 1,
407                        minor: 2,
408                        patch: 3,
409                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
410                        build: Vec::new(),
411                    }));
412         assert_eq!(Version::parse("  1.2.3-alpha1  "),
413                    Ok(Version {
414                        major: 1,
415                        minor: 2,
416                        patch: 3,
417                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
418                        build: Vec::new(),
419                    }));
420         assert_eq!(Version::parse("1.2.3+build5"),
421                    Ok(Version {
422                        major: 1,
423                        minor: 2,
424                        patch: 3,
425                        pre: Vec::new(),
426                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
427                    }));
428         assert_eq!(Version::parse("  1.2.3+build5  "),
429                    Ok(Version {
430                        major: 1,
431                        minor: 2,
432                        patch: 3,
433                        pre: Vec::new(),
434                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
435                    }));
436         assert_eq!(Version::parse("1.2.3-alpha1+build5"),
437                    Ok(Version {
438                        major: 1,
439                        minor: 2,
440                        patch: 3,
441                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
442                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
443                    }));
444         assert_eq!(Version::parse("  1.2.3-alpha1+build5  "),
445                    Ok(Version {
446                        major: 1,
447                        minor: 2,
448                        patch: 3,
449                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
450                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
451                    }));
452         assert_eq!(Version::parse("1.2.3-1.alpha1.9+build5.7.3aedf  "),
453                    Ok(Version {
454                        major: 1,
455                        minor: 2,
456                        patch: 3,
457                        pre: vec![Identifier::Numeric(1),
458                       Identifier::AlphaNumeric(String::from("alpha1")),
459                       Identifier::Numeric(9),
460             ],
461                        build: vec![Identifier::AlphaNumeric(String::from("build5")),
462                         Identifier::Numeric(7),
463                         Identifier::AlphaNumeric(String::from("3aedf")),
464             ],
465                    }));
466         assert_eq!(Version::parse("0.4.0-beta.1+0851523"),
467                    Ok(Version {
468                        major: 0,
469                        minor: 4,
470                        patch: 0,
471                        pre: vec![Identifier::AlphaNumeric(String::from("beta")),
472                       Identifier::Numeric(1),
473             ],
474                        build: vec![Identifier::AlphaNumeric(String::from("0851523"))],
475                    }));
476 
477     }
478 
479     #[test]
test_increment_patch()480     fn test_increment_patch() {
481         let mut buggy_release = Version::parse("0.1.0").unwrap();
482         buggy_release.increment_patch();
483         assert_eq!(buggy_release, Version::parse("0.1.1").unwrap());
484     }
485 
486     #[test]
test_increment_minor()487     fn test_increment_minor() {
488         let mut feature_release = Version::parse("1.4.6").unwrap();
489         feature_release.increment_minor();
490         assert_eq!(feature_release, Version::parse("1.5.0").unwrap());
491     }
492 
493     #[test]
test_increment_major()494     fn test_increment_major() {
495         let mut chrome_release = Version::parse("46.1.246773").unwrap();
496         chrome_release.increment_major();
497         assert_eq!(chrome_release, Version::parse("47.0.0").unwrap());
498     }
499 
500     #[test]
test_increment_keep_prerelease()501     fn test_increment_keep_prerelease() {
502         let mut release = Version::parse("1.0.0-alpha").unwrap();
503         release.increment_patch();
504 
505         assert_eq!(release, Version::parse("1.0.1").unwrap());
506 
507         release.increment_minor();
508 
509         assert_eq!(release, Version::parse("1.1.0").unwrap());
510 
511         release.increment_major();
512 
513         assert_eq!(release, Version::parse("2.0.0").unwrap());
514     }
515 
516 
517     #[test]
test_increment_clear_metadata()518     fn test_increment_clear_metadata() {
519         let mut release = Version::parse("1.0.0+4442").unwrap();
520         release.increment_patch();
521 
522         assert_eq!(release, Version::parse("1.0.1").unwrap());
523         release = Version::parse("1.0.1+hello").unwrap();
524 
525         release.increment_minor();
526 
527         assert_eq!(release, Version::parse("1.1.0").unwrap());
528         release = Version::parse("1.1.3747+hello").unwrap();
529 
530         release.increment_major();
531 
532         assert_eq!(release, Version::parse("2.0.0").unwrap());
533     }
534 
535     #[test]
test_eq()536     fn test_eq() {
537         assert_eq!(Version::parse("1.2.3"), Version::parse("1.2.3"));
538         assert_eq!(Version::parse("1.2.3-alpha1"),
539                    Version::parse("1.2.3-alpha1"));
540         assert_eq!(Version::parse("1.2.3+build.42"),
541                    Version::parse("1.2.3+build.42"));
542         assert_eq!(Version::parse("1.2.3-alpha1+42"),
543                    Version::parse("1.2.3-alpha1+42"));
544         assert_eq!(Version::parse("1.2.3+23"), Version::parse("1.2.3+42"));
545     }
546 
547     #[test]
test_ne()548     fn test_ne() {
549         assert!(Version::parse("0.0.0") != Version::parse("0.0.1"));
550         assert!(Version::parse("0.0.0") != Version::parse("0.1.0"));
551         assert!(Version::parse("0.0.0") != Version::parse("1.0.0"));
552         assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta"));
553     }
554 
555     #[test]
test_show()556     fn test_show() {
557         assert_eq!(format!("{}", Version::parse("1.2.3").unwrap()),
558                    "1.2.3".to_string());
559         assert_eq!(format!("{}", Version::parse("1.2.3-alpha1").unwrap()),
560                    "1.2.3-alpha1".to_string());
561         assert_eq!(format!("{}", Version::parse("1.2.3+build.42").unwrap()),
562                    "1.2.3+build.42".to_string());
563         assert_eq!(format!("{}", Version::parse("1.2.3-alpha1+42").unwrap()),
564                    "1.2.3-alpha1+42".to_string());
565     }
566 
567     #[test]
test_to_string()568     fn test_to_string() {
569         assert_eq!(Version::parse("1.2.3").unwrap().to_string(),
570                    "1.2.3".to_string());
571         assert_eq!(Version::parse("1.2.3-alpha1").unwrap().to_string(),
572                    "1.2.3-alpha1".to_string());
573         assert_eq!(Version::parse("1.2.3+build.42").unwrap().to_string(),
574                    "1.2.3+build.42".to_string());
575         assert_eq!(Version::parse("1.2.3-alpha1+42").unwrap().to_string(),
576                    "1.2.3-alpha1+42".to_string());
577     }
578 
579     #[test]
test_lt()580     fn test_lt() {
581         assert!(Version::parse("0.0.0") < Version::parse("1.2.3-alpha2"));
582         assert!(Version::parse("1.0.0") < Version::parse("1.2.3-alpha2"));
583         assert!(Version::parse("1.2.0") < Version::parse("1.2.3-alpha2"));
584         assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3"));
585         assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3-alpha2"));
586         assert!(!(Version::parse("1.2.3-alpha2") < Version::parse("1.2.3-alpha2")));
587         assert!(!(Version::parse("1.2.3+23") < Version::parse("1.2.3+42")));
588     }
589 
590     #[test]
test_le()591     fn test_le() {
592         assert!(Version::parse("0.0.0") <= Version::parse("1.2.3-alpha2"));
593         assert!(Version::parse("1.0.0") <= Version::parse("1.2.3-alpha2"));
594         assert!(Version::parse("1.2.0") <= Version::parse("1.2.3-alpha2"));
595         assert!(Version::parse("1.2.3-alpha1") <= Version::parse("1.2.3-alpha2"));
596         assert!(Version::parse("1.2.3-alpha2") <= Version::parse("1.2.3-alpha2"));
597         assert!(Version::parse("1.2.3+23") <= Version::parse("1.2.3+42"));
598     }
599 
600     #[test]
test_gt()601     fn test_gt() {
602         assert!(Version::parse("1.2.3-alpha2") > Version::parse("0.0.0"));
603         assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.0.0"));
604         assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0"));
605         assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha1"));
606         assert!(Version::parse("1.2.3") > Version::parse("1.2.3-alpha2"));
607         assert!(!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha2")));
608         assert!(!(Version::parse("1.2.3+23") > Version::parse("1.2.3+42")));
609     }
610 
611     #[test]
test_ge()612     fn test_ge() {
613         assert!(Version::parse("1.2.3-alpha2") >= Version::parse("0.0.0"));
614         assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.0.0"));
615         assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.0"));
616         assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha1"));
617         assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha2"));
618         assert!(Version::parse("1.2.3+23") >= Version::parse("1.2.3+42"));
619     }
620 
621     #[test]
test_prerelease_check()622     fn test_prerelease_check() {
623         assert!(Version::parse("1.0.0").unwrap().is_prerelease() == false);
624         assert!(Version::parse("0.0.1").unwrap().is_prerelease() == false);
625         assert!(Version::parse("4.1.4-alpha").unwrap().is_prerelease());
626         assert!(Version::parse("1.0.0-beta294296").unwrap().is_prerelease());
627     }
628 
629     #[test]
test_spec_order()630     fn test_spec_order() {
631         let vs = ["1.0.0-alpha",
632                   "1.0.0-alpha.1",
633                   "1.0.0-alpha.beta",
634                   "1.0.0-beta",
635                   "1.0.0-beta.2",
636                   "1.0.0-beta.11",
637                   "1.0.0-rc.1",
638                   "1.0.0"];
639         let mut i = 1;
640         while i < vs.len() {
641             let a = Version::parse(vs[i - 1]);
642             let b = Version::parse(vs[i]);
643             assert!(a < b, "nope {:?} < {:?}", a, b);
644             i += 1;
645         }
646     }
647 
648     #[test]
test_from_str()649     fn test_from_str() {
650         assert_eq!("1.2.3".parse(),
651                    Ok(Version {
652                        major: 1,
653                        minor: 2,
654                        patch: 3,
655                        pre: Vec::new(),
656                        build: Vec::new(),
657                    }));
658         assert_eq!("  1.2.3  ".parse(),
659                    Ok(Version {
660                        major: 1,
661                        minor: 2,
662                        patch: 3,
663                        pre: Vec::new(),
664                        build: Vec::new(),
665                    }));
666         assert_eq!("1.2.3-alpha1".parse(),
667                    Ok(Version {
668                        major: 1,
669                        minor: 2,
670                        patch: 3,
671                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
672                        build: Vec::new(),
673                    }));
674         assert_eq!("  1.2.3-alpha1  ".parse(),
675                    Ok(Version {
676                        major: 1,
677                        minor: 2,
678                        patch: 3,
679                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
680                        build: Vec::new(),
681                    }));
682         assert_eq!("1.2.3+build5".parse(),
683                    Ok(Version {
684                        major: 1,
685                        minor: 2,
686                        patch: 3,
687                        pre: Vec::new(),
688                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
689                    }));
690         assert_eq!("  1.2.3+build5  ".parse(),
691                    Ok(Version {
692                        major: 1,
693                        minor: 2,
694                        patch: 3,
695                        pre: Vec::new(),
696                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
697                    }));
698         assert_eq!("1.2.3-alpha1+build5".parse(),
699                    Ok(Version {
700                        major: 1,
701                        minor: 2,
702                        patch: 3,
703                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
704                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
705                    }));
706         assert_eq!("  1.2.3-alpha1+build5  ".parse(),
707                    Ok(Version {
708                        major: 1,
709                        minor: 2,
710                        patch: 3,
711                        pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
712                        build: vec![Identifier::AlphaNumeric(String::from("build5"))],
713                    }));
714         assert_eq!("1.2.3-1.alpha1.9+build5.7.3aedf  ".parse(),
715                    Ok(Version {
716                        major: 1,
717                        minor: 2,
718                        patch: 3,
719                        pre: vec![Identifier::Numeric(1),
720                       Identifier::AlphaNumeric(String::from("alpha1")),
721                       Identifier::Numeric(9),
722             ],
723                        build: vec![Identifier::AlphaNumeric(String::from("build5")),
724                         Identifier::Numeric(7),
725                         Identifier::AlphaNumeric(String::from("3aedf")),
726             ],
727                    }));
728         assert_eq!("0.4.0-beta.1+0851523".parse(),
729                    Ok(Version {
730                        major: 0,
731                        minor: 4,
732                        patch: 0,
733                        pre: vec![Identifier::AlphaNumeric(String::from("beta")),
734                       Identifier::Numeric(1),
735             ],
736                        build: vec![Identifier::AlphaNumeric(String::from("0851523"))],
737                    }));
738 
739     }
740 
741     #[test]
test_from_str_errors()742     fn test_from_str_errors() {
743         fn parse_error(e: &str) -> result::Result<Version, SemVerError> {
744             return Err(SemVerError::ParseError(e.to_string()));
745         }
746 
747         assert_eq!("".parse(), parse_error("Error parsing major identifier"));
748         assert_eq!("  ".parse(), parse_error("Error parsing major identifier"));
749         assert_eq!("1".parse(), parse_error("Expected dot"));
750         assert_eq!("1.2".parse(),
751                    parse_error("Expected dot"));
752         assert_eq!("1.2.3-".parse(),
753                    parse_error("Error parsing prerelease"));
754         assert_eq!("a.b.c".parse(),
755                    parse_error("Error parsing major identifier"));
756         assert_eq!("1.2.3 abc".parse(),
757                    parse_error("Extra junk after valid version:  abc"));
758     }
759 }
760