version_number/parsers.rs
1//! This module contains multiple parsers. In the next paragraphs, each parser is described.
2//!
3//! # Parsers
4//!
5//! ## Original
6//!
7//! The [`original::Parser`] parses a version, byte by byte (`u8`). It stores a
8//! slice of bytes in the Parser struct and cursor is created at the start of the
9//! [`original::Parser::parse`] method, which acts as an index pointing to the
10//! next token to be parsed.
11//!
12//! It can be used to parse two- or three-component `major.minor(.patch)` versions,
13//! where the patch version may or may not be present.
14//!
15//! ## Modular
16//!
17//! The [`modular::Parser`] has an API which is based on the _type state_ pattern.
18//! Internally it uses a `Peekable` iterator over bytes (`u8`).
19//! The modular parser can parse a version incrementally.
20//!
21//! It may be used to parse either a two component `major.minor` version, or a three component
22//! `major.minor.patch` version, or both.
23//!
24//! # Example
25//!
26//! In this example we show a basic example of how the original and modular parsers
27//! can be used to parse a [`Version`]. For more detailed examples, see their
28//! respective modules.
29//!
30//! ```
31//! // Normally you would only use one of these, not both!
32//! use version_number::parsers::original;
33//! use version_number::parsers::modular;
34//!
35//! // As an alternative valid input, we could have used a three component version like `1.64.1`.
36//! let two_component_version = "1.64";
37//!
38//! let original_parser = original::Parser::from_slice(two_component_version.as_bytes());
39//! let modular_parser = modular::Parser::from_slice(two_component_version.as_bytes());
40//!
41//! let original_parsed = original_parser.parse().unwrap();
42//! let modular_parsed = modular_parser.parse().unwrap();
43//!
44//! assert_eq!(original_parsed, modular_parsed );
45//! ```
46//!
47
48use crate::{BaseVersion, FullVersion, Version};
49
50pub use error::{NumericError, ParserError};
51
52pub mod error;
53pub mod modular;
54pub mod original;
55
56/// Parse a UTF-8 slice of bytes to a [`Version`].
57pub trait VersionParser {
58 /// Parse a UTF-8 formatted input buffer, `input` to a [`Version`].
59 /// This version may be a [`BaseVersion`], or a [`FullVersion`].
60 ///
61 /// If the version type is known in advance, or you require a specifically
62 /// a base- or full version, you may instead use [`BaseVersionParser::parse_base`]
63 /// or [`FullVersionParser::parse_full`].
64 fn parse_version<B: AsRef<[u8]>>(&self, input: B) -> Result<Version, ParserError>;
65}
66
67/// Parse a UTF-8 slice of bytes to a [`BaseVersion`].
68pub trait BaseVersionParser {
69 /// Parse a UTF-8 formatted input buffer, `input` to a [`BaseVersion`].
70 ///
71 /// If you don't know, or care, whether the version consists of two or three components,
72 /// you may instead use [`VersionParser::parse_version`].
73 fn parse_base<B: AsRef<[u8]>>(&self, input: B) -> Result<BaseVersion, ParserError>;
74}
75
76/// Parse a UTF-8 slice of bytes to a [`FullVersion`].
77pub trait FullVersionParser {
78 /// Parse a UTF-8 formatted input buffer, `input` to a [`FullVersion`].
79 ///
80 /// If you don't know, or care, whether the version consists of two or three components,
81 /// you may instead use [`VersionParser::parse_version`].
82 fn parse_full<B: AsRef<[u8]>>(&self, input: B) -> Result<FullVersion, ParserError>;
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn parse_version_either() {
91 let input = "1.22.33";
92 let expected = Version::new_full_version(1, 22, 33);
93
94 let original = original::OriginalParser;
95 let v = original.parse_version(input).unwrap();
96 assert_eq!(v, expected);
97
98 let modular = modular::ModularParser;
99 let v = modular.parse_version(input).unwrap();
100 assert_eq!(v, expected);
101 }
102
103 fn example_generic<T: VersionParser>(input: &str, p: T) -> Version {
104 p.parse_version(input).unwrap()
105 }
106
107 #[test]
108 fn parse_version_either_generic() {
109 let input = "1.22.33";
110 let expected = Version::new_full_version(1, 22, 33);
111
112 let v = example_generic(input, original::OriginalParser);
113 assert_eq!(v, expected);
114
115 let v = example_generic(input, modular::ModularParser);
116 assert_eq!(v, expected);
117 }
118}