1use crate::{TokenIter, TokenStream, TokenTree};
2use std::sync::Arc;
3
4pub type Result<T> = std::result::Result<T, Error>;
6
7#[derive(Clone)]
11pub enum ErrorKind {
12 NoError,
14 UnexpectedToken,
16 OutOfRange {
18 have: usize,
20 want: usize,
22 },
23 InfiniteLoop {
25 parser_type: &'static str,
27 },
28 Other {
30 reason: String,
32 },
33 Dynamic(Arc<dyn std::error::Error>),
35}
36
37#[must_use]
39#[derive(Clone)]
40pub struct Error {
41 pub kind: ErrorKind,
43 expected: &'static str,
45 refined: Option<&'static str>,
47 at: Option<TokenTree>,
48 after: Option<TokenIter>,
50 pos: usize,
53}
54
55impl Error {
56 #[allow(clippy::missing_errors_doc)]
58 pub const fn no_error() -> Self {
59 Error {
60 kind: ErrorKind::NoError,
61 expected: "<NoError>",
62 refined: None,
63 at: None,
64 after: None,
65 pos: 0,
66 }
67 }
68
69 #[allow(clippy::missing_errors_doc)]
71 pub fn upgrade<T>(&mut self, r: Result<T>) -> Result<T> {
72 if let Err(other) = &r {
73 if matches!(self.kind, ErrorKind::NoError) || other.pos > self.pos {
74 *self = other.clone();
75 }
76 }
77 r
78 }
79
80 pub fn set_pos(&mut self, pos: impl TokenCount) {
85 self.pos = pos.token_count();
86 }
87
88 #[must_use]
90 pub const fn pos(&self) -> usize {
91 self.pos
92 }
93
94 #[allow(clippy::missing_errors_doc)]
107 pub fn unexpected_token<T>(at: Option<TokenTree>, after: &TokenIter) -> Result<T> {
108 let pos = after.counter();
110 Err(Error {
111 kind: ErrorKind::UnexpectedToken,
112 expected: std::any::type_name::<T>(),
113 refined: None,
114 at,
115 after: Some(after.clone()),
116 pos,
117 })
118 }
119
120 #[allow(clippy::missing_errors_doc)]
122 pub fn unexpected_end<T>() -> Result<T> {
123 Err(Error {
124 kind: ErrorKind::UnexpectedToken,
125 expected: std::any::type_name::<T>(),
126 refined: None,
127 at: None,
128 after: None,
129 pos: usize::MAX,
130 })
131 }
132
133 #[allow(clippy::missing_errors_doc)]
136 pub fn out_of_range<const LIM: usize, T>(
137 have: usize,
138 at: Option<TokenTree>,
139 after: &TokenIter,
140 ) -> Result<T> {
141 let pos = after.counter();
142 Err(Error {
143 kind: ErrorKind::OutOfRange { have, want: LIM },
144 expected: std::any::type_name::<T>(),
145 refined: None,
146 at,
147 after: Some(after.clone()),
148 pos,
149 })
150 }
151
152 #[allow(clippy::missing_errors_doc)]
156 pub fn other<T>(at: Option<TokenTree>, after: &TokenIter, reason: String) -> Result<T> {
157 let pos = after.counter();
158 Err(Error {
159 kind: ErrorKind::Other { reason },
160 expected: std::any::type_name::<T>(),
161 refined: None,
162 at,
163 after: Some(after.clone()),
164 pos,
165 })
166 }
167
168 #[allow(clippy::missing_errors_doc)]
172 pub fn infinite_loop<T>(at: Option<TokenTree>, after: &TokenIter) -> Result<T> {
173 let pos = after.counter();
174 Err(Error {
175 kind: ErrorKind::InfiniteLoop {
176 parser_type: std::any::type_name::<T>(),
177 },
178 expected: std::any::type_name::<T>(),
179 refined: None,
180 at,
181 after: Some(after.clone()),
182 pos,
183 })
184 }
185
186 #[allow(clippy::missing_errors_doc)]
189 pub fn dynamic<T>(
190 at: Option<TokenTree>,
191 after: &TokenIter,
192 error: impl std::error::Error + Send + Sync + 'static,
193 ) -> Result<T> {
194 let pos = after.counter();
195 Err(Error {
196 kind: ErrorKind::Dynamic(Arc::new(error)),
197 expected: std::any::type_name::<T>(),
198 refined: None,
199 at,
200 after: Some(after.clone()),
201 pos,
202 })
203 }
204
205 #[must_use]
207 pub fn expected_type_name(&self) -> &'static str {
208 self.refined.unwrap_or(self.expected)
209 }
210
211 #[must_use]
213 pub const fn expected_original_type_name(&self) -> &'static str {
214 self.expected
215 }
216
217 #[must_use]
219 pub fn failed_at(&self) -> Option<TokenTree> {
220 self.at.clone()
221 }
222
223 #[must_use]
227 pub fn tokens_after(&self) -> TokenIter {
228 self.after
229 .clone()
230 .unwrap_or_else(|| TokenIter::new(TokenStream::new()))
231 }
232}
233
234impl std::error::Error for Error {}
235
236impl std::fmt::Debug for Error {
237 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
238 match &self.kind {
239 ErrorKind::NoError => {
240 write!(f, "NoError")
241 }
242 ErrorKind::UnexpectedToken => {
243 write!(
244 f,
245 "Unexpected token: expected {}, found {:?} at {:?}",
246 self.expected_type_name(),
247 OptionPP(&self.at),
248 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
249 )
250 }
251 ErrorKind::OutOfRange { have, want } => {
252 write!(
253 f,
254 "RangedRepeats out of bounds: expected {want}, requested {have} at {:?}",
255 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
256 )
257 }
258 ErrorKind::InfiniteLoop { parser_type } => {
259 write!(
260 f,
261 "Infinite loop detected: parser {} succeeded without consuming tokens at {:?}",
262 parser_type,
263 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
264 )
265 }
266 ErrorKind::Other { reason } => {
267 write!(
268 f,
269 "Parser failed: expected {}, because {reason}, found {:?} at {:?}",
270 self.expected_type_name(),
271 OptionPP(&self.at),
272 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
273 )
274 }
275 ErrorKind::Dynamic(err) => {
276 write!(
277 f,
278 "Parser failed: expected {}, because {err}, found {:?} at {:?}",
279 self.expected_type_name(),
280 OptionPP(&self.at),
281 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
282 )
283 }
284 }
285 }
286}
287
288impl std::fmt::Display for Error {
289 #[cfg_attr(test, mutants::skip)]
290 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
291 match &self.kind {
292 ErrorKind::NoError => {
293 write!(f, "NoError")
294 }
295 ErrorKind::UnexpectedToken => {
296 write!(
297 f,
298 "Unexpected token: expected {}, found {:?} at {:?}",
299 self.expected_type_name(),
300 OptionPP(&self.at),
301 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
302 )
303 }
304 ErrorKind::OutOfRange { have, want } => {
305 write!(
306 f,
307 "RangedRepeats out of bounds: expected {want}, requested {have} at {:?}",
308 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
309 )
310 }
311 ErrorKind::InfiniteLoop { parser_type } => {
312 write!(
313 f,
314 "Infinite loop detected: parser {} succeeded without consuming tokens at {:?}",
315 parser_type,
316 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
317 )
318 }
319 ErrorKind::Other { reason } => {
320 write!(
321 f,
322 "Parser failed: expected {}, because {reason}, found {:?} at {:?}",
323 self.expected_type_name(),
324 OptionPP(&self.at),
325 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
326 )
327 }
328 ErrorKind::Dynamic(err) => {
329 write!(
330 f,
331 "Parser failed: expected {}, because {err}, found {:?} at {:?}",
332 self.expected_type_name(),
333 OptionPP(&self.at),
334 OptionPP(&self.at.as_ref().map(|s| s.span().start()))
335 )
336 }
337 }
338 }
339}
340
341pub trait RefineErr {
349 #[must_use]
351 fn refine_err<T>(self) -> Self
352 where
353 Self: Sized;
354}
355
356impl<T> RefineErr for Result<T> {
357 fn refine_err<U>(mut self) -> Self
358 where
359 Self: Sized,
360 {
361 if let Err(ref mut err) = self {
362 err.refined = Some(std::any::type_name::<U>());
363 }
364 self
365 }
366}
367
368struct OptionPP<'a, T>(&'a Option<T>);
370
371impl<T: std::fmt::Debug> std::fmt::Debug for OptionPP<'_, T> {
372 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
373 match &self.0 {
374 Some(value) => write!(f, "{value:?}"),
375 None => write!(f, "None"),
376 }
377 }
378}
379
380impl<T: std::fmt::Display> std::fmt::Display for OptionPP<'_, T> {
381 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
382 match &self.0 {
383 Some(value) => write!(f, "{value}"),
384 None => write!(f, "None"),
385 }
386 }
387}
388
389#[test]
390fn test_optionpp() {
391 let none = format!("{}", OptionPP::<i32>(&None));
392 assert_eq!(none, "None");
393 let populated = format!("{}", OptionPP(&Some(42)));
394 assert_eq!(populated, "42");
395 let none = format!("{:?}", OptionPP::<i32>(&None));
396 assert_eq!(none, "None");
397 let populated = format!("{:?}", OptionPP(&Some(42)));
398 assert_eq!(populated, "42");
399}
400
401pub trait TokenCount {
406 fn token_count(self) -> usize;
408}
409
410impl TokenCount for usize {
412 #[inline]
413 fn token_count(self) -> usize {
414 self
415 }
416}
417
418impl TokenCount for &TokenIter {
419 #[inline]
420 fn token_count(self) -> usize {
421 self.counter()
422 }
423}
424
425impl TokenCount for &mut TokenIter {
426 #[inline]
427 fn token_count(self) -> usize {
428 self.counter()
429 }
430}
431
432impl TokenCount for &&mut TokenIter {
435 #[inline]
436 fn token_count(self) -> usize {
437 self.counter()
438 }
439}