1 //! # Error management
2 //!
3 //! Errors are designed with multiple needs in mind:
4 //! - Accumulate more [context][Parser::context] as the error goes up the parser chain
5 //! - Distinguish between [recoverable errors,
6 //!   unrecoverable errors, and more data is needed][ErrMode]
7 //! - Have a very low overhead, as errors are often discarded by the calling parser (examples: `repeat`, `alt`)
8 //! - Can be modified according to the user's needs, because some languages need a lot more information
9 //! - Help thread-through the [stream][crate::stream]
10 //!
11 //! To abstract these needs away from the user, generally `winnow` parsers use the [`PResult`]
12 //! alias, rather than [`Result`].  [`Parser::parse`] is a top-level operation
13 //! that can help convert to a `Result` for integrating with your application's error reporting.
14 //!
15 //! Error types include:
16 //! - `()`
17 //! - [`ErrorKind`]
18 //! - [`InputError`] (mostly for testing)
19 //! - [`ContextError`]
20 //! - [`TreeError`] (mostly for testing)
21 //! - [Custom errors][crate::_topic::error]
22 
23 #[cfg(feature = "alloc")]
24 use crate::lib::std::borrow::ToOwned;
25 use crate::lib::std::fmt;
26 use core::num::NonZeroUsize;
27 
28 use crate::stream::AsBStr;
29 use crate::stream::Stream;
30 #[allow(unused_imports)] // Here for intra-doc links
31 use crate::Parser;
32 
33 /// For use with [`Parser::parse_peek`] which allows the input stream to be threaded through a
34 /// parser.
35 ///
36 /// - `Ok((I, O))` is the remaining [input][crate::stream] and the parsed value
37 /// - [`Err(ErrMode<E>)`][ErrMode] is the error along with how to respond to it
38 ///
39 /// By default, the error type (`E`) is [`InputError`]
40 ///
41 /// When integrating into the result of the application, see
42 /// - [`Parser::parse`]
43 /// - [`ErrMode::into_inner`]
44 pub type IResult<I, O, E = InputError<I>> = PResult<(I, O), E>;
45 
46 /// For use with [`Parser::parse_next`]
47 ///
48 /// - `Ok(O)` is the parsed value
49 /// - [`Err(ErrMode<E>)`][ErrMode] is the error along with how to respond to it
50 ///
51 /// By default, the error type (`E`) is [`ContextError`].
52 ///
53 /// When integrating into the result of the application, see
54 /// - [`Parser::parse`]
55 /// - [`ErrMode::into_inner`]
56 pub type PResult<O, E = ContextError> = Result<O, ErrMode<E>>;
57 
58 /// Contains information on needed data if a parser returned `Incomplete`
59 ///
60 /// **Note:** This is only possible for `Stream` that are [partial][`crate::stream::StreamIsPartial`],
61 /// like [`Partial`][crate::Partial].
62 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
63 #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
64 pub enum Needed {
65     /// Needs more data, but we do not know how much
66     Unknown,
67     /// Contains the required data size in bytes
68     Size(NonZeroUsize),
69 }
70 
71 impl Needed {
72     /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
new(s: usize) -> Self73     pub fn new(s: usize) -> Self {
74         match NonZeroUsize::new(s) {
75             Some(sz) => Needed::Size(sz),
76             None => Needed::Unknown,
77         }
78     }
79 
80     /// Indicates if we know how many bytes we need
is_known(&self) -> bool81     pub fn is_known(&self) -> bool {
82         *self != Needed::Unknown
83     }
84 
85     /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
86     #[inline]
map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed87     pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
88         match self {
89             Needed::Unknown => Needed::Unknown,
90             Needed::Size(n) => Needed::new(f(n)),
91         }
92     }
93 }
94 
95 /// Add parse error state to [`ParserError`]s
96 #[derive(Debug, Clone, PartialEq)]
97 #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
98 pub enum ErrMode<E> {
99     /// There was not enough data to determine the appropriate action
100     ///
101     /// More data needs to be buffered before retrying the parse.
102     ///
103     /// This must only be set when the [`Stream`] is [partial][`crate::stream::StreamIsPartial`], like with
104     /// [`Partial`][crate::Partial]
105     ///
106     /// Convert this into an `Backtrack` with [`Parser::complete_err`]
107     Incomplete(Needed),
108     /// The parser failed with a recoverable error (the default).
109     ///
110     /// For example, a parser for json values might include a
111     /// [`dec_uint`][crate::ascii::dec_uint] as one case in an [`alt`][crate::combinator::alt]
112     /// combinator. If it fails, the next case should be tried.
113     Backtrack(E),
114     /// The parser had an unrecoverable error.
115     ///
116     /// The parser was on the right branch, so directly report it to the user rather than trying
117     /// other branches. You can use [`cut_err()`][crate::combinator::cut_err] combinator to switch
118     /// from `ErrMode::Backtrack` to `ErrMode::Cut`.
119     ///
120     /// For example, one case in an [`alt`][crate::combinator::alt] combinator found a unique prefix
121     /// and you want any further errors parsing the case to be reported to the user.
122     Cut(E),
123 }
124 
125 impl<E> ErrMode<E> {
126     /// Tests if the result is Incomplete
127     #[inline]
is_incomplete(&self) -> bool128     pub fn is_incomplete(&self) -> bool {
129         matches!(self, ErrMode::Incomplete(_))
130     }
131 
132     /// Prevent backtracking, bubbling the error up to the top
cut(self) -> Self133     pub fn cut(self) -> Self {
134         match self {
135             ErrMode::Backtrack(e) => ErrMode::Cut(e),
136             rest => rest,
137         }
138     }
139 
140     /// Enable backtracking support
backtrack(self) -> Self141     pub fn backtrack(self) -> Self {
142         match self {
143             ErrMode::Cut(e) => ErrMode::Backtrack(e),
144             rest => rest,
145         }
146     }
147 
148     /// Applies the given function to the inner error
map<E2, F>(self, f: F) -> ErrMode<E2> where F: FnOnce(E) -> E2,149     pub fn map<E2, F>(self, f: F) -> ErrMode<E2>
150     where
151         F: FnOnce(E) -> E2,
152     {
153         match self {
154             ErrMode::Incomplete(n) => ErrMode::Incomplete(n),
155             ErrMode::Cut(t) => ErrMode::Cut(f(t)),
156             ErrMode::Backtrack(t) => ErrMode::Backtrack(f(t)),
157         }
158     }
159 
160     /// Automatically converts between errors if the underlying type supports it
convert<F>(self) -> ErrMode<F> where E: ErrorConvert<F>,161     pub fn convert<F>(self) -> ErrMode<F>
162     where
163         E: ErrorConvert<F>,
164     {
165         self.map(ErrorConvert::convert)
166     }
167 
168     /// Unwrap the mode, returning the underlying error
169     ///
170     /// Returns `None` for [`ErrMode::Incomplete`]
171     #[cfg_attr(debug_assertions, track_caller)]
172     #[inline(always)]
into_inner(self) -> Option<E>173     pub fn into_inner(self) -> Option<E> {
174         match self {
175             ErrMode::Backtrack(e) | ErrMode::Cut(e) => Some(e),
176             ErrMode::Incomplete(_) => None,
177         }
178     }
179 }
180 
181 impl<I, E: ParserError<I>> ParserError<I> for ErrMode<E> {
182     #[inline(always)]
from_error_kind(input: &I, kind: ErrorKind) -> Self183     fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
184         ErrMode::Backtrack(E::from_error_kind(input, kind))
185     }
186 
187     #[cfg_attr(debug_assertions, track_caller)]
188     #[inline(always)]
assert(input: &I, message: &'static str) -> Self where I: crate::lib::std::fmt::Debug,189     fn assert(input: &I, message: &'static str) -> Self
190     where
191         I: crate::lib::std::fmt::Debug,
192     {
193         ErrMode::Backtrack(E::assert(input, message))
194     }
195 
196     #[inline]
append(self, input: &I, kind: ErrorKind) -> Self197     fn append(self, input: &I, kind: ErrorKind) -> Self {
198         match self {
199             ErrMode::Backtrack(e) => ErrMode::Backtrack(e.append(input, kind)),
200             e => e,
201         }
202     }
203 
or(self, other: Self) -> Self204     fn or(self, other: Self) -> Self {
205         match (self, other) {
206             (ErrMode::Backtrack(e), ErrMode::Backtrack(o)) => ErrMode::Backtrack(e.or(o)),
207             (ErrMode::Incomplete(e), _) | (_, ErrMode::Incomplete(e)) => ErrMode::Incomplete(e),
208             (ErrMode::Cut(e), _) | (_, ErrMode::Cut(e)) => ErrMode::Cut(e),
209         }
210     }
211 }
212 
213 impl<I, EXT, E> FromExternalError<I, EXT> for ErrMode<E>
214 where
215     E: FromExternalError<I, EXT>,
216 {
217     #[inline(always)]
from_external_error(input: &I, kind: ErrorKind, e: EXT) -> Self218     fn from_external_error(input: &I, kind: ErrorKind, e: EXT) -> Self {
219         ErrMode::Backtrack(E::from_external_error(input, kind, e))
220     }
221 }
222 
223 impl<I, C, E: AddContext<I, C>> AddContext<I, C> for ErrMode<E> {
224     #[inline(always)]
add_context(self, input: &I, ctx: C) -> Self225     fn add_context(self, input: &I, ctx: C) -> Self {
226         self.map(|err| err.add_context(input, ctx))
227     }
228 }
229 
230 impl<T: Clone> ErrMode<InputError<T>> {
231     /// Maps `ErrMode<InputError<T>>` to `ErrMode<InputError<U>>` with the given `F: T -> U`
map_input<U: Clone, F>(self, f: F) -> ErrMode<InputError<U>> where F: FnOnce(T) -> U,232     pub fn map_input<U: Clone, F>(self, f: F) -> ErrMode<InputError<U>>
233     where
234         F: FnOnce(T) -> U,
235     {
236         match self {
237             ErrMode::Incomplete(n) => ErrMode::Incomplete(n),
238             ErrMode::Cut(InputError { input, kind }) => ErrMode::Cut(InputError {
239                 input: f(input),
240                 kind,
241             }),
242             ErrMode::Backtrack(InputError { input, kind }) => ErrMode::Backtrack(InputError {
243                 input: f(input),
244                 kind,
245             }),
246         }
247     }
248 }
249 
250 impl<E: Eq> Eq for ErrMode<E> {}
251 
252 impl<E> fmt::Display for ErrMode<E>
253 where
254     E: fmt::Debug,
255 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result256     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257         match self {
258             ErrMode::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
259             ErrMode::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
260             ErrMode::Cut(c) => write!(f, "Parsing Failure: {:?}", c),
261             ErrMode::Backtrack(c) => write!(f, "Parsing Error: {:?}", c),
262         }
263     }
264 }
265 
266 /// The basic [`Parser`] trait for errors
267 ///
268 /// It provides methods to create an error from some combinators,
269 /// and combine existing errors in combinators like `alt`.
270 pub trait ParserError<I>: Sized {
271     /// Creates an error from the input position and an [`ErrorKind`]
from_error_kind(input: &I, kind: ErrorKind) -> Self272     fn from_error_kind(input: &I, kind: ErrorKind) -> Self;
273 
274     /// Process a parser assertion
275     #[cfg_attr(debug_assertions, track_caller)]
assert(input: &I, _message: &'static str) -> Self where I: crate::lib::std::fmt::Debug,276     fn assert(input: &I, _message: &'static str) -> Self
277     where
278         I: crate::lib::std::fmt::Debug,
279     {
280         #[cfg(debug_assertions)]
281         panic!("assert `{}` failed at {:#?}", _message, input);
282         #[cfg(not(debug_assertions))]
283         Self::from_error_kind(input, ErrorKind::Assert)
284     }
285 
286     /// Like [`ParserError::from_error_kind`] but merges it with the existing error.
287     ///
288     /// This is useful when backtracking through a parse tree, accumulating error context on the
289     /// way.
append(self, input: &I, kind: ErrorKind) -> Self290     fn append(self, input: &I, kind: ErrorKind) -> Self;
291 
292     /// Combines errors from two different parse branches.
293     ///
294     /// For example, this would be used by [`alt`][crate::combinator::alt] to report the error from
295     /// each case.
296     #[inline]
or(self, other: Self) -> Self297     fn or(self, other: Self) -> Self {
298         other
299     }
300 }
301 
302 /// Used by [`Parser::context`] to add custom data to error while backtracking
303 ///
304 /// May be implemented multiple times for different kinds of context.
305 pub trait AddContext<I, C = &'static str>: Sized {
306     /// Append to an existing error custom data
307     ///
308     /// This is used mainly by [`Parser::context`], to add user friendly information
309     /// to errors when backtracking through a parse tree
310     #[inline]
add_context(self, _input: &I, _ctx: C) -> Self311     fn add_context(self, _input: &I, _ctx: C) -> Self {
312         self
313     }
314 }
315 
316 /// Capture context from when an error was recovered
317 pub trait FromRecoverableError<I: Stream, E> {
318     /// Capture context from when an error was recovered
from_recoverable_error( token_start: &<I as Stream>::Checkpoint, err_start: &<I as Stream>::Checkpoint, input: &I, e: E, ) -> Self319     fn from_recoverable_error(
320         token_start: &<I as Stream>::Checkpoint,
321         err_start: &<I as Stream>::Checkpoint,
322         input: &I,
323         e: E,
324     ) -> Self;
325 }
326 
327 /// Create a new error with an external error, from [`std::str::FromStr`]
328 ///
329 /// This trait is required by the [`Parser::try_map`] combinator.
330 pub trait FromExternalError<I, E> {
331     /// Like [`ParserError::from_error_kind`] but also include an external error.
from_external_error(input: &I, kind: ErrorKind, e: E) -> Self332     fn from_external_error(input: &I, kind: ErrorKind, e: E) -> Self;
333 }
334 
335 /// Equivalent of `From` implementation to avoid orphan rules in bits parsers
336 pub trait ErrorConvert<E> {
337     /// Transform to another error type
convert(self) -> E338     fn convert(self) -> E;
339 }
340 
341 /// Capture input on error
342 ///
343 /// This is useful for testing of generic parsers to ensure the error happens at the right
344 /// location.
345 ///
346 /// **Note:** [context][Parser::context] and inner errors (like from [`Parser::try_map`]) will be
347 /// dropped.
348 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
349 pub struct InputError<I: Clone> {
350     /// The input stream, pointing to the location where the error occurred
351     pub input: I,
352     /// A rudimentary error kind
353     pub kind: ErrorKind,
354 }
355 
356 impl<I: Clone> InputError<I> {
357     /// Creates a new basic error
358     #[inline]
new(input: I, kind: ErrorKind) -> Self359     pub fn new(input: I, kind: ErrorKind) -> Self {
360         Self { input, kind }
361     }
362 
363     /// Translate the input type
364     #[inline]
map_input<I2: Clone, O: Fn(I) -> I2>(self, op: O) -> InputError<I2>365     pub fn map_input<I2: Clone, O: Fn(I) -> I2>(self, op: O) -> InputError<I2> {
366         InputError {
367             input: op(self.input),
368             kind: self.kind,
369         }
370     }
371 }
372 
373 #[cfg(feature = "alloc")]
374 impl<'i, I: ToOwned> InputError<&'i I>
375 where
376     <I as ToOwned>::Owned: Clone,
377 {
378     /// Obtaining ownership
into_owned(self) -> InputError<<I as ToOwned>::Owned>379     pub fn into_owned(self) -> InputError<<I as ToOwned>::Owned> {
380         self.map_input(ToOwned::to_owned)
381     }
382 }
383 
384 impl<I: Clone> ParserError<I> for InputError<I> {
385     #[inline]
from_error_kind(input: &I, kind: ErrorKind) -> Self386     fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
387         Self {
388             input: input.clone(),
389             kind,
390         }
391     }
392 
393     #[inline]
append(self, _: &I, _: ErrorKind) -> Self394     fn append(self, _: &I, _: ErrorKind) -> Self {
395         self
396     }
397 }
398 
399 impl<I: Clone, C> AddContext<I, C> for InputError<I> {}
400 
401 impl<I: Clone + Stream> FromRecoverableError<I, Self> for InputError<I> {
402     #[inline]
from_recoverable_error( _token_start: &<I as Stream>::Checkpoint, _err_start: &<I as Stream>::Checkpoint, _input: &I, e: Self, ) -> Self403     fn from_recoverable_error(
404         _token_start: &<I as Stream>::Checkpoint,
405         _err_start: &<I as Stream>::Checkpoint,
406         _input: &I,
407         e: Self,
408     ) -> Self {
409         e
410     }
411 }
412 
413 impl<I: Clone, E> FromExternalError<I, E> for InputError<I> {
414     /// Create a new error from an input position and an external error
415     #[inline]
from_external_error(input: &I, kind: ErrorKind, _e: E) -> Self416     fn from_external_error(input: &I, kind: ErrorKind, _e: E) -> Self {
417         Self {
418             input: input.clone(),
419             kind,
420         }
421     }
422 }
423 
424 impl<I: Clone> ErrorConvert<InputError<(I, usize)>> for InputError<I> {
425     #[inline]
convert(self) -> InputError<(I, usize)>426     fn convert(self) -> InputError<(I, usize)> {
427         InputError {
428             input: (self.input, 0),
429             kind: self.kind,
430         }
431     }
432 }
433 
434 impl<I: Clone> ErrorConvert<InputError<I>> for InputError<(I, usize)> {
435     #[inline]
convert(self) -> InputError<I>436     fn convert(self) -> InputError<I> {
437         InputError {
438             input: self.input.0,
439             kind: self.kind,
440         }
441     }
442 }
443 
444 /// The Display implementation allows the `std::error::Error` implementation
445 impl<I: Clone + fmt::Display> fmt::Display for InputError<I> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result446     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447         write!(
448             f,
449             "{} error starting at: {}",
450             self.kind.description(),
451             self.input
452         )
453     }
454 }
455 
456 #[cfg(feature = "std")]
457 impl<I: Clone + fmt::Debug + fmt::Display + Sync + Send + 'static> std::error::Error
458     for InputError<I>
459 {
460 }
461 
462 impl<I> ParserError<I> for () {
463     #[inline]
from_error_kind(_: &I, _: ErrorKind) -> Self464     fn from_error_kind(_: &I, _: ErrorKind) -> Self {}
465 
466     #[inline]
append(self, _: &I, _: ErrorKind) -> Self467     fn append(self, _: &I, _: ErrorKind) -> Self {}
468 }
469 
470 impl<I, C> AddContext<I, C> for () {}
471 
472 impl<I: Stream> FromRecoverableError<I, Self> for () {
473     #[inline]
from_recoverable_error( _token_start: &<I as Stream>::Checkpoint, _err_start: &<I as Stream>::Checkpoint, _input: &I, (): Self, ) -> Self474     fn from_recoverable_error(
475         _token_start: &<I as Stream>::Checkpoint,
476         _err_start: &<I as Stream>::Checkpoint,
477         _input: &I,
478         (): Self,
479     ) -> Self {
480     }
481 }
482 
483 impl<I, E> FromExternalError<I, E> for () {
484     #[inline]
from_external_error(_input: &I, _kind: ErrorKind, _e: E) -> Self485     fn from_external_error(_input: &I, _kind: ErrorKind, _e: E) -> Self {}
486 }
487 
488 impl ErrorConvert<()> for () {
489     #[inline]
convert(self)490     fn convert(self) {}
491 }
492 
493 /// Accumulate context while backtracking errors
494 #[derive(Debug)]
495 pub struct ContextError<C = StrContext> {
496     #[cfg(feature = "alloc")]
497     context: crate::lib::std::vec::Vec<C>,
498     #[cfg(not(feature = "alloc"))]
499     context: core::marker::PhantomData<C>,
500     #[cfg(feature = "std")]
501     cause: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
502 }
503 
504 impl<C> ContextError<C> {
505     /// Create an empty error
506     #[inline]
new() -> Self507     pub fn new() -> Self {
508         Self {
509             context: Default::default(),
510             #[cfg(feature = "std")]
511             cause: None,
512         }
513     }
514 
515     /// Access context from [`Parser::context`]
516     #[inline]
517     #[cfg(feature = "alloc")]
context(&self) -> impl Iterator<Item = &C>518     pub fn context(&self) -> impl Iterator<Item = &C> {
519         self.context.iter()
520     }
521 
522     /// Originating [`std::error::Error`]
523     #[inline]
524     #[cfg(feature = "std")]
cause(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)>525     pub fn cause(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)> {
526         self.cause.as_deref()
527     }
528 }
529 
530 impl<C: Clone> Clone for ContextError<C> {
clone(&self) -> Self531     fn clone(&self) -> Self {
532         Self {
533             context: self.context.clone(),
534             #[cfg(feature = "std")]
535             cause: self.cause.as_ref().map(|e| e.to_string().into()),
536         }
537     }
538 }
539 
540 impl<C> Default for ContextError<C> {
541     #[inline]
default() -> Self542     fn default() -> Self {
543         Self::new()
544     }
545 }
546 
547 impl<I, C> ParserError<I> for ContextError<C> {
548     #[inline]
from_error_kind(_input: &I, _kind: ErrorKind) -> Self549     fn from_error_kind(_input: &I, _kind: ErrorKind) -> Self {
550         Self::new()
551     }
552 
553     #[inline]
append(self, _input: &I, _kind: ErrorKind) -> Self554     fn append(self, _input: &I, _kind: ErrorKind) -> Self {
555         self
556     }
557 
558     #[inline]
or(self, other: Self) -> Self559     fn or(self, other: Self) -> Self {
560         other
561     }
562 }
563 
564 impl<C, I> AddContext<I, C> for ContextError<C> {
565     #[inline]
add_context(mut self, _input: &I, ctx: C) -> Self566     fn add_context(mut self, _input: &I, ctx: C) -> Self {
567         #[cfg(feature = "alloc")]
568         self.context.push(ctx);
569         self
570     }
571 }
572 
573 impl<I: Stream, C> FromRecoverableError<I, Self> for ContextError<C> {
574     #[inline]
from_recoverable_error( _token_start: &<I as Stream>::Checkpoint, _err_start: &<I as Stream>::Checkpoint, _input: &I, e: Self, ) -> Self575     fn from_recoverable_error(
576         _token_start: &<I as Stream>::Checkpoint,
577         _err_start: &<I as Stream>::Checkpoint,
578         _input: &I,
579         e: Self,
580     ) -> Self {
581         e
582     }
583 }
584 
585 #[cfg(feature = "std")]
586 impl<C, I, E: std::error::Error + Send + Sync + 'static> FromExternalError<I, E>
587     for ContextError<C>
588 {
589     #[inline]
from_external_error(_input: &I, _kind: ErrorKind, e: E) -> Self590     fn from_external_error(_input: &I, _kind: ErrorKind, e: E) -> Self {
591         let mut err = Self::new();
592         {
593             err.cause = Some(Box::new(e));
594         }
595         err
596     }
597 }
598 
599 // HACK: This is more general than `std`, making the features non-additive
600 #[cfg(not(feature = "std"))]
601 impl<C, I, E: Send + Sync + 'static> FromExternalError<I, E> for ContextError<C> {
602     #[inline]
from_external_error(_input: &I, _kind: ErrorKind, _e: E) -> Self603     fn from_external_error(_input: &I, _kind: ErrorKind, _e: E) -> Self {
604         let err = Self::new();
605         err
606     }
607 }
608 
609 // For tests
610 impl<C: core::cmp::PartialEq> core::cmp::PartialEq for ContextError<C> {
eq(&self, other: &Self) -> bool611     fn eq(&self, other: &Self) -> bool {
612         #[cfg(feature = "alloc")]
613         {
614             if self.context != other.context {
615                 return false;
616             }
617         }
618         #[cfg(feature = "std")]
619         {
620             if self.cause.as_ref().map(ToString::to_string)
621                 != other.cause.as_ref().map(ToString::to_string)
622             {
623                 return false;
624             }
625         }
626 
627         true
628     }
629 }
630 
631 impl crate::lib::std::fmt::Display for ContextError<StrContext> {
fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result632     fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
633         #[cfg(feature = "alloc")]
634         {
635             let expression = self.context().find_map(|c| match c {
636                 StrContext::Label(c) => Some(c),
637                 _ => None,
638             });
639             let expected = self
640                 .context()
641                 .filter_map(|c| match c {
642                     StrContext::Expected(c) => Some(c),
643                     _ => None,
644                 })
645                 .collect::<crate::lib::std::vec::Vec<_>>();
646 
647             let mut newline = false;
648 
649             if let Some(expression) = expression {
650                 newline = true;
651 
652                 write!(f, "invalid {}", expression)?;
653             }
654 
655             if !expected.is_empty() {
656                 if newline {
657                     writeln!(f)?;
658                 }
659                 newline = true;
660 
661                 write!(f, "expected ")?;
662                 for (i, expected) in expected.iter().enumerate() {
663                     if i != 0 {
664                         write!(f, ", ")?;
665                     }
666                     write!(f, "{}", expected)?;
667                 }
668             }
669             #[cfg(feature = "std")]
670             {
671                 if let Some(cause) = self.cause() {
672                     if newline {
673                         writeln!(f)?;
674                     }
675                     write!(f, "{}", cause)?;
676                 }
677             }
678         }
679 
680         Ok(())
681     }
682 }
683 
684 /// Additional parse context for [`ContextError`] added via [`Parser::context`]
685 #[derive(Clone, Debug, PartialEq, Eq)]
686 #[non_exhaustive]
687 pub enum StrContext {
688     /// Description of what is currently being parsed
689     Label(&'static str),
690     /// Grammar item that was expected
691     Expected(StrContextValue),
692 }
693 
694 impl crate::lib::std::fmt::Display for StrContext {
fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result695     fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
696         match self {
697             Self::Label(name) => write!(f, "invalid {name}"),
698             Self::Expected(value) => write!(f, "expected {value}"),
699         }
700     }
701 }
702 
703 /// See [`StrContext`]
704 #[derive(Clone, Debug, PartialEq, Eq)]
705 #[non_exhaustive]
706 pub enum StrContextValue {
707     /// A [`char`] token
708     CharLiteral(char),
709     /// A [`&str`] token
710     StringLiteral(&'static str),
711     /// A description of what was being parsed
712     Description(&'static str),
713 }
714 
715 impl From<char> for StrContextValue {
716     #[inline]
from(inner: char) -> Self717     fn from(inner: char) -> Self {
718         Self::CharLiteral(inner)
719     }
720 }
721 
722 impl From<&'static str> for StrContextValue {
723     #[inline]
from(inner: &'static str) -> Self724     fn from(inner: &'static str) -> Self {
725         Self::StringLiteral(inner)
726     }
727 }
728 
729 impl crate::lib::std::fmt::Display for StrContextValue {
fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result730     fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
731         match self {
732             Self::CharLiteral('\n') => "newline".fmt(f),
733             Self::CharLiteral('`') => "'`'".fmt(f),
734             Self::CharLiteral(c) if c.is_ascii_control() => {
735                 write!(f, "`{}`", c.escape_debug())
736             }
737             Self::CharLiteral(c) => write!(f, "`{}`", c),
738             Self::StringLiteral(c) => write!(f, "`{}`", c),
739             Self::Description(c) => write!(f, "{}", c),
740         }
741     }
742 }
743 
744 /// Trace all error paths, particularly for tests
745 #[derive(Debug)]
746 #[cfg(feature = "std")]
747 pub enum TreeError<I, C = StrContext> {
748     /// Initial error that kicked things off
749     Base(TreeErrorBase<I>),
750     /// Traces added to the error while walking back up the stack
751     Stack {
752         /// Initial error that kicked things off
753         base: Box<Self>,
754         /// Traces added to the error while walking back up the stack
755         stack: Vec<TreeErrorFrame<I, C>>,
756     },
757     /// All failed branches of an `alt`
758     Alt(Vec<Self>),
759 }
760 
761 /// See [`TreeError::Stack`]
762 #[derive(Debug)]
763 #[cfg(feature = "std")]
764 pub enum TreeErrorFrame<I, C = StrContext> {
765     /// See [`ParserError::append`]
766     Kind(TreeErrorBase<I>),
767     /// See [`AddContext::add_context`]
768     Context(TreeErrorContext<I, C>),
769 }
770 
771 /// See [`TreeErrorFrame::Kind`], [`ParserError::append`]
772 #[derive(Debug)]
773 #[cfg(feature = "std")]
774 pub struct TreeErrorBase<I> {
775     /// Parsed input, at the location where the error occurred
776     pub input: I,
777     /// Debug context
778     pub kind: ErrorKind,
779     /// See [`FromExternalError::from_external_error`]
780     pub cause: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
781 }
782 
783 /// See [`TreeErrorFrame::Context`], [`AddContext::add_context`]
784 #[derive(Debug)]
785 #[cfg(feature = "std")]
786 pub struct TreeErrorContext<I, C = StrContext> {
787     /// Parsed input, at the location where the error occurred
788     pub input: I,
789     /// See [`AddContext::add_context`]
790     pub context: C,
791 }
792 
793 #[cfg(feature = "std")]
794 impl<'i, I: ToOwned, C> TreeError<&'i I, C>
795 where
796     <I as ToOwned>::Owned: Clone,
797 {
798     /// Obtaining ownership
into_owned(self) -> TreeError<<I as ToOwned>::Owned, C>799     pub fn into_owned(self) -> TreeError<<I as ToOwned>::Owned, C> {
800         self.map_input(ToOwned::to_owned)
801     }
802 }
803 
804 #[cfg(feature = "std")]
805 impl<I, C> TreeError<I, C>
806 where
807     I: Clone,
808 {
809     /// Translate the input type
map_input<I2: Clone, O: Clone + Fn(I) -> I2>(self, op: O) -> TreeError<I2, C>810     pub fn map_input<I2: Clone, O: Clone + Fn(I) -> I2>(self, op: O) -> TreeError<I2, C> {
811         match self {
812             TreeError::Base(base) => TreeError::Base(TreeErrorBase {
813                 input: op(base.input),
814                 kind: base.kind,
815                 cause: base.cause,
816             }),
817             TreeError::Stack { base, stack } => {
818                 let base = Box::new(base.map_input(op.clone()));
819                 let stack = stack
820                     .into_iter()
821                     .map(|frame| match frame {
822                         TreeErrorFrame::Kind(kind) => TreeErrorFrame::Kind(TreeErrorBase {
823                             input: op(kind.input),
824                             kind: kind.kind,
825                             cause: kind.cause,
826                         }),
827                         TreeErrorFrame::Context(context) => {
828                             TreeErrorFrame::Context(TreeErrorContext {
829                                 input: op(context.input),
830                                 context: context.context,
831                             })
832                         }
833                     })
834                     .collect();
835                 TreeError::Stack { base, stack }
836             }
837             TreeError::Alt(alt) => {
838                 TreeError::Alt(alt.into_iter().map(|e| e.map_input(op.clone())).collect())
839             }
840         }
841     }
842 
append_frame(self, frame: TreeErrorFrame<I, C>) -> Self843     fn append_frame(self, frame: TreeErrorFrame<I, C>) -> Self {
844         match self {
845             TreeError::Stack { base, mut stack } => {
846                 stack.push(frame);
847                 TreeError::Stack { base, stack }
848             }
849             base => TreeError::Stack {
850                 base: Box::new(base),
851                 stack: vec![frame],
852             },
853         }
854     }
855 }
856 
857 #[cfg(feature = "std")]
858 impl<I, C> ParserError<I> for TreeError<I, C>
859 where
860     I: Clone,
861 {
from_error_kind(input: &I, kind: ErrorKind) -> Self862     fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
863         TreeError::Base(TreeErrorBase {
864             input: input.clone(),
865             kind,
866             cause: None,
867         })
868     }
869 
append(self, input: &I, kind: ErrorKind) -> Self870     fn append(self, input: &I, kind: ErrorKind) -> Self {
871         let frame = TreeErrorFrame::Kind(TreeErrorBase {
872             input: input.clone(),
873             kind,
874             cause: None,
875         });
876         self.append_frame(frame)
877     }
878 
or(self, other: Self) -> Self879     fn or(self, other: Self) -> Self {
880         match (self, other) {
881             (TreeError::Alt(mut first), TreeError::Alt(second)) => {
882                 // Just in case an implementation does a divide-and-conquer algorithm
883                 //
884                 // To prevent mixing `alt`s at different levels, parsers should
885                 // `alt_err.append(input, ErrorKind::Alt)`.
886                 first.extend(second);
887                 TreeError::Alt(first)
888             }
889             (TreeError::Alt(mut alt), new) | (new, TreeError::Alt(mut alt)) => {
890                 alt.push(new);
891                 TreeError::Alt(alt)
892             }
893             (first, second) => TreeError::Alt(vec![first, second]),
894         }
895     }
896 }
897 
898 #[cfg(feature = "std")]
899 impl<I, C> AddContext<I, C> for TreeError<I, C>
900 where
901     I: Clone,
902 {
add_context(self, input: &I, context: C) -> Self903     fn add_context(self, input: &I, context: C) -> Self {
904         let frame = TreeErrorFrame::Context(TreeErrorContext {
905             input: input.clone(),
906             context,
907         });
908         self.append_frame(frame)
909     }
910 }
911 
912 #[cfg(feature = "std")]
913 impl<I: Clone + Stream, C> FromRecoverableError<I, Self> for TreeError<I, C> {
914     #[inline]
from_recoverable_error( _token_start: &<I as Stream>::Checkpoint, _err_start: &<I as Stream>::Checkpoint, _input: &I, e: Self, ) -> Self915     fn from_recoverable_error(
916         _token_start: &<I as Stream>::Checkpoint,
917         _err_start: &<I as Stream>::Checkpoint,
918         _input: &I,
919         e: Self,
920     ) -> Self {
921         e
922     }
923 }
924 
925 #[cfg(feature = "std")]
926 impl<I, C, E: std::error::Error + Send + Sync + 'static> FromExternalError<I, E> for TreeError<I, C>
927 where
928     I: Clone,
929 {
from_external_error(input: &I, kind: ErrorKind, e: E) -> Self930     fn from_external_error(input: &I, kind: ErrorKind, e: E) -> Self {
931         TreeError::Base(TreeErrorBase {
932             input: input.clone(),
933             kind,
934             cause: Some(Box::new(e)),
935         })
936     }
937 }
938 
939 #[cfg(feature = "std")]
940 impl<I, C> TreeError<I, C>
941 where
942     I: Clone + crate::lib::std::fmt::Display,
943     C: fmt::Display,
944 {
write(&self, f: &mut fmt::Formatter<'_>, indent: usize) -> fmt::Result945     fn write(&self, f: &mut fmt::Formatter<'_>, indent: usize) -> fmt::Result {
946         let child_indent = indent + 2;
947         match self {
948             TreeError::Base(base) => {
949                 writeln!(f, "{:indent$}{base}", "")?;
950             }
951             TreeError::Stack { base, stack } => {
952                 base.write(f, indent)?;
953                 for (level, frame) in stack.iter().enumerate() {
954                     match frame {
955                         TreeErrorFrame::Kind(frame) => {
956                             writeln!(f, "{:child_indent$}{level}: {frame}", "")?;
957                         }
958                         TreeErrorFrame::Context(frame) => {
959                             writeln!(f, "{:child_indent$}{level}: {frame}", "")?;
960                         }
961                     }
962                 }
963             }
964             TreeError::Alt(alt) => {
965                 writeln!(f, "{:indent$}during one of:", "")?;
966                 for child in alt {
967                     child.write(f, child_indent)?;
968                 }
969             }
970         }
971 
972         Ok(())
973     }
974 }
975 
976 #[cfg(feature = "std")]
977 impl<I: Clone + fmt::Display> fmt::Display for TreeErrorBase<I> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result978     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
979         if let Some(cause) = self.cause.as_ref() {
980             write!(f, "caused by {cause}")?;
981         } else {
982             let kind = self.kind.description();
983             write!(f, "in {kind}")?;
984         }
985         let input = abbreviate(self.input.to_string());
986         write!(f, " at '{input}'")?;
987         Ok(())
988     }
989 }
990 
991 #[cfg(feature = "std")]
992 impl<I: Clone + fmt::Display, C: fmt::Display> fmt::Display for TreeErrorContext<I, C> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result993     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
994         let context = &self.context;
995         let input = abbreviate(self.input.to_string());
996         write!(f, "{context} at '{input}'")?;
997         Ok(())
998     }
999 }
1000 
1001 #[cfg(feature = "std")]
1002 impl<
1003         I: Clone + fmt::Debug + fmt::Display + Sync + Send + 'static,
1004         C: fmt::Display + fmt::Debug,
1005     > std::error::Error for TreeError<I, C>
1006 {
1007 }
1008 
1009 #[cfg(feature = "std")]
abbreviate(input: String) -> String1010 fn abbreviate(input: String) -> String {
1011     let mut abbrev = None;
1012 
1013     if let Some((line, _)) = input.split_once('\n') {
1014         abbrev = Some(line);
1015     }
1016 
1017     let max_len = 20;
1018     let current = abbrev.unwrap_or(&input);
1019     if max_len < current.len() {
1020         if let Some((index, _)) = current.char_indices().nth(max_len) {
1021             abbrev = Some(&current[..index]);
1022         }
1023     }
1024 
1025     if let Some(abbrev) = abbrev {
1026         format!("{abbrev}...")
1027     } else {
1028         input
1029     }
1030 }
1031 
1032 #[cfg(feature = "std")]
1033 impl<I: Clone + fmt::Display, C: fmt::Display> fmt::Display for TreeError<I, C> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1034     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1035         self.write(f, 0)
1036     }
1037 }
1038 
1039 /// Deprecated, replaced with [`ContextError`]
1040 #[cfg(feature = "std")]
1041 #[allow(deprecated)]
1042 #[deprecated(since = "0.5.8", note = "Replaced with `ContextError`")]
1043 #[derive(Clone, Debug, Eq, PartialEq)]
1044 pub struct VerboseError<I: Clone, C = &'static str> {
1045     /// Accumulated error information
1046     pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind<C>)>,
1047 }
1048 
1049 #[cfg(feature = "std")]
1050 #[allow(deprecated)]
1051 impl<'i, I: ToOwned, C> VerboseError<&'i I, C>
1052 where
1053     <I as ToOwned>::Owned: Clone,
1054 {
1055     /// Obtaining ownership
into_owned(self) -> VerboseError<<I as ToOwned>::Owned, C>1056     pub fn into_owned(self) -> VerboseError<<I as ToOwned>::Owned, C> {
1057         self.map_input(ToOwned::to_owned)
1058     }
1059 }
1060 
1061 #[cfg(feature = "std")]
1062 #[allow(deprecated)]
1063 impl<I: Clone, C> VerboseError<I, C> {
1064     /// Translate the input type
map_input<I2: Clone, O>(self, op: O) -> VerboseError<I2, C> where O: Fn(I) -> I2,1065     pub fn map_input<I2: Clone, O>(self, op: O) -> VerboseError<I2, C>
1066     where
1067         O: Fn(I) -> I2,
1068     {
1069         VerboseError {
1070             errors: self.errors.into_iter().map(|(i, k)| (op(i), k)).collect(),
1071         }
1072     }
1073 }
1074 
1075 /// Deprecated, replaced with [`ContextError`]
1076 #[cfg(feature = "std")]
1077 #[deprecated(since = "0.5.8", note = "Replaced with `ContextError`")]
1078 #[derive(Clone, Debug, Eq, PartialEq)]
1079 pub enum VerboseErrorKind<C = &'static str> {
1080     /// Static string added by the `context` function
1081     Context(C),
1082     /// Error kind given by various parsers
1083     Winnow(ErrorKind),
1084 }
1085 
1086 #[cfg(feature = "std")]
1087 #[allow(deprecated)]
1088 impl<I: Clone, C> ParserError<I> for VerboseError<I, C> {
from_error_kind(input: &I, kind: ErrorKind) -> Self1089     fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
1090         VerboseError {
1091             errors: vec![(input.clone(), VerboseErrorKind::Winnow(kind))],
1092         }
1093     }
1094 
append(mut self, input: &I, kind: ErrorKind) -> Self1095     fn append(mut self, input: &I, kind: ErrorKind) -> Self {
1096         self.errors
1097             .push((input.clone(), VerboseErrorKind::Winnow(kind)));
1098         self
1099     }
1100 }
1101 
1102 #[cfg(feature = "std")]
1103 #[allow(deprecated)]
1104 impl<I: Clone, C> AddContext<I, C> for VerboseError<I, C> {
add_context(mut self, input: &I, ctx: C) -> Self1105     fn add_context(mut self, input: &I, ctx: C) -> Self {
1106         self.errors
1107             .push((input.clone(), VerboseErrorKind::Context(ctx)));
1108         self
1109     }
1110 }
1111 
1112 #[cfg(feature = "std")]
1113 #[allow(deprecated)]
1114 impl<I: Clone, C, E> FromExternalError<I, E> for VerboseError<I, C> {
1115     /// Create a new error from an input position and an external error
from_external_error(input: &I, kind: ErrorKind, _e: E) -> Self1116     fn from_external_error(input: &I, kind: ErrorKind, _e: E) -> Self {
1117         Self::from_error_kind(input, kind)
1118     }
1119 }
1120 
1121 #[cfg(feature = "std")]
1122 #[allow(deprecated)]
1123 impl<I: Clone + fmt::Display, C: fmt::Display> fmt::Display for VerboseError<I, C> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1124     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1125         writeln!(f, "Parse error:")?;
1126         for (input, error) in &self.errors {
1127             match error {
1128                 VerboseErrorKind::Winnow(e) => writeln!(f, "{} at: {}", e.description(), input)?,
1129                 VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?,
1130             }
1131         }
1132 
1133         Ok(())
1134     }
1135 }
1136 
1137 #[cfg(feature = "std")]
1138 #[allow(deprecated)]
1139 impl<
1140         I: Clone + fmt::Debug + fmt::Display + Sync + Send + 'static,
1141         C: fmt::Display + fmt::Debug,
1142     > std::error::Error for VerboseError<I, C>
1143 {
1144 }
1145 
1146 /// Provide some minor debug context for errors
1147 #[rustfmt::skip]
1148 #[derive(Debug,PartialEq,Eq,Hash,Clone,Copy)]
1149 #[allow(missing_docs)]
1150 pub enum ErrorKind {
1151   Assert,
1152   Token,
1153   Tag,
1154   Alt,
1155   Many,
1156   Eof,
1157   Slice,
1158   Complete,
1159   Not,
1160   Verify,
1161   Fail,
1162 }
1163 
1164 impl ErrorKind {
1165     #[rustfmt::skip]
1166     /// Converts an `ErrorKind` to a text description
description(&self) -> &str1167     pub fn description(&self) -> &str {
1168     match *self {
1169       ErrorKind::Assert                    => "assert",
1170       ErrorKind::Token                     => "token",
1171       ErrorKind::Tag                       => "tag",
1172       ErrorKind::Alt                       => "alternative",
1173       ErrorKind::Many                      => "many",
1174       ErrorKind::Eof                       => "end of file",
1175       ErrorKind::Slice                     => "slice",
1176       ErrorKind::Complete                  => "complete",
1177       ErrorKind::Not                       => "negation",
1178       ErrorKind::Verify                    => "predicate verification",
1179       ErrorKind::Fail                      => "fail",
1180     }
1181   }
1182 }
1183 
1184 impl<I> ParserError<I> for ErrorKind {
1185     #[inline]
from_error_kind(_input: &I, kind: ErrorKind) -> Self1186     fn from_error_kind(_input: &I, kind: ErrorKind) -> Self {
1187         kind
1188     }
1189 
1190     #[inline]
append(self, _: &I, _: ErrorKind) -> Self1191     fn append(self, _: &I, _: ErrorKind) -> Self {
1192         self
1193     }
1194 }
1195 
1196 impl<I, C> AddContext<I, C> for ErrorKind {}
1197 
1198 impl<I, E> FromExternalError<I, E> for ErrorKind {
1199     /// Create a new error from an input position and an external error
1200     #[inline]
from_external_error(_input: &I, kind: ErrorKind, _e: E) -> Self1201     fn from_external_error(_input: &I, kind: ErrorKind, _e: E) -> Self {
1202         kind
1203     }
1204 }
1205 
1206 /// The Display implementation allows the `std::error::Error` implementation
1207 impl fmt::Display for ErrorKind {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1208     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1209         write!(f, "error {:?}", self)
1210     }
1211 }
1212 
1213 #[cfg(feature = "std")]
1214 impl std::error::Error for ErrorKind {}
1215 
1216 /// See [`Parser::parse`]
1217 #[derive(Clone, Debug, PartialEq, Eq)]
1218 pub struct ParseError<I, E> {
1219     input: I,
1220     offset: usize,
1221     inner: E,
1222 }
1223 
1224 impl<I: Stream, E: ParserError<I>> ParseError<I, E> {
new(mut input: I, start: I::Checkpoint, inner: E) -> Self1225     pub(crate) fn new(mut input: I, start: I::Checkpoint, inner: E) -> Self {
1226         let offset = input.offset_from(&start);
1227         input.reset(start);
1228         Self {
1229             input,
1230             offset,
1231             inner,
1232         }
1233     }
1234 }
1235 
1236 impl<I, E> ParseError<I, E> {
1237     /// The [`Stream`] at the initial location when parsing started
1238     #[inline]
input(&self) -> &I1239     pub fn input(&self) -> &I {
1240         &self.input
1241     }
1242 
1243     /// The location in [`ParseError::input`] where parsing failed
1244     ///
1245     /// **Note:** This is an offset, not an index, and may point to the end of input
1246     /// (`input.len()`) on eof errors.
1247     #[inline]
offset(&self) -> usize1248     pub fn offset(&self) -> usize {
1249         self.offset
1250     }
1251 
1252     /// The original [`ParserError`]
1253     #[inline]
inner(&self) -> &E1254     pub fn inner(&self) -> &E {
1255         &self.inner
1256     }
1257 
1258     /// The original [`ParserError`]
1259     #[inline]
into_inner(self) -> E1260     pub fn into_inner(self) -> E {
1261         self.inner
1262     }
1263 }
1264 
1265 impl<I, E> core::fmt::Display for ParseError<I, E>
1266 where
1267     I: AsBStr,
1268     E: core::fmt::Display,
1269 {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result1270     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1271         let input = self.input.as_bstr();
1272         let span_start = self.offset;
1273         let span_end = span_start;
1274         #[cfg(feature = "std")]
1275         if input.contains(&b'\n') {
1276             let (line_idx, col_idx) = translate_position(input, span_start);
1277             let line_num = line_idx + 1;
1278             let col_num = col_idx + 1;
1279             let gutter = line_num.to_string().len();
1280             let content = input
1281                 .split(|c| *c == b'\n')
1282                 .nth(line_idx)
1283                 .expect("valid line number");
1284 
1285             writeln!(f, "parse error at line {}, column {}", line_num, col_num)?;
1286             //   |
1287             for _ in 0..gutter {
1288                 write!(f, " ")?;
1289             }
1290             writeln!(f, " |")?;
1291 
1292             // 1 | 00:32:00.a999999
1293             write!(f, "{} | ", line_num)?;
1294             writeln!(f, "{}", String::from_utf8_lossy(content))?;
1295 
1296             //   |          ^
1297             for _ in 0..gutter {
1298                 write!(f, " ")?;
1299             }
1300             write!(f, " | ")?;
1301             for _ in 0..col_idx {
1302                 write!(f, " ")?;
1303             }
1304             // The span will be empty at eof, so we need to make sure we always print at least
1305             // one `^`
1306             write!(f, "^")?;
1307             for _ in (span_start + 1)..(span_end.min(span_start + content.len())) {
1308                 write!(f, "^")?;
1309             }
1310             writeln!(f)?;
1311         } else {
1312             let content = input;
1313             writeln!(f, "{}", String::from_utf8_lossy(content))?;
1314             for _ in 0..span_start {
1315                 write!(f, " ")?;
1316             }
1317             // The span will be empty at eof, so we need to make sure we always print at least
1318             // one `^`
1319             write!(f, "^")?;
1320             for _ in (span_start + 1)..(span_end.min(span_start + content.len())) {
1321                 write!(f, "^")?;
1322             }
1323             writeln!(f)?;
1324         }
1325         write!(f, "{}", self.inner)?;
1326 
1327         Ok(())
1328     }
1329 }
1330 
1331 #[cfg(feature = "std")]
translate_position(input: &[u8], index: usize) -> (usize, usize)1332 fn translate_position(input: &[u8], index: usize) -> (usize, usize) {
1333     if input.is_empty() {
1334         return (0, index);
1335     }
1336 
1337     let safe_index = index.min(input.len() - 1);
1338     let column_offset = index - safe_index;
1339     let index = safe_index;
1340 
1341     let nl = input[0..index]
1342         .iter()
1343         .rev()
1344         .enumerate()
1345         .find(|(_, b)| **b == b'\n')
1346         .map(|(nl, _)| index - nl - 1);
1347     let line_start = match nl {
1348         Some(nl) => nl + 1,
1349         None => 0,
1350     };
1351     let line = input[0..line_start].iter().filter(|b| **b == b'\n').count();
1352 
1353     // HACK: This treats byte offset and column offsets the same
1354     let column = crate::lib::std::str::from_utf8(&input[line_start..=index])
1355         .map(|s| s.chars().count() - 1)
1356         .unwrap_or_else(|_| index - line_start);
1357     let column = column + column_offset;
1358 
1359     (line, column)
1360 }
1361 
1362 #[cfg(test)]
1363 #[cfg(feature = "std")]
1364 mod test_parse_error {
1365     use super::*;
1366 
1367     #[test]
single_line()1368     fn single_line() {
1369         let mut input = "0xZ123";
1370         let start = input.checkpoint();
1371         let _ = input.next_token().unwrap();
1372         let _ = input.next_token().unwrap();
1373         let inner = InputError::new(input, ErrorKind::Slice);
1374         let error = ParseError::new(input, start, inner);
1375         let expected = "\
1376 0xZ123
1377   ^
1378 slice error starting at: Z123";
1379         assert_eq!(error.to_string(), expected);
1380     }
1381 }
1382 
1383 #[cfg(test)]
1384 #[cfg(feature = "std")]
1385 mod test_translate_position {
1386     use super::*;
1387 
1388     #[test]
empty()1389     fn empty() {
1390         let input = b"";
1391         let index = 0;
1392         let position = translate_position(&input[..], index);
1393         assert_eq!(position, (0, 0));
1394     }
1395 
1396     #[test]
start()1397     fn start() {
1398         let input = b"Hello";
1399         let index = 0;
1400         let position = translate_position(&input[..], index);
1401         assert_eq!(position, (0, 0));
1402     }
1403 
1404     #[test]
end()1405     fn end() {
1406         let input = b"Hello";
1407         let index = input.len() - 1;
1408         let position = translate_position(&input[..], index);
1409         assert_eq!(position, (0, input.len() - 1));
1410     }
1411 
1412     #[test]
after()1413     fn after() {
1414         let input = b"Hello";
1415         let index = input.len();
1416         let position = translate_position(&input[..], index);
1417         assert_eq!(position, (0, input.len()));
1418     }
1419 
1420     #[test]
first_line()1421     fn first_line() {
1422         let input = b"Hello\nWorld\n";
1423         let index = 2;
1424         let position = translate_position(&input[..], index);
1425         assert_eq!(position, (0, 2));
1426     }
1427 
1428     #[test]
end_of_line()1429     fn end_of_line() {
1430         let input = b"Hello\nWorld\n";
1431         let index = 5;
1432         let position = translate_position(&input[..], index);
1433         assert_eq!(position, (0, 5));
1434     }
1435 
1436     #[test]
start_of_second_line()1437     fn start_of_second_line() {
1438         let input = b"Hello\nWorld\n";
1439         let index = 6;
1440         let position = translate_position(&input[..], index);
1441         assert_eq!(position, (1, 0));
1442     }
1443 
1444     #[test]
second_line()1445     fn second_line() {
1446         let input = b"Hello\nWorld\n";
1447         let index = 8;
1448         let position = translate_position(&input[..], index);
1449         assert_eq!(position, (1, 2));
1450     }
1451 }
1452 
1453 /// Creates a parse error from a [`ErrorKind`]
1454 /// and the position in the input
1455 #[cfg(test)]
1456 macro_rules! error_position(
1457   ($input:expr, $code:expr) => ({
1458     $crate::error::ParserError::from_error_kind($input, $code)
1459   });
1460 );
1461 
1462 #[cfg(test)]
1463 macro_rules! error_node_position(
1464   ($input:expr, $code:expr, $next:expr) => ({
1465     $crate::error::ParserError::append($next, $input, $code)
1466   });
1467 );
1468