oni_comb_parser_rs/core/
parse_error.rs

1use std::fmt;
2use std::fmt::Display;
3
4/// The enum type representing the parsing error.
5#[derive(Debug, Clone, PartialOrd, PartialEq)]
6pub enum ParseError<'a, I> {
7  /// Error when the parser's condition does not match
8  Mismatch {
9    input: &'a [I],
10    offset: usize,
11    length: usize,
12    message: String,
13  },
14  /// Error when conversion fails
15  Conversion {
16    input: &'a [I],
17    offset: usize,
18    length: usize,
19    message: String,
20  },
21  /// Error when parsing is interrupted or incomplete
22  Incomplete,
23  /// Error when the result deviates from expectations
24  Expect {
25    offset: usize,
26    inner: Box<ParseError<'a, I>>,
27    message: String,
28  },
29  /// Custom error
30  Custom {
31    offset: usize,
32    inner: Option<Box<ParseError<'a, I>>>,
33    message: String,
34  },
35}
36
37impl<'a, I> Display for ParseError<'a, I> {
38  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39    match self {
40      ParseError::Incomplete => write!(f, "Incomplete"),
41      ParseError::Mismatch {
42        ref message,
43        ref offset,
44        ..
45      } => write!(f, "Mismatch at {}: {}", offset, message),
46      ParseError::Conversion {
47        ref message,
48        ref offset,
49        ..
50      } => write!(f, "Conversion failed at {}: {}", offset, message),
51      ParseError::Expect {
52        ref message,
53        ref offset,
54        ref inner,
55      } => write!(f, "{} at {}: {}", message, offset, inner),
56      ParseError::Custom {
57        ref message,
58        ref offset,
59        inner: Some(ref inner),
60      } => write!(f, "{} at {}, (inner: {})", message, offset, inner),
61      ParseError::Custom {
62        ref message,
63        ref offset,
64        inner: None,
65      } => write!(f, "{} at {}", message, offset),
66    }
67  }
68}
69
70impl<'a> ParseError<'a, char> {
71  pub fn input_string(&self) -> Option<String> {
72    self.input().map(|chars| String::from_iter(chars))
73  }
74}
75
76impl<'a> ParseError<'a, u8> {
77  pub fn input_string(&self) -> Option<String> {
78    match self.input() {
79      Some(bytes) => match std::str::from_utf8(bytes) {
80        Ok(s) => Some(s.to_string()),
81        Err(_) => Some("".to_string()),
82      },
83      None => None,
84    }
85  }
86}
87
88impl<'a, I> ParseError<'a, I> {
89  pub fn input(&self) -> Option<&'a [I]> {
90    match self {
91      ParseError::Incomplete => None,
92      ParseError::Mismatch {
93        input, offset, length, ..
94      } => Some(&input[*offset..(*offset + length)]),
95      ParseError::Conversion {
96        input, offset, length, ..
97      } => Some(&input[*offset..(*offset + length)]),
98      ParseError::Expect { ref inner, .. } => inner.input(),
99      ParseError::Custom {
100        inner: Some(ref inner), ..
101      } => inner.input(),
102      ParseError::Custom { inner: None, .. } => None,
103    }
104  }
105
106  pub fn is_expect(&self) -> bool {
107    match self {
108      ParseError::Expect { .. } => true,
109      _ => false,
110    }
111  }
112
113  pub fn is_custom(&self) -> bool {
114    match self {
115      ParseError::Custom { .. } => true,
116      _ => false,
117    }
118  }
119
120  pub fn is_mismatch(&self) -> bool {
121    match self {
122      ParseError::Mismatch { .. } => true,
123      _ => false,
124    }
125  }
126
127  pub fn is_conversion(&self) -> bool {
128    match self {
129      ParseError::Conversion { .. } => true,
130      _ => false,
131    }
132  }
133
134  pub fn is_in_complete(&self) -> bool {
135    match self {
136      ParseError::Incomplete => true,
137      _ => false,
138    }
139  }
140
141  pub fn of_expect(offset: usize, inner: Box<ParseError<'a, I>>, message: String) -> Self {
142    ParseError::Expect { offset, inner, message }
143  }
144
145  pub fn of_custom(offset: usize, inner: Option<Box<ParseError<'a, I>>>, message: String) -> Self {
146    ParseError::Custom { offset, inner, message }
147  }
148
149  pub fn of_mismatch(input: &'a [I], offset: usize, length: usize, message: String) -> Self {
150    ParseError::Mismatch {
151      input,
152      offset,
153      length,
154      message,
155    }
156  }
157
158  pub fn of_conversion(input: &'a [I], offset: usize, length: usize, message: String) -> Self {
159    ParseError::Conversion {
160      input,
161      offset,
162      length,
163      message,
164    }
165  }
166
167  pub fn of_in_complete() -> Self {
168    ParseError::Incomplete
169  }
170}