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