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