utils/parser/
error.rs

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