1use crate::ascii::AsciiSet;
2use crate::parser::then::Then2;
3use crate::parser::{ParseState, Parser, ParserResult};
4use std::error::Error;
5use std::fmt::{Display, Formatter};
6
7#[non_exhaustive]
11#[derive(Debug, Copy, Clone, PartialEq, Eq)]
12pub enum ParseError {
13 Expected(&'static str),
15 ExpectedLiteral(&'static str),
17 ExpectedByte(u8),
19 ExpectedByteRange(u8, u8),
21 ExpectedOneOf(AsciiSet),
23 ExpectedMatches(usize),
25 ExpectedLessItems(usize),
27 ExpectedEof(),
29 NumberTooLarge(i128),
31 NumberTooSmall(i128),
33 NumberOutOfRange(),
37 Custom(&'static str),
39}
40
41impl ParseError {
42 #[inline]
43 pub(super) fn too_large(max: impl TryInto<i128>) -> Self {
44 if let Ok(max) = max.try_into() {
45 Self::NumberTooLarge(max)
46 } else {
47 Self::NumberOutOfRange()
48 }
49 }
50
51 #[inline]
52 pub(super) fn too_small(min: impl TryInto<i128>) -> Self {
53 if let Ok(min) = min.try_into() {
54 Self::NumberTooSmall(min)
55 } else {
56 Self::NumberOutOfRange()
57 }
58 }
59}
60
61impl Display for ParseError {
62 #[cold]
63 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64 match *self {
65 ParseError::Expected(x) => write!(f, "expected {x}"),
66 ParseError::ExpectedLiteral(x) => write!(f, "expected {x:?}"),
67 ParseError::ExpectedByte(x) => write!(f, "expected {:?}", x as char),
68 ParseError::ExpectedByteRange(min, max) => {
69 write!(f, "expected {:?}-{:?}", min as char, max as char)
70 }
71 ParseError::ExpectedOneOf(set) => write!(f, "expected one of {set}"),
72 ParseError::ExpectedEof() => write!(f, "expected end of input"),
73 ParseError::ExpectedMatches(x) => write!(f, "expected at least {x} match"),
74 ParseError::ExpectedLessItems(x) => write!(f, "expected {x} items or less"),
75 ParseError::NumberTooLarge(x) => write!(f, "expected number <= {x}"),
76 ParseError::NumberTooSmall(x) => write!(f, "expected number >= {x}"),
77 ParseError::NumberOutOfRange() => write!(f, "number out of range"),
78 ParseError::Custom(x) => f.write_str(x),
79 }
80 }
81}
82
83impl Error for ParseError {}
84
85impl PartialEq<ParseError> for Box<dyn Error> {
86 fn eq(&self, other: &ParseError) -> bool {
87 if let Some(pe) = self.downcast_ref::<ParseError>() {
88 pe == other
89 } else {
90 false
91 }
92 }
93}
94impl PartialEq<Box<dyn Error>> for ParseError {
95 fn eq(&self, other: &Box<dyn Error>) -> bool {
96 other == self
97 }
98}
99
100#[derive(Copy, Clone)]
101pub struct WithErrorMsg<P> {
102 pub(super) parser: P,
103 pub(super) message: &'static str,
104}
105impl<'i, P: Parser<'i>> Parser<'i> for WithErrorMsg<P> {
106 type Output = P::Output;
107 type Then<T: Parser<'i>> = Then2<Self, T>;
108
109 #[inline]
110 fn parse_ctx(
111 &self,
112 input: &'i [u8],
113 state: &mut ParseState<'i>,
114 commit: &mut bool,
115 tail: bool,
116 ) -> ParserResult<'i, Self::Output> {
117 let prev_remaining = state.error.map(|e| e.1);
118 self.parser
119 .parse_ctx(input, state, commit, tail)
120 .inspect_err(|_| {
121 let remaining = state.error.unwrap().1;
122 if prev_remaining != Some(remaining) {
123 state.error = Some((ParseError::Custom(self.message), remaining));
125 }
126 })
127 }
128}