utils/parser/
error.rs

1use crate::parser::then::Then2;
2use crate::parser::{ParseResult, Parser};
3use std::error::Error;
4use std::fmt::{Display, Formatter};
5
6/// Error type returned by [`Parser::parse`].
7#[non_exhaustive]
8#[derive(Debug, Copy, Clone, PartialEq, Eq)]
9pub enum ParseError {
10    /// Expected $type.
11    Expected(&'static str),
12    /// Expected $literal.
13    ExpectedLiteral(&'static str),
14    /// Expected $byte.
15    ExpectedByte(u8),
16    /// Expected $min - $max.
17    ExpectedByteRange(u8, u8),
18    /// Expected at least $n matches.
19    ExpectedMatches(usize),
20    /// Expected $n items or less.
21    ExpectedLessItems(usize),
22    /// Expected end of input.
23    ExpectedEof(),
24    /// Expected number <= $num.
25    NumberTooLarge(i128),
26    /// Expected number >= $num.
27    NumberTooSmall(i128),
28    /// Number out of range.
29    ///
30    /// Used as a fallback if min/max bound doesn't fit in an [`i128`] (for example, [`u128::MAX`]).
31    NumberOutOfRange(),
32    /// Custom error returned by [`Parser::map_res`] & [`Parser::error_msg`].
33    Custom(&'static str),
34}
35
36impl ParseError {
37    #[inline]
38    pub(super) fn too_large(max: impl TryInto<i128>) -> Self {
39        if let Ok(max) = max.try_into() {
40            Self::NumberTooLarge(max)
41        } else {
42            Self::NumberOutOfRange()
43        }
44    }
45
46    #[inline]
47    pub(super) fn too_small(min: impl TryInto<i128>) -> Self {
48        if let Ok(min) = min.try_into() {
49            Self::NumberTooSmall(min)
50        } else {
51            Self::NumberOutOfRange()
52        }
53    }
54}
55
56impl Display for ParseError {
57    #[cold]
58    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
59        match *self {
60            ParseError::Expected(x) => write!(f, "expected {x}"),
61            ParseError::ExpectedLiteral(x) => write!(f, "expected {x:?}"),
62            ParseError::ExpectedByte(x) => write!(f, "expected {:?}", x.escape_ascii().to_string()),
63            ParseError::ExpectedByteRange(min, max) => {
64                write!(
65                    f,
66                    "expected {:?}-{:?}",
67                    min.escape_ascii().to_string(),
68                    max.escape_ascii().to_string(),
69                )
70            }
71            ParseError::ExpectedEof() => write!(f, "expected end of input"),
72            ParseError::ExpectedMatches(x) => write!(f, "expected at least {x} match"),
73            ParseError::ExpectedLessItems(x) => write!(f, "expected {x} items or less"),
74            ParseError::NumberTooLarge(x) => write!(f, "expected number <= {x}"),
75            ParseError::NumberTooSmall(x) => write!(f, "expected number >= {x}"),
76            ParseError::NumberOutOfRange() => write!(f, "number out of range"),
77            ParseError::Custom(x) => f.write_str(x),
78        }
79    }
80}
81
82impl Error for ParseError {}
83
84#[derive(Copy, Clone)]
85pub struct WithErrorMsg<P> {
86    pub(super) parser: P,
87    pub(super) message: &'static str,
88}
89impl<'i, P: Parser<'i>> Parser<'i> for WithErrorMsg<P> {
90    type Output = P::Output;
91    type Then<T: Parser<'i>> = Then2<Self, T>;
92
93    #[inline]
94    fn parse(&self, input: &'i [u8]) -> ParseResult<'i, Self::Output> {
95        match self.parser.parse(input) {
96            Ok(v) => Ok(v),
97            Err((_, pos)) => Err((ParseError::Custom(self.message), pos)),
98        }
99    }
100}