nom_supreme/
error.rs

1//! An error type, [`ErrorTree`], designed to retain much more useful
2//! information about parse failures than the built-in nom error types.
3//! Requires the `error` feature to be enabled.
4
5use std::{
6    error::Error,
7    fmt::{self, Debug, Display, Formatter, Write},
8};
9
10use indent_write::fmt::IndentWriter;
11use joinery::JoinableIterator;
12use nom::{
13    error::{ErrorKind as NomErrorKind, FromExternalError, ParseError},
14    ErrorConvert, InputLength,
15};
16
17use crate::{
18    context::ContextError,
19    final_parser::{ExtractContext, RecreateContext},
20    tag::TagError,
21};
22
23/// Enum for generic things that can be expected by nom parsers
24///
25/// Certain nom parsers (think [`digit1`], [`tag`], or [`space1`]) are "base
26/// level" in the sense that, rather than combining subparsers, they scan for a
27/// specific character or specific kind of character. This enum tracks the
28/// different kinds of things that can be expected by these base parses.
29///
30/// Printing an expectation via [`Display`] will only include the thing that
31/// was expected, in a form suitable for being prefixed with "expected" or
32/// suffixed with "was expected".
33///
34/// This enum is non-exhaustive; it is intended to represent everything parse
35/// errors where we know *specifically* what was expected. For instance,
36/// [`take_while`] cannot create an [`Expectation`], because it can't
37/// meaningfully report what its subparser is expecting.
38///
39/// [`digit1`]: nom::character::complete::digit1
40/// [`tag`]: crate::tag::complete::tag
41/// [`space1`]: nom::character::complete::space1
42/// [`take_while`]: nom::bytes::complete::take_while
43#[non_exhaustive]
44#[derive(Debug, Copy, Clone, PartialEq, Eq)]
45pub enum Expectation<T> {
46    /// A tag was expected.
47    Tag(T),
48
49    /// A specific character was expected.
50    Char(char),
51
52    /// An ASCII letter (`[a-zA-Z]`) was expected.
53    Alpha,
54
55    /// A decimal digit (`[0-9]`) was expected.
56    Digit,
57
58    /// A hexadecimal digit (`[0-9a-fA-F]`) was expected.
59    HexDigit,
60
61    /// An octal digit (`[0-7]`) was expected.
62    OctDigit,
63
64    /// An alphanumeric character (`[0-9a-zA-Z]`) was expected.
65    AlphaNumeric,
66
67    /// A space or tab was expected.
68    Space,
69
70    /// A space, tab, newline, or carriage return was expected.
71    Multispace,
72
73    /// `"\r\n"` was expected.
74    CrLf,
75
76    /// Eof was expected.
77    Eof,
78
79    /// Expected something; ie, not Eof.
80    Something,
81}
82
83impl<T: Debug> Display for Expectation<T> {
84    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
85        match *self {
86            Expectation::Tag(ref tag) => write!(f, "{:?}", tag),
87            Expectation::Char(c) => write!(f, "{:?}", c),
88            Expectation::Alpha => write!(f, "an ascii letter"),
89            Expectation::Digit => write!(f, "an ascii digit"),
90            Expectation::HexDigit => write!(f, "a hexadecimal digit"),
91            Expectation::OctDigit => write!(f, "an octal digit"),
92            Expectation::AlphaNumeric => write!(f, "an ascii alphanumeric character"),
93            Expectation::Space => write!(f, "a space or tab"),
94            Expectation::Multispace => write!(f, "whitespace"),
95            Expectation::Eof => write!(f, "eof"),
96            Expectation::CrLf => write!(f, "CRLF"),
97            Expectation::Something => write!(f, "not eof"),
98        }
99    }
100}
101
102/// These are the different specific things that can go wrong at a particular
103/// location during a nom parse. Many of these are collected into an
104/// [`ErrorTree`].
105///
106/// - `T` is the tag type, such as &'static str.
107/// - `E` is the external error type, such as `Box<dyn Error>`.
108#[derive(Debug)]
109pub enum BaseErrorKind<T, E> {
110    /// Something specific was expected, such as a specific
111    /// [character][Expectation::Char] or any [digit](Expectation::Digit).
112    /// See [`Expectation`] for details.
113    Expected(Expectation<T>),
114
115    /// A nom parser failed.
116    Kind(NomErrorKind),
117
118    /// An error outside of nom occurred during parsing; for instance, as a
119    /// result of an error during [`map_res`].
120    ///
121    /// [`map_res`]: crate::parser_ext::ParserExt::map_res
122    // Design note: I've gone back and forth on whether or not to exclude the
123    // ErrorKind from this variant. Right now I'm doing so, because it seems
124    // like in practice it's *always* MapRes.
125    External(E),
126}
127
128impl<T: Debug, E: Display> Display for BaseErrorKind<T, E> {
129    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
130        match *self {
131            BaseErrorKind::Expected(ref expectation) => write!(f, "expected {}", expectation),
132            BaseErrorKind::External(ref err) => {
133                writeln!(f, "external error:")?;
134                let mut f = IndentWriter::new("  ", f);
135                write!(f, "{}", err)
136            }
137            BaseErrorKind::Kind(kind) => write!(f, "error in {:?}", kind),
138        }
139    }
140}
141
142/// Context that can appear in a [stack][GenericErrorTree::Stack], above a base
143/// [`ErrorTree`]. Stack contexts are attached by parser combinators to errors
144/// from their subparsers during stack unwinding.
145#[derive(Debug, Clone, Copy, PartialEq, Eq)]
146pub enum StackContext<C> {
147    /// A nom combinator attached an [`ErrorKind`][NomErrorKind] as context
148    /// for a subparser error.
149    Kind(NomErrorKind),
150
151    /// The [`context`][crate::parser_ext::ParserExt::context] combinator
152    /// attached a message as context for a subparser error.
153    Context(C),
154}
155
156impl<C: Debug> Display for StackContext<C> {
157    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
158        match *self {
159            StackContext::Kind(kind) => write!(f, "while parsing {:?}", kind),
160            StackContext::Context(ref ctx) => write!(f, "in section {:?}", ctx),
161        }
162    }
163}
164
165/// A comprehensive tree of nom errors describing a parse failure.
166///
167/// This Error type is designed to be [`VerboseError`]`++`. While
168/// [`VerboseError`] can represent a *stack* of errors, this type can represent
169/// a full tree. In addition to representing a particular specific parse error,
170/// it can also represent a stack of nested error contexts (for instance, as
171/// provided by [`context`][crate::ParserExt::context]), or a list of
172/// alternatives that were all tried individually by [`alt`][nom::branch::alt]
173/// and all failed.
174///
175/// In general, the design goal for this type is to discard as little useful
176/// information as possible. That being said, many [`ErrorKind`] variants add
177/// very little useful contextual information to error traces; for example,
178/// [`ErrorKind::Alt`] doesn't add any interesting context to an
179/// [`ErrorTree::Alt`], and its presence in a stack precludes merging together
180/// adjacent sets of [`ErrorTree::Alt`] siblings.
181///
182/// # Examples
183///
184/// ## Base parser errors
185///
186/// An `ErrorTree::Base` is an error that occurred at the "bottom" of the stack,
187/// from a parser looking for 1 specific kind of thing.
188///
189/// ```rust
190/// use cool_asserts::assert_matches;
191/// use nom::{Parser, Err};
192/// use nom::character::complete::{digit1, char};
193/// use nom_supreme::error::{ErrorTree, BaseErrorKind, StackContext, Expectation};
194/// use nom_supreme::parser_ext::ParserExt;
195///
196/// let err: Err<ErrorTree<&str>> = digit1.parse("abc").unwrap_err();
197///
198/// assert_matches!(err, Err::Error(ErrorTree::Base{
199///     location: "abc",
200///     kind: BaseErrorKind::Expected(Expectation::Digit),
201/// }));
202///
203/// let err: Err<ErrorTree<&str>> = char('a').and(char('b')).parse("acb").unwrap_err();
204///
205/// assert_matches!(err, Err::Error(ErrorTree::Base{
206///     location: "cb",
207///     kind: BaseErrorKind::Expected(Expectation::Char('b')),
208/// }));
209/// ```
210///
211/// ## Stacks
212///
213/// An [`ErrorTree::Stack`] is created when a parser combinator—typically
214/// [`context`]—attaches additional error context to a subparser error. It can
215/// have any [`ErrorTree`] at the base of the stack.
216///
217/// ```rust
218/// use cool_asserts::assert_matches;
219/// use nom::{Parser, Err};
220/// use nom::character::complete::{alpha1, space1, char,};
221/// use nom::sequence::{separated_pair, delimited};
222/// use nom_supreme::parser_ext::ParserExt;
223/// use nom_supreme::error::{ErrorTree, BaseErrorKind, StackContext, Expectation};
224///
225/// // Parse a single identifier, defined as just a string of letters.
226/// let identifier = alpha1.context("identifier");
227///
228/// // Parse a pair of identifiers, separated by whitespace
229/// let identifier_pair = separated_pair(identifier, space1, identifier)
230///     .context("identifier pair");
231///
232/// // Parse a pair of identifiers in parenthesis.
233/// let mut parenthesized = delimited(char('('), identifier_pair, char(')'))
234///     .context("parenthesized");
235///
236/// let err: Err<ErrorTree<&str>> = parenthesized.parse("(abc 123)").unwrap_err();
237///
238/// assert_matches!(err, Err::Error(ErrorTree::Stack {
239///     base,
240///     contexts,
241/// }) => {
242///     assert_matches!(*base, ErrorTree::Base {
243///         location: "123)",
244///         kind: BaseErrorKind::Expected(Expectation::Alpha)
245///     });
246///
247///     assert_eq!(contexts, [
248///         ("123)", StackContext::Context("identifier")),
249///         ("abc 123)", StackContext::Context("identifier pair")),
250///         ("(abc 123)", StackContext::Context("parenthesized")),
251///     ]);
252/// });
253/// ```
254///
255/// ## Alternatives
256///
257/// An [`ErrorTree::Alt`] is created when a series of parsers are all tried,
258/// and all of them fail. Most commonly this will happen via the
259/// [`alt`][nom::branch::alt] combinator or the equivalent [`.or`] postfix
260/// combinator. When all of these subparsers fail, their errors (each
261/// individually their own `ErrorTree`) are aggregated into an
262/// [`ErrorTree::Alt`], indicating that "any one of these things were
263/// expected."
264///
265/// ```rust
266/// use cool_asserts::assert_matches;
267/// use nom::{Parser, Err};
268/// use nom::branch::alt;
269/// use nom_supreme::error::{ErrorTree, BaseErrorKind, StackContext, Expectation};
270/// use nom_supreme::parser_ext::ParserExt;
271/// use nom_supreme::tag::complete::tag;
272///
273/// let parse_bool = alt((
274///     tag("true").value(true),
275///     tag("false").value(false),
276/// ));
277///
278/// let mut parse_null_bool = alt((
279///     parse_bool.map(Some),
280///     tag("null").value(None),
281/// ));
282///
283/// assert_eq!(parse_null_bool.parse("true").unwrap(), ("", Some(true)));
284/// assert_eq!(parse_null_bool.parse("false").unwrap(), ("", Some(false)));
285/// assert_eq!(parse_null_bool.parse("null").unwrap(), ("", None));
286///
287/// let err: Err<ErrorTree<&str>> = parse_null_bool.parse("123").unwrap_err();
288///
289/// // This error communicates to the caller that any one of "true", "false",
290/// // or "null" was expected at that location.
291/// assert_matches!(err, Err::Error(ErrorTree::Alt(choices)) => {
292///     assert_matches!(choices.as_slice(), [
293///         ErrorTree::Base {
294///             location: "123",
295///             kind: BaseErrorKind::Expected(Expectation::Tag("true"))},
296///         ErrorTree::Base {
297///             location: "123",
298///             kind: BaseErrorKind::Expected(Expectation::Tag("false"))},
299///         ErrorTree::Base {
300///             location: "123",
301///             kind: BaseErrorKind::Expected(Expectation::Tag("null"))},
302///     ])
303/// });
304/// ```
305///
306/// ## Contexts and Alternatives
307///
308/// Because [`Stack`] and [`Alt`] recursively contain [`ErrorTree`] errors from
309/// subparsers, they can be can combined to create error trees of arbitrary
310/// complexity.
311///
312/// ```rust
313/// use cool_asserts::assert_matches;
314/// use nom::{Parser, Err};
315/// use nom::branch::alt;
316/// use nom_supreme::error::{ErrorTree, BaseErrorKind, StackContext, Expectation};
317/// use nom_supreme::parser_ext::ParserExt;
318/// use nom_supreme::tag::complete::tag;
319///
320/// let parse_bool = alt((
321///     tag("true").value(true),
322///     tag("false").value(false),
323/// )).context("bool");
324///
325/// let mut parse_null_bool = alt((
326///     parse_bool.map(Some),
327///     tag("null").value(None).context("null"),
328/// )).context("null or bool");
329///
330/// assert_eq!(parse_null_bool.parse("true").unwrap(), ("", Some(true)));
331/// assert_eq!(parse_null_bool.parse("false").unwrap(), ("", Some(false)));
332/// assert_eq!(parse_null_bool.parse("null").unwrap(), ("", None));
333///
334/// let err: Err<ErrorTree<&str>> = parse_null_bool.parse("123").unwrap_err();
335///
336/// assert_matches!(err, Err::Error(ErrorTree::Stack{base, contexts}) => {
337///     assert_eq!(contexts, [("123", StackContext::Context("null or bool"))]);
338///     assert_matches!(*base, ErrorTree::Alt(choices) => {
339///         assert_matches!(&choices[0], ErrorTree::Stack{base, contexts} => {
340///             assert_eq!(contexts, &[("123", StackContext::Context("bool"))]);
341///             assert_matches!(&**base, ErrorTree::Alt(choices) => {
342///                 assert_matches!(&choices[0], ErrorTree::Base {
343///                     location: "123",
344///                     kind: BaseErrorKind::Expected(Expectation::Tag("true"))
345///                 });
346///                 assert_matches!(&choices[1], ErrorTree::Base {
347///                     location: "123",
348///                     kind: BaseErrorKind::Expected(Expectation::Tag("false"))
349///                 });
350///            });
351///         });
352///         assert_matches!(&choices[1], ErrorTree::Stack{base, contexts} => {
353///             assert_eq!(contexts, &[("123", StackContext::Context("null"))]);
354///             assert_matches!(&**base, ErrorTree::Base {
355///                 location: "123",
356///                 kind: BaseErrorKind::Expected(Expectation::Tag("null"))
357///             });
358///         });
359///     });
360/// });
361/// ```
362///
363/// # Display formatting
364///
365/// TODO WRITE THIS SECTION
366///
367/// [`.or`]: nom::Parser::or
368/// [`Alt`]: GenericErrorTree::Alt
369/// [`context`]: nom::error::context
370/// [`ErrorKind::Alt`]: nom::error::ErrorKind::Alt
371/// [`ErrorKind`]: nom::error::ErrorKind
372/// [`ErrorTree::Alt`]: GenericErrorTree::Alt
373/// [`ErrorTree::Base`]: GenericErrorTree::Base
374/// [`ErrorTree::Stack`]: GenericErrorTree::Stack
375/// [`Stack`]: GenericErrorTree::Stack
376/// [`VerboseError`]: nom::error::VerboseError
377pub type ErrorTree<I> =
378    GenericErrorTree<I, &'static str, &'static str, Box<dyn Error + Send + Sync + 'static>>;
379
380/// Generic version of [`ErrorTree`], which allows for arbitrary `Tag`, `Context`,
381/// and `ExternalError` types. See [`ErrorTree`] for more extensive docs and
382/// examples.
383///
384/// - `Tag` is typically something like `&'static str` or `&'static [u8]`.
385/// - `Context` is typically `&'static str`, and it must be in order to
386///   interoperate with nom's [`context`][nom::error::context] combinator.
387///   `nom-supreme` provides a more generic [`.context`][crate::ParserExt::context]
388///   combinator that allows for any kind of context to be attached to an error.
389/// - `Error` can usually be nothing, as it's unusual for nom parsers to
390///   require external errors. `Box<dyn Error + Send + Sync + 'static>` is
391///   a common catch-all.
392#[derive(Debug)]
393pub enum GenericErrorTree<Location, Tag, Context, ExternalError> {
394    /// A specific error event at a specific location. Often this will indicate
395    /// that something like a tag or character was expected at that location.
396    Base {
397        /// The location of this error in the input
398        location: Location,
399
400        /// The specific error that occurred
401        kind: BaseErrorKind<Tag, ExternalError>,
402    },
403
404    /// A stack indicates a chain of error contexts was provided. The stack
405    /// should be read "backwards"; that is, errors *earlier* in the `Vec`
406    /// occurred "sooner" (deeper in the call stack).
407    Stack {
408        /// The original error
409        base: Box<Self>,
410
411        /// The stack of contexts attached to that error
412        contexts: Vec<(Location, StackContext<Context>)>,
413    },
414
415    /// A series of parsers were tried at the same location (for instance, via
416    /// the [`alt`](nom::branch::alt) combinator) and all of them failed. All
417    /// of the errors in this set are "siblings".
418    Alt(Vec<Self>),
419    // TODO: in a future version of nom-supreme, elaborate on the specific
420    // type combinations here. For instance:
421    // - Alt can only contain Stack or Base
422    // - Stack has a single Base or Alt, followed by a series of contexts
423    //   (Context or Kind)
424}
425
426impl<I, T, C, E> GenericErrorTree<I, T, C, E> {
427    /// Helper for `map_locations`. Because it operates recursively, this
428    /// method uses an `&mut impl FnMut`, which can be reborrowed.
429    fn map_locations_ref<I2>(
430        self,
431        convert_location: &mut impl FnMut(I) -> I2,
432    ) -> GenericErrorTree<I2, T, C, E> {
433        // TODO: does the recursive nature of this function present a potential
434        // security risk? Consider replacing it with a breadth-first algorithm,
435        // or capping the maximum recursion depth. Note, though, that recursion
436        // only happens when alternating between different *kinds* of
437        // ErrorTree; nested groups of Alt or Stack are flattened.
438        match self {
439            GenericErrorTree::Base { location, kind } => GenericErrorTree::Base {
440                location: convert_location(location),
441                kind,
442            },
443            GenericErrorTree::Stack { base, contexts } => GenericErrorTree::Stack {
444                base: Box::new(base.map_locations_ref(convert_location)),
445                contexts: contexts
446                    .into_iter()
447                    .map(|(location, context)| (convert_location(location), context))
448                    .collect(),
449            },
450            GenericErrorTree::Alt(siblings) => GenericErrorTree::Alt(
451                siblings
452                    .into_iter()
453                    .map(|err| err.map_locations_ref(convert_location))
454                    .collect(),
455            ),
456        }
457    }
458
459    /// Convert all of the locations in this error using some kind of mapping
460    /// function. This is intended to help add additional context that may not
461    /// have been available when the nom parsers were running, such as line
462    /// and column numbers.
463    pub fn map_locations<I2>(
464        self,
465        mut convert_location: impl FnMut(I) -> I2,
466    ) -> GenericErrorTree<I2, T, C, E> {
467        self.map_locations_ref(&mut convert_location)
468    }
469}
470
471impl<I: Display, T: Debug, C: Debug, E: Display> Display for GenericErrorTree<I, T, C, E> {
472    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
473        match self {
474            GenericErrorTree::Base { location, kind } => write!(f, "{} at {:#}", kind, location),
475            GenericErrorTree::Stack { contexts, base } => {
476                contexts.iter().rev().try_for_each(|(location, context)| {
477                    writeln!(f, "{} at {:#},", context, location)
478                })?;
479
480                base.fmt(f)
481            }
482            GenericErrorTree::Alt(siblings) => {
483                writeln!(f, "one of:")?;
484                let mut f = IndentWriter::new("  ", f);
485                write!(f, "{}", siblings.iter().join_with(", or\n"))
486            }
487        }
488    }
489}
490
491impl<I: Display + Debug, T: Debug, C: Debug, E: Display + Debug> Error
492    for GenericErrorTree<I, T, C, E>
493{
494}
495
496impl<I: InputLength, T, C, E> ParseError<I> for GenericErrorTree<I, T, C, E> {
497    /// Create a new error at the given position. Interpret `kind` as an
498    /// [`Expectation`] if possible, to give a more informative error message.
499    fn from_error_kind(location: I, kind: NomErrorKind) -> Self {
500        let kind = match kind {
501            NomErrorKind::Alpha => BaseErrorKind::Expected(Expectation::Alpha),
502            NomErrorKind::Digit => BaseErrorKind::Expected(Expectation::Digit),
503            NomErrorKind::HexDigit => BaseErrorKind::Expected(Expectation::HexDigit),
504            NomErrorKind::OctDigit => BaseErrorKind::Expected(Expectation::OctDigit),
505            NomErrorKind::AlphaNumeric => BaseErrorKind::Expected(Expectation::AlphaNumeric),
506            NomErrorKind::Space => BaseErrorKind::Expected(Expectation::Space),
507            NomErrorKind::MultiSpace => BaseErrorKind::Expected(Expectation::Multispace),
508            NomErrorKind::CrLf => BaseErrorKind::Expected(Expectation::CrLf),
509
510            // Problem: ErrorKind::Eof is used interchangeably by various nom
511            // parsers to mean either "expected Eof" or "expected NOT eof". See
512            // https://github.com/Geal/nom/issues/1259. For now, we examine the
513            // input string to guess what the likely intention is.
514            NomErrorKind::Eof => match location.input_len() {
515                // The input is at Eof, which means that this refers to an
516                // *unexpected* eof.
517                0 => BaseErrorKind::Expected(Expectation::Something),
518
519                // The input is *not* at eof, which means that this refers to
520                // an *expected* eof.
521                _ => BaseErrorKind::Expected(Expectation::Eof),
522            },
523            kind => BaseErrorKind::Kind(kind),
524        };
525
526        GenericErrorTree::Base { location, kind }
527    }
528
529    /// Combine an existing error with a new one. This is how error context is
530    /// accumulated when backtracing. "other" is the original error, and the
531    /// inputs new error from higher in the call stack.
532    ///
533    /// If `other` is already an `GenericErrorTree::Stack`, the context is added to
534    /// the stack; otherwise, a new stack is created, with `other` at the root.
535    fn append(location: I, kind: NomErrorKind, other: Self) -> Self {
536        let context = (location, StackContext::Kind(kind));
537
538        match other {
539            // Don't create a stack of [ErrorKind::Alt, GenericErrorTree::Alt(..)]
540            alt @ GenericErrorTree::Alt(..) if kind == NomErrorKind::Alt => alt,
541
542            // This is already a stack, so push on to it
543            GenericErrorTree::Stack { contexts, base } => GenericErrorTree::Stack {
544                base,
545                contexts: express!(contexts.push(context)),
546            },
547
548            // This isn't a stack; create a new stack
549            base => GenericErrorTree::Stack {
550                base: Box::new(base),
551                contexts: vec![context],
552            },
553        }
554    }
555
556    /// Create an error indicating an expected character at a given position
557    fn from_char(location: I, character: char) -> Self {
558        GenericErrorTree::Base {
559            location,
560            kind: BaseErrorKind::Expected(Expectation::Char(character)),
561        }
562    }
563
564    /// Combine two errors from branches of alt. If either or both errors are
565    /// already [`GenericErrorTree::Alt`], the different error sets are merged;
566    /// otherwise, a new [`GenericErrorTree::Alt`] is created, containing both
567    /// `self` and `other`.
568    fn or(self, other: Self) -> Self {
569        // For now we assume that there's no need to try and preserve
570        // left-to-right ordering of alternatives.
571        let siblings = match (self, other) {
572            (GenericErrorTree::Alt(siblings1), GenericErrorTree::Alt(siblings2)) => {
573                match siblings1.capacity() >= siblings2.capacity() {
574                    true => express!(siblings1.extend(siblings2)),
575                    false => express!(siblings2.extend(siblings1)),
576                }
577            }
578            (GenericErrorTree::Alt(siblings), err) | (err, GenericErrorTree::Alt(siblings)) => {
579                express!(siblings.push(err))
580            }
581            (err1, err2) => vec![err1, err2],
582        };
583
584        GenericErrorTree::Alt(siblings)
585    }
586}
587
588impl<I, T, C, E> ContextError<I, C> for GenericErrorTree<I, T, C, E> {
589    fn add_context(location: I, ctx: C, other: Self) -> Self {
590        let context = (location, StackContext::Context(ctx));
591
592        match other {
593            // This is already a stack, so push on to it
594            GenericErrorTree::Stack { contexts, base } => GenericErrorTree::Stack {
595                base,
596                contexts: express!(contexts.push(context)),
597            },
598
599            // This isn't a stack, create a new stack
600            base => GenericErrorTree::Stack {
601                base: Box::new(base),
602                contexts: vec![context],
603            },
604        }
605    }
606}
607
608impl<I, T, E> nom::error::ContextError<I> for GenericErrorTree<I, T, &'static str, E> {
609    fn add_context(location: I, ctx: &'static str, other: Self) -> Self {
610        ContextError::add_context(location, ctx, other)
611    }
612}
613
614impl<I, T, C, E, E2> FromExternalError<I, E2> for GenericErrorTree<I, T, C, E>
615where
616    E: From<E2>,
617{
618    /// Create an error from a given external error, such as from FromStr
619    fn from_external_error(location: I, _kind: NomErrorKind, e: E2) -> Self {
620        GenericErrorTree::Base {
621            location,
622            kind: BaseErrorKind::External(e.into()),
623        }
624    }
625}
626
627impl<I, T: AsRef<[u8]>, C, E> TagError<I, T> for GenericErrorTree<I, T, C, E> {
628    fn from_tag(location: I, tag: T) -> Self {
629        GenericErrorTree::Base {
630            location,
631            kind: BaseErrorKind::Expected(match tag.as_ref() {
632                b"\r\n" => Expectation::CrLf,
633                _ => Expectation::Tag(tag),
634            }),
635        }
636    }
637}
638
639impl<I, T, C, E> ErrorConvert<GenericErrorTree<(I, usize), T, C, E>>
640    for GenericErrorTree<I, T, C, E>
641{
642    fn convert(self) -> GenericErrorTree<(I, usize), T, C, E> {
643        self.map_locations(|location| (location, 0))
644    }
645}
646
647impl<I, T, C, E> ErrorConvert<GenericErrorTree<I, T, C, E>>
648    for GenericErrorTree<(I, usize), T, C, E>
649{
650    fn convert(self) -> GenericErrorTree<I, T, C, E> {
651        self.map_locations(move |(location, _offset)| location)
652    }
653}
654
655impl<I, I2, T, C, E> ExtractContext<I, GenericErrorTree<I2, T, C, E>>
656    for GenericErrorTree<I, T, C, E>
657where
658    I: Clone,
659    I2: RecreateContext<I>,
660{
661    fn extract_context(self, original_input: I) -> GenericErrorTree<I2, T, C, E> {
662        self.map_locations(move |location| I2::recreate_context(original_input.clone(), location))
663    }
664}
665
666#[cfg(test)]
667mod tests {
668    use super::*;
669
670    use nom::{
671        bits::{bits, complete::take},
672        sequence::tuple,
673        IResult, Parser,
674    };
675
676    type BitInput<'a> = (&'a [u8], usize);
677
678    fn parse_bool_bit(input: (&[u8], usize)) -> IResult<BitInput, bool, ErrorTree<BitInput>> {
679        take(1usize).map(|bit: u8| bit != 0).parse(input)
680    }
681
682    type Byte = (bool, bool, bool, bool, bool, bool, bool, bool);
683
684    /// Parse 8 bits
685    fn parse_bits(input: &[u8]) -> IResult<&[u8], Byte, ErrorTree<&[u8]>> {
686        bits(tuple((
687            parse_bool_bit,
688            parse_bool_bit,
689            parse_bool_bit,
690            parse_bool_bit,
691            parse_bool_bit,
692            parse_bool_bit,
693            parse_bool_bit,
694            parse_bool_bit,
695        )))
696        .parse(input)
697    }
698
699    /// Test that ErrorTree can be used with a bits parser, which requires
700    /// ErrorConvert
701    #[test]
702    fn error_tree_bits() {
703        let values = [0b1010_1111, 10];
704        let (tail, result) = parse_bits(&values).unwrap();
705
706        assert_eq!(tail, &[10]);
707        assert_eq!(result, (true, false, true, false, true, true, true, true));
708    }
709}