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}