]>
git.proxmox.com Git - rustc.git/blob - vendor/semver-parser/src/version.rs
1 //! Version data and functions.
3 //! This module contains [`Version`] struct, [`parse`] function for building
4 //! [`Version`] struct from string and some helper data structures and functions.
8 //! Parsing `Version` from string and checking its fields:
11 //! use semver_parser::version;
13 //! # fn try_main() -> Result<(), String> {
14 //! let version = version::parse("1.2.3-alpha1")?;
16 //! assert_eq!(version.major, 1);
17 //! assert_eq!(version.minor, 2);
18 //! assert_eq!(version.patch, 3);
20 //! let expected_pre = vec![
21 //! version::Identifier::AlphaNumeric(String::from("alpha1")),
24 //! assert_eq!(expected_pre, version.pre);
28 //! # try_main().unwrap();
30 //! [`Version`]: ./struct.Version.html
31 //! [`parse`]: ./fn.parse.html
33 use crate::parser
::{self, Parser}
;
36 /// Structure representing version data.
38 /// `Version` struct has some public fields representing version data, like major/minor version
39 /// string, patch number and vectors of prefix and build identifiers.
43 /// Parsing `Version` from string and checking its fields:
46 /// use semver_parser::version;
48 /// # fn try_main() -> Result<(), String> {
49 /// let version = version::parse("0.1.2-alpha1")?;
50 /// assert_eq!(version.major, 0);
51 /// assert_eq!(version.minor, 1);
52 /// assert_eq!(version.patch, 2);
53 /// let expected_pre = vec![version::Identifier::AlphaNumeric(String::from("alpha1"))];
54 /// assert_eq!(expected_pre, version.pre);
58 /// # try_main().unwrap();
60 #[derive(Clone, PartialOrd, Ord, Hash, Debug, PartialEq, Eq)]
62 /// Major version as number (`0` in `"0.1.2"`).
64 /// Minor version as number (`1` in `"0.1.2"`).
66 /// Patch version as number (`2` in `"0.1.2"`).
68 /// Pre-release metadata as a vector of `Identifier` (`"alpha1"` in `"0.1.2-alpha1"`
69 /// or `7` (numeric) in `"0.1.2-7"`, `"pre"` and `0` (numeric) in `"0.1.2-pre.0"`).
70 pub pre
: Vec
<Identifier
>,
71 /// Build metadata as a vector of `Identifier` (`"build1"` in `"0.1.2+build1"`
72 /// or `7` (numeric) in `"0.1.2+7"`, `"build"` and `0` (numeric) in `"0.1.2+pre.0"`).
73 pub build
: Vec
<Identifier
>,
76 /// Helper enum for holding data of alphanumeric or numeric suffix identifiers.
78 /// This enum is used to hold suffix parts of `pre` and `build` fields of
79 /// [`Version`] struct. Theses suffixes may be either numeric or alphanumeric.
83 /// Parsing [`Version`] with pre-release part composed of two `Identifier`s:
86 /// use semver_parser::version;
88 /// # fn try_main() -> Result<(), String> {
89 /// let version = version::parse("0.1.2-alpha1.0")?;
91 /// let expected_pre = vec![
92 /// version::Identifier::AlphaNumeric(String::from("alpha1")),
93 /// version::Identifier::Numeric(0),
96 /// assert_eq!(expected_pre, version.pre);
100 /// # try_main().unwrap();
102 /// [`Version`]: ./struct.Version.html
103 #[derive(Clone, PartialOrd, Ord, Hash, Debug, PartialEq, Eq)]
104 pub enum Identifier
{
105 /// An identifier that's solely numbers.
107 /// An identifier with letters and numbers.
108 AlphaNumeric(String
),
112 pub fn concat(self, add_str
: &str) -> Identifier
{
114 Identifier
::Numeric(n
) => Identifier
::AlphaNumeric(format
!("{}{}", n
, add_str
)),
115 Identifier
::AlphaNumeric(s
) => Identifier
::AlphaNumeric(format
!("{}{}", s
, add_str
)),
120 /// Function for parsing version string to [`Version`].
122 /// Returns `Result<`[`Version`]`, String>`, where `String` represents an error while parsing.
126 /// Parsing [`Version`] from string and checking its fields:
129 /// use semver_parser::version;
131 /// # fn try_main() -> Result<(), String> {
132 /// let version = version::parse("0.1.2-alpha1")?;
133 /// assert_eq!(version.major, 0);
134 /// assert_eq!(version.minor, 1);
135 /// assert_eq!(version.patch, 2);
136 /// let expected_pre = vec![version::Identifier::AlphaNumeric(String::from("alpha1"))];
137 /// assert_eq!(expected_pre, version.pre);
141 /// # try_main().unwrap();
143 /// [`Version`]: ./struct.Version.html
144 pub fn parse(input
: &str) -> Result
<Version
, parser
::Error
> {
145 let mut parser
= Parser
::new(input
)?
;
146 let version
= parser
.version()?
;
148 if !parser
.is_eof() {
149 return Err(parser
::Error
::MoreInput(parser
.tail()?
));
155 impl fmt
::Display
for Version
{
156 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
157 write
!(f
, "{}.{}.{}", self.major
, self.minor
, self.patch
).expect("write failed");
158 if !self.pre
.is_empty() {
159 let strs
: Vec
<_
> = self.pre
.iter().map(ToString
::to_string
).collect();
160 write
!(f
, "-{}", strs
.join(".")).expect("write failed");
162 if !self.build
.is_empty() {
163 let strs
: Vec
<_
> = self.build
.iter().map(ToString
::to_string
).collect();
164 write
!(f
, "+{}", strs
.join(".")).expect("write failed");
170 impl fmt
::Display
for Identifier
{
171 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
173 Identifier
::Numeric(ref id
) => id
.fmt(f
),
174 Identifier
::AlphaNumeric(ref id
) => id
.fmt(f
),
188 let parsed
= version
::parse(version
);
192 "empty string incorrectly considered a valid parse"
200 let parsed
= version
::parse(version
);
204 "blank string incorrectly considered a valid parse"
209 fn parse_no_minor_patch() {
212 let parsed
= version
::parse(version
);
216 format
!("'{}' incorrectly considered a valid parse", version
)
221 fn parse_no_patch() {
224 let parsed
= version
::parse(version
);
228 format
!("'{}' incorrectly considered a valid parse", version
)
233 fn parse_empty_pre() {
234 let version
= "1.2.3-";
236 let parsed
= version
::parse(version
);
240 format
!("'{}' incorrectly considered a valid parse", version
)
246 let version
= "a.b.c";
248 let parsed
= version
::parse(version
);
252 format
!("'{}' incorrectly considered a valid parse", version
)
257 fn parse_with_letters() {
258 let version
= "1.2.3 a.b.c";
260 let parsed
= version
::parse(version
);
264 format
!("'{}' incorrectly considered a valid parse", version
)
269 fn parse_basic_version() {
270 let version
= "1.2.3";
272 let parsed
= version
::parse(version
).unwrap();
274 assert_eq
!(1, parsed
.major
);
275 assert_eq
!(2, parsed
.minor
);
276 assert_eq
!(3, parsed
.patch
);
280 fn parse_trims_input() {
281 let version
= " 1.2.3 ";
283 let parsed
= version
::parse(version
).unwrap();
285 assert_eq
!(1, parsed
.major
);
286 assert_eq
!(2, parsed
.minor
);
287 assert_eq
!(3, parsed
.patch
);
291 fn parse_no_major_leading_zeroes() {
292 let version
= "01.0.0";
294 let parsed
= version
::parse(version
);
298 "01 incorrectly considered a valid major version"
303 fn parse_no_minor_leading_zeroes() {
304 let version
= "0.01.0";
306 let parsed
= version
::parse(version
);
310 "01 incorrectly considered a valid minor version"
315 fn parse_no_patch_leading_zeroes() {
316 let version
= "0.0.01";
318 let parsed
= version
::parse(version
);
322 "01 incorrectly considered a valid patch version"
327 fn parse_no_major_overflow() {
328 let version
= "98765432109876543210.0.0";
330 let parsed
= version
::parse(version
);
334 "98765432109876543210 incorrectly considered a valid major version"
339 fn parse_no_minor_overflow() {
340 let version
= "0.98765432109876543210.0";
342 let parsed
= version
::parse(version
);
346 "98765432109876543210 incorrectly considered a valid minor version"
351 fn parse_no_patch_overflow() {
352 let version
= "0.0.98765432109876543210";
354 let parsed
= version
::parse(version
);
358 "98765432109876543210 incorrectly considered a valid patch version"
363 fn parse_basic_prerelease() {
364 let version
= "1.2.3-pre";
366 let parsed
= version
::parse(version
).unwrap();
368 let expected_pre
= vec
![Identifier
::AlphaNumeric(String
::from("pre"))];
369 assert_eq
!(expected_pre
, parsed
.pre
);
373 fn parse_prerelease_alphanumeric() {
374 let version
= "1.2.3-alpha1";
376 let parsed
= version
::parse(version
).unwrap();
378 let expected_pre
= vec
![Identifier
::AlphaNumeric(String
::from("alpha1"))];
379 assert_eq
!(expected_pre
, parsed
.pre
);
383 fn parse_prerelease_zero() {
384 let version
= "1.2.3-pre.0";
386 let parsed
= version
::parse(version
).unwrap();
388 let expected_pre
= vec
![
389 Identifier
::AlphaNumeric(String
::from("pre")),
390 Identifier
::Numeric(0),
392 assert_eq
!(expected_pre
, parsed
.pre
);
396 fn parse_basic_build() {
397 let version
= "1.2.3+build";
399 let parsed
= version
::parse(version
).unwrap();
401 let expected_build
= vec
![Identifier
::AlphaNumeric(String
::from("build"))];
402 assert_eq
!(expected_build
, parsed
.build
);
406 fn parse_build_alphanumeric() {
407 let version
= "1.2.3+build5";
409 let parsed
= version
::parse(version
).unwrap();
411 let expected_build
= vec
![Identifier
::AlphaNumeric(String
::from("build5"))];
412 assert_eq
!(expected_build
, parsed
.build
);
416 fn parse_pre_and_build() {
417 let version
= "1.2.3-alpha1+build5";
419 let parsed
= version
::parse(version
).unwrap();
421 let expected_pre
= vec
![Identifier
::AlphaNumeric(String
::from("alpha1"))];
422 assert_eq
!(expected_pre
, parsed
.pre
);
424 let expected_build
= vec
![Identifier
::AlphaNumeric(String
::from("build5"))];
425 assert_eq
!(expected_build
, parsed
.build
);
429 fn parse_complex_metadata_01() {
430 let version
= "1.2.3-1.alpha1.9+build5.7.3aedf ";
432 let parsed
= version
::parse(version
).unwrap();
434 let expected_pre
= vec
![
435 Identifier
::Numeric(1),
436 Identifier
::AlphaNumeric(String
::from("alpha1")),
437 Identifier
::Numeric(9),
439 assert_eq
!(expected_pre
, parsed
.pre
);
441 let expected_build
= vec
![
442 Identifier
::AlphaNumeric(String
::from("build5")),
443 Identifier
::Numeric(7),
444 Identifier
::AlphaNumeric(String
::from("3aedf")),
446 assert_eq
!(expected_build
, parsed
.build
);
450 fn parse_complex_metadata_02() {
451 let version
= "0.4.0-beta.1+0851523";
453 let parsed
= version
::parse(version
).unwrap();
455 let expected_pre
= vec
![
456 Identifier
::AlphaNumeric(String
::from("beta")),
457 Identifier
::Numeric(1),
459 assert_eq
!(expected_pre
, parsed
.pre
);
461 let expected_build
= vec
![Identifier
::AlphaNumeric(String
::from("0851523"))];
462 assert_eq
!(expected_build
, parsed
.build
);
466 fn parse_metadata_overflow() {
467 let version
= "0.4.0-beta.1+98765432109876543210";
469 let parsed
= version
::parse(version
).unwrap();
471 let expected_pre
= vec
![
472 Identifier
::AlphaNumeric(String
::from("beta")),
473 Identifier
::Numeric(1),
475 assert_eq
!(expected_pre
, parsed
.pre
);
477 let expected_build
= vec
![Identifier
::AlphaNumeric(String
::from(
478 "98765432109876543210",
480 assert_eq
!(expected_build
, parsed
.build
);
484 fn parse_regression_01() {
485 let version
= "0.0.0-WIP";
487 let parsed
= version
::parse(version
).unwrap();
489 assert_eq
!(0, parsed
.major
);
490 assert_eq
!(0, parsed
.minor
);
491 assert_eq
!(0, parsed
.patch
);
493 let expected_pre
= vec
![Identifier
::AlphaNumeric(String
::from("WIP"))];
494 assert_eq
!(expected_pre
, parsed
.pre
);
498 fn parse_regression_02() {
499 // this is used by really old versions of npm, and is valid according to semver.org
500 let version
= "1.2.3-beta-1";
502 let parsed
= version
::parse(version
).unwrap();
504 assert_eq
!(1, parsed
.major
);
505 assert_eq
!(2, parsed
.minor
);
506 assert_eq
!(3, parsed
.patch
);
508 let expected_pre
= vec
![Identifier
::AlphaNumeric(String
::from("beta-1"))];
509 assert_eq
!(expected_pre
, parsed
.pre
);