version_number/parsers/
error.rs

1//! A module for a common error API.
2//! Individual parsers may implement their own, more detailed error type.
3//! This error type may be used with the convenience parse traits, [`ParseVersion`],
4//! [`ParseBase`] and [`ParseFull`].
5//!
6//! [`ParseVersion`]: crate::VersionParser
7//! [`ParseBase`]: crate::BaseVersionParser
8//! [`ParseFull`]: crate::FullVersionParser
9
10type Index = usize;
11
12///
13#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
14pub enum ParserError {
15    /// An error variant for fault when a some type of input, or none at all,
16    /// was expected next.
17    #[error(transparent)]
18    Expected(#[from] ExpectedError),
19
20    /// An error variant for faults when parsing and constructing a number.
21    #[error(transparent)]
22    Numeric(#[from] NumericError),
23}
24
25/// An error type for faults relating to parsing and expecting a certain type of
26/// token.
27#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
28pub enum ExpectedError {
29    /// When this error variant is returned, the `.` token, i.e. the separator, was expected, but
30    /// a different token was present. The `got` field shows the token read.
31    #[error("Expected dot token '.', but got '{}'{}.", 
32        .got.map(String::from).unwrap_or_else(|| "EOI".to_string()),
33        .at.map(|i| format!(" at {}", i)).unwrap_or_default())
34    ]
35    Separator {
36        /// Place where the token was expected.
37        ///
38        /// May be `None` if the respective parser does not store the index.
39        at: Option<Index>,
40        /// Token found instead, or `None` if we unexpectedly got the end-of-input.
41        got: Option<char>,
42    },
43
44    /// When this error variant is returned, the parser expected that no more
45    /// tokens should be present, but instead 1 or more additional tokens
46    /// were not parsed yet.
47    ///
48    /// The `got` field contains the next token received, where
49    /// it expected none to be remaining.
50    #[error("Expected end of input, but got '{got}'{}.", .at.map(|i| format!(" at {}", i)).unwrap_or_default())]
51    EndOfInput {
52        /// Place where the end-of-input was expected.
53        ///
54        /// May be `None` if the respective parser does not store the index.
55        at: Option<Index>,
56        /// Character found at the expected end-of-input.
57        got: char,
58    },
59
60    /// When this error variant is returned, a numeric token was expected, but
61    /// a different token was present.
62    ///
63    /// The `got` field shows the token read.
64    #[error("Expected numeric token (0-9), but got '{}'{}.",
65        .got.map(String::from).unwrap_or_else(|| "EOI".to_string()),
66        .at.map(|i| format!(" at {}", i)).unwrap_or_default())
67    ]
68    Numeric {
69        /// Place where the token was expected.
70        ///
71        /// May be `None` if the respective parser does not store the index.
72        at: Option<Index>,
73        /// Token found instead, or `None` if we unexpectedly got the end-of-input.
74        got: Option<char>,
75    },
76}
77
78/// An error type for faults relating to parsing and constructing numbers.
79#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
80pub enum NumericError {
81    /// When this error variant is returned, the parser detected that the number started with a leading
82    /// zero, which is not allowed for number components.
83    #[error("Number may not start with a leading zero, unless the complete component is '0'")]
84    LeadingZero,
85
86    /// This error variant is returned if the number would overflow.
87    ///
88    /// Each number component consists of a 64 bits unsigned integer.
89    #[error("Overflow: Found number component which would be larger than the maximum supported number (max={})", u64::MAX)]
90    Overflow,
91}