combine/
error.rs

1use crate::lib::fmt;
2
3#[cfg(feature = "std")]
4use std::error::Error as StdError;
5
6use crate::{stream::StreamOnce, ErrorOffset};
7
8use self::ParseResult::*;
9
10pub(crate) trait ResultExt<E, T> {
11    fn committed(self) -> ParseResult<E, T>;
12}
13
14impl<E, T> ResultExt<E, T> for Result<E, T> {
15    fn committed(self) -> ParseResult<E, T> {
16        match self {
17            Ok(x) => CommitOk(x),
18            Err(x) => CommitErr(x),
19        }
20    }
21}
22
23#[macro_export]
24#[doc(hidden)]
25macro_rules! ctry {
26    ($result:expr) => {
27        match $result {
28            $crate::error::ParseResult::CommitOk(x) => (x, $crate::error::Commit::Commit(())),
29            $crate::error::ParseResult::PeekOk(x) => (x, $crate::error::Commit::Peek(())),
30            $crate::error::ParseResult::CommitErr(err) => {
31                return $crate::error::ParseResult::CommitErr(err.into())
32            }
33            $crate::error::ParseResult::PeekErr(err) => {
34                return $crate::error::ParseResult::PeekErr(err.into())
35            }
36        }
37    };
38}
39
40/// Trait for types which can be used to construct error information.
41///
42/// To call functions expecting this trait, use the wrapper types defined in this module
43/// `Token`, `Range`, `Format` or `Static`/`&'static str`
44pub trait ErrorInfo<'s, T, R> {
45    type Format: fmt::Display;
46
47    #[allow(clippy::wrong_self_convention)]
48    fn into_info(&'s self) -> Info<T, R, Self::Format>;
49}
50
51impl<'s, 'a, T, R, F> ErrorInfo<'s, T, R> for &'a F
52where
53    F: ErrorInfo<'s, T, R>,
54{
55    type Format = F::Format;
56    fn into_info(&'s self) -> Info<T, R, Self::Format> {
57        (**self).into_info()
58    }
59}
60
61#[derive(Clone, Debug)]
62pub enum Info<T, R, F = &'static str> {
63    Token(T),
64    Range(R),
65    Static(&'static str),
66    Format(F),
67}
68
69impl<'s, T, R, F> ErrorInfo<'s, T, R> for Info<T, R, F>
70where
71    T: Clone,
72    R: Clone,
73    F: fmt::Display + 's,
74{
75    type Format = &'s F;
76    fn into_info(&'s self) -> Info<T, R, <Self as ErrorInfo<'_, T, R>>::Format> {
77        match self {
78            Info::Token(b) => Info::Token(b.clone()),
79            Info::Range(b) => Info::Range(b.clone()),
80            Info::Static(b) => Info::Static(*b),
81            Info::Format(b) => Info::Format(b),
82        }
83    }
84}
85
86impl<R, F> From<char> for Info<char, R, F> {
87    fn from(s: char) -> Self {
88        Info::Token(s)
89    }
90}
91
92impl<'s, R> ErrorInfo<'s, char, R> for char {
93    type Format = &'static str;
94    fn into_info(&self) -> Info<char, R, Self::Format> {
95        Info::Token(*self)
96    }
97}
98
99impl<T, R, F> From<&'static str> for Info<T, R, F> {
100    fn from(s: &'static str) -> Self {
101        Info::Static(s)
102    }
103}
104
105impl<'s, T, R> ErrorInfo<'s, T, R> for &'static str {
106    type Format = &'static str;
107    fn into_info(&self) -> Info<T, R, Self::Format> {
108        Info::Static(*self)
109    }
110}
111
112impl<R, F> From<u8> for Info<u8, R, F> {
113    fn from(s: u8) -> Self {
114        Info::Token(s)
115    }
116}
117
118impl<R> ErrorInfo<'_, Self, R> for u8 {
119    type Format = &'static str;
120    fn into_info(&self) -> Info<Self, R, Self::Format> {
121        Info::Token(*self)
122    }
123}
124
125/// Newtype which constructs an `Info::Token` through `ErrorInfo`
126pub struct Token<T>(pub T);
127
128impl<T, R> From<Token<T>> for Info<T, R, &'static str> {
129    fn from(s: Token<T>) -> Self {
130        Info::Token(s.0)
131    }
132}
133
134impl<'s, T, R> ErrorInfo<'s, T, R> for Token<T>
135where
136    T: Clone,
137{
138    type Format = &'static str;
139    fn into_info(&'s self) -> Info<T, R, Self::Format> {
140        Info::Token(self.0.clone())
141    }
142}
143
144/// Newtype which constructs an `Info::Range` through `ErrorInfo`
145pub struct Range<R>(pub R);
146
147impl<T, R> From<Range<R>> for Info<T, R, &'static str> {
148    fn from(s: Range<R>) -> Self {
149        Info::Range(s.0)
150    }
151}
152
153impl<'s, T, R> ErrorInfo<'s, T, R> for Range<R>
154where
155    R: Clone,
156{
157    type Format = &'static str;
158    fn into_info(&'s self) -> Info<T, R, Self::Format> {
159        Info::Range(self.0.clone())
160    }
161}
162
163/// Newtype which constructs an `Info::Static` through `ErrorInfo`
164/// A plain `&'static str` can also be used, this exists for consistency.
165pub struct Static(&'static str);
166
167impl<T, R, F> From<Static> for Info<T, R, F>
168where
169    F: fmt::Display,
170{
171    fn from(s: Static) -> Self {
172        Info::Static(s.0)
173    }
174}
175
176impl<'s, T, R> ErrorInfo<'s, T, R> for Static {
177    type Format = &'static str;
178    fn into_info(&'s self) -> Info<T, R, Self::Format> {
179        Info::Static(self.0)
180    }
181}
182
183/// Newtype which constructs an `Info::Format` through `ErrorInfo`
184pub struct Format<F>(pub F)
185where
186    F: fmt::Display;
187
188impl<T, R, F> From<Format<F>> for Info<T, R, F>
189where
190    F: fmt::Display,
191{
192    fn from(s: Format<F>) -> Self {
193        Info::Format(s.0)
194    }
195}
196
197impl<'s, T, R, F> ErrorInfo<'s, T, R> for Format<F>
198where
199    F: fmt::Display + 's,
200{
201    type Format = &'s F;
202    fn into_info(&'s self) -> Info<T, R, Self::Format> {
203        Info::Format(&self.0)
204    }
205}
206
207/// Enum used to indicate if a parser committed any items of the stream it was given as an input.
208///
209/// This is used by parsers such as `or` and `choice` to determine if they should try to parse
210/// with another parser as they will only be able to provide good error reporting if the preceding
211/// parser did not commit to the parse.
212#[derive(Clone, PartialEq, Debug, Copy)]
213pub enum Commit<T> {
214    /// Constructor indicating that the parser has committed to this parse. If a parser after this fails,
215    /// other parser alternatives will not be attempted (`CommitErr` will be returned)
216    Commit(T),
217    /// Constructor indicating that the parser has not committed to this parse. If a parser after this fails,
218    /// other parser alternatives will be attempted (`EmptyErr` will be returned)
219    Peek(T),
220}
221
222impl<T> AsMut<T> for Commit<T> {
223    fn as_mut(&mut self) -> &mut T {
224        match *self {
225            Commit::Peek(ref mut t) | Commit::Commit(ref mut t) => t,
226        }
227    }
228}
229
230impl<T> AsRef<T> for Commit<T> {
231    fn as_ref(&self) -> &T {
232        match *self {
233            Commit::Peek(ref t) | Commit::Commit(ref t) => t,
234        }
235    }
236}
237
238impl<T> Commit<T> {
239    /// Returns true if `self` is peek.
240    pub fn is_peek(&self) -> bool {
241        match *self {
242            Commit::Peek(_) => true,
243            Commit::Commit(_) => false,
244        }
245    }
246
247    /// Extracts the contained value.
248    pub fn into_inner(self) -> T {
249        match self {
250            Commit::Peek(x) | Commit::Commit(x) => x,
251        }
252    }
253
254    /// Converts `self` into the `Commit` state.
255    pub fn into_commit(self) -> Commit<T> {
256        Commit::Commit(self.into_inner())
257    }
258
259    /// Converts `self` into the `Peek` state.
260    pub fn into_peek(self) -> Commit<T> {
261        Commit::Peek(self.into_inner())
262    }
263
264    /// Maps over the contained value without changing the committed state.
265    pub fn map<F, U>(self, f: F) -> Commit<U>
266    where
267        F: FnOnce(T) -> U,
268    {
269        match self {
270            Commit::Peek(x) => Commit::Peek(f(x)),
271            Commit::Commit(x) => Commit::Commit(f(x)),
272        }
273    }
274
275    pub fn merge(&self, current: Commit<T>) -> Commit<T> {
276        match *self {
277            Commit::Peek(_) => current,
278            Commit::Commit(_) => current.into_commit(),
279        }
280    }
281
282    /// Combines the `Commit` flags from `self` and the result of `f`.
283    ///
284    /// ```text
285    /// Peek    <> Peek    -> Peek
286    /// Commit <> Peek    -> Commit
287    /// Peek    <> Commit -> Commit
288    /// Commit <> Commit -> Commit
289    /// ```
290    ///
291    /// ```
292    /// # extern crate combine as pc;
293    /// # use pc::*;
294    /// # fn main() {
295    /// //Parses a character of string literal and handles the escaped characters \\ and \" as \
296    /// //and " respectively
297    /// fn char<Input>(input: &mut Input) -> StdParseResult<char, Input>
298    ///     where Input: Stream<Token = char>,
299    /// {
300    ///     let (c, committed) = satisfy(|c| c != '"').parse_stream(input).into_result()?;
301    ///     match c {
302    ///         //Since the `char` parser has already committed some of the input `combine` is used
303    ///         //propagate the committed state to the next part of the parser
304    ///         '\\' => committed.combine(|_| {
305    ///             satisfy(|c| c == '"' || c == '\\')
306    ///                 .map(|c| {
307    ///                     match c {
308    ///                         '"' => '"',
309    ///                         '\\' => '\\',
310    ///                         c => c
311    ///                     }
312    ///                 })
313    ///                 .parse_stream(input)
314    ///                 .into_result()
315    ///             }),
316    ///         _ => Ok((c, committed))
317    ///     }
318    /// }
319    /// let result = many(parser(char))
320    ///     .easy_parse(r#"abc\"\\"#);
321    /// assert_eq!(result, Ok((r#"abc"\"#.to_string(), "")));
322    /// }
323    /// ```
324    pub fn combine<F, U, E>(self, f: F) -> StdParseResult2<U, E>
325    where
326        F: FnOnce(T) -> StdParseResult2<U, E>,
327    {
328        match self {
329            Commit::Commit(x) => match f(x) {
330                Ok((v, Commit::Peek(()))) => Ok((v, Commit::Commit(()))),
331                Err(Commit::Peek(err)) => Err(Commit::Commit(err)),
332                y => y,
333            },
334            Commit::Peek(x) => f(x),
335        }
336    }
337    pub fn combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E>
338    where
339        F: FnOnce(T) -> ParseResult<U, E>,
340    {
341        use self::ParseResult::*;
342
343        match self {
344            Commit::Commit(x) => match f(x) {
345                PeekOk(v) => CommitOk(v),
346                PeekErr(err) => CommitErr(err.error),
347                y => y,
348            },
349            Commit::Peek(x) => f(x),
350        }
351    }
352}
353
354/// A type alias over the specific `Result` type used by parsers to indicate whether they were
355/// successful or not.
356/// `O` is the type that is output on success.
357/// `Input` is the specific stream type used in the parser.
358pub type StdParseResult<O, Input> =
359    Result<(O, Commit<()>), Commit<Tracked<<Input as StreamOnce>::Error>>>;
360pub type StdParseResult2<O, E> = Result<(O, Commit<()>), Commit<Tracked<E>>>;
361
362/// `StreamError` represents a single error returned from a `Stream` or a `Parser`.
363///
364/// Usually multiple instances of `StreamError` is composed into a `ParseError` to build the final
365/// error value.
366pub trait StreamError<Item, Range>: Sized {
367    fn unexpected_token(token: Item) -> Self;
368    fn unexpected_range(token: Range) -> Self;
369    fn unexpected_format<T>(msg: T) -> Self
370    where
371        T: fmt::Display;
372    fn unexpected<E>(info: E) -> Self
373    where
374        E: for<'s> ErrorInfo<'s, Item, Range>,
375    {
376        match info.into_info() {
377            Info::Token(b) => Self::unexpected_token(b),
378            Info::Range(b) => Self::unexpected_range(b),
379            Info::Static(b) => Self::unexpected_static_message(b),
380            Info::Format(b) => Self::unexpected_format(b),
381        }
382    }
383    fn unexpected_static_message(msg: &'static str) -> Self {
384        Self::unexpected_format(msg)
385    }
386
387    fn expected_token(token: Item) -> Self;
388    fn expected_range(token: Range) -> Self;
389    fn expected_format<T>(msg: T) -> Self
390    where
391        T: fmt::Display;
392    fn expected<E>(info: E) -> Self
393    where
394        E: for<'s> ErrorInfo<'s, Item, Range>,
395    {
396        match info.into_info() {
397            Info::Token(b) => Self::expected_token(b),
398            Info::Range(b) => Self::expected_range(b),
399            Info::Static(b) => Self::expected_static_message(b),
400            Info::Format(b) => Self::expected_format(b),
401        }
402    }
403    fn expected_static_message(msg: &'static str) -> Self {
404        Self::expected_format(msg)
405    }
406
407    fn message_token(token: Item) -> Self;
408    fn message_range(token: Range) -> Self;
409    fn message_format<T>(msg: T) -> Self
410    where
411        T: fmt::Display;
412    fn message_static_message(msg: &'static str) -> Self {
413        Self::message_format(msg)
414    }
415    fn message<E>(info: E) -> Self
416    where
417        E: for<'s> ErrorInfo<'s, Item, Range>,
418    {
419        match info.into_info() {
420            Info::Token(b) => Self::message_token(b),
421            Info::Range(b) => Self::message_range(b),
422            Info::Static(b) => Self::message_static_message(b),
423            Info::Format(b) => Self::message_format(b),
424        }
425    }
426
427    #[cfg(feature = "std")]
428    fn other<E>(err: E) -> Self
429    where
430        E: StdError + Send + Sync + 'static,
431    {
432        Self::message_format(err)
433    }
434
435    fn end_of_input() -> Self {
436        Self::unexpected_static_message("end of input")
437    }
438
439    fn is_unexpected_end_of_input(&self) -> bool;
440
441    /// Converts `self` into a different `StreamError` type.
442    ///
443    /// This should aim to preserve as much information as possible into the returned `T` value but
444    /// if `Self` ignores some information passed to it using one of the constructors that
445    /// information is naturally lost.
446    fn into_other<T>(self) -> T
447    where
448        T: StreamError<Item, Range>;
449}
450
451/// Trait which defines a combine parse error.
452///
453/// A parse error is composed of zero or more `StreamError` instances which gets added to it as
454/// errors are encountered during parsing.
455pub trait ParseError<Item, Range, Position>: Sized + PartialEq {
456    type StreamError: StreamError<Item, Range>;
457
458    /// Constructs an empty error.
459    ///
460    /// An empty error is expected to be cheap to create as it is frequently created and discarded.
461    fn empty(position: Position) -> Self;
462
463    /// Creates a `ParseError` from a single `Self::StreamError`
464    fn from_error(position: Position, err: Self::StreamError) -> Self {
465        let mut errors = Self::empty(position);
466        errors.add(err);
467        errors
468    }
469
470    fn position(&self) -> Position {
471        // TODO Remove the default implementation in a breaking release
472        unimplemented!()
473    }
474
475    /// Sets the position of this `ParseError`
476    fn set_position(&mut self, position: Position);
477
478    /// Merges two errors. If they exist at the same position the errors of `other` are
479    /// added to `self` (using the semantics of `add`). If they are not at the same
480    /// position the error furthest ahead are returned, ignoring the other `ParseError`.
481    fn merge(self, other: Self) -> Self {
482        other
483    }
484
485    /// Adds a `StreamError` to `self`.
486    ///
487    /// It is up to each individual error type to define what adding an error does, some may push
488    /// it to a vector while others may only keep `self` or `err` to avoid allocation
489    fn add(&mut self, err: Self::StreamError);
490
491    fn add_expected<E>(&mut self, info: E)
492    where
493        E: for<'s> ErrorInfo<'s, Item, Range>,
494    {
495        self.add(Self::StreamError::expected(info))
496    }
497
498    fn add_unexpected<E>(&mut self, info: E)
499    where
500        E: for<'s> ErrorInfo<'s, Item, Range>,
501    {
502        self.add(Self::StreamError::unexpected(info))
503    }
504
505    fn add_message<E>(&mut self, info: E)
506    where
507        E: for<'s> ErrorInfo<'s, Item, Range>,
508    {
509        self.add(Self::StreamError::message(info))
510    }
511
512    /// Sets `info` as the *only* `Expected` error of `self`
513    fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
514    where
515        F: FnOnce(&mut Tracked<Self>);
516
517    /// Removes any expected errors currently in `self`
518    fn clear_expected(&mut self) {}
519
520    fn is_unexpected_end_of_input(&self) -> bool;
521
522    /// Does a best-effort conversion of `self` into another `ParseError`
523    fn into_other<T>(self) -> T
524    where
525        T: ParseError<Item, Range, Position>;
526}
527
528/// Defines a conversion between two parse error types.
529///
530/// Like `ParseError::into_other` but with a more general signature
531/// (This will take the place of `into_other` on breaking release of combine)
532pub trait ParseErrorInto<Item, Range, Position>: Sized {
533    fn into_other_error<T, Item2, Range2, Position2>(self) -> T
534    where
535        T: ParseError<Item2, Range2, Position2>,
536        Item2: From<Item>,
537        Range2: From<Range>,
538        Position2: From<Position>;
539}
540
541/// Defines a conversion between two stream error types.
542///
543/// Like `StreamError::into_other` but with a more general signature
544/// (This will take the place of `into_other` on breaking release of combine)
545pub trait StreamErrorInto<Item, Range>: Sized {
546    fn into_other_error<T, Item2, Range2>(self) -> T
547    where
548        T: StreamError<Item2, Range2>,
549        Item2: From<Item>,
550        Range2: From<Range>;
551}
552
553#[derive(Clone, Copy, Debug, PartialEq)]
554pub enum UnexpectedParse {
555    Eoi,
556    Unexpected,
557}
558
559impl fmt::Display for UnexpectedParse {
560    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561        write!(f, "{}", self.as_str())
562    }
563}
564
565#[cfg(feature = "std")]
566impl StdError for UnexpectedParse {
567    fn description(&self) -> &str {
568        self.as_str()
569    }
570}
571
572impl UnexpectedParse {
573    fn as_str(&self) -> &str {
574        use self::UnexpectedParse::*;
575        match *self {
576            Unexpected => "unexpected parse",
577            Eoi => "unexpected end of input",
578        }
579    }
580}
581
582impl<Item, Range> StreamError<Item, Range> for UnexpectedParse {
583    #[inline]
584    fn unexpected_token(_: Item) -> Self {
585        UnexpectedParse::Unexpected
586    }
587    #[inline]
588    fn unexpected_range(_: Range) -> Self {
589        UnexpectedParse::Unexpected
590    }
591    #[inline]
592    fn unexpected_format<T>(_: T) -> Self
593    where
594        T: fmt::Display,
595    {
596        UnexpectedParse::Unexpected
597    }
598
599    #[inline]
600    fn expected_token(_: Item) -> Self {
601        UnexpectedParse::Unexpected
602    }
603    #[inline]
604    fn expected_range(_: Range) -> Self {
605        UnexpectedParse::Unexpected
606    }
607    #[inline]
608    fn expected_format<T>(_: T) -> Self
609    where
610        T: fmt::Display,
611    {
612        UnexpectedParse::Unexpected
613    }
614    #[inline]
615    fn message_format<T>(_: T) -> Self
616    where
617        T: fmt::Display,
618    {
619        UnexpectedParse::Unexpected
620    }
621    #[inline]
622    fn message_token(_: Item) -> Self {
623        UnexpectedParse::Unexpected
624    }
625    #[inline]
626    fn message_range(_: Range) -> Self {
627        UnexpectedParse::Unexpected
628    }
629
630    #[inline]
631    fn end_of_input() -> Self {
632        UnexpectedParse::Eoi
633    }
634
635    #[inline]
636    fn is_unexpected_end_of_input(&self) -> bool {
637        *self == UnexpectedParse::Eoi
638    }
639
640    #[inline]
641    fn into_other<T>(self) -> T
642    where
643        T: StreamError<Item, Range>,
644    {
645        match self {
646            UnexpectedParse::Unexpected => T::unexpected_static_message("parse"),
647            UnexpectedParse::Eoi => T::end_of_input(),
648        }
649    }
650}
651
652impl<Item, Range, Position> ParseError<Item, Range, Position> for UnexpectedParse
653where
654    Position: Default,
655{
656    type StreamError = Self;
657    #[inline]
658    fn empty(_position: Position) -> Self {
659        UnexpectedParse::Unexpected
660    }
661
662    #[inline]
663    fn from_error(_: Position, err: Self::StreamError) -> Self {
664        err
665    }
666
667    fn position(&self) -> Position {
668        Position::default()
669    }
670
671    #[inline]
672    fn set_position(&mut self, _position: Position) {}
673
674    #[inline]
675    fn add(&mut self, err: Self::StreamError) {
676        *self = match (*self, err) {
677            (UnexpectedParse::Eoi, _) => UnexpectedParse::Eoi,
678            (_, err) => err,
679        };
680    }
681
682    #[inline]
683    fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
684    where
685        F: FnOnce(&mut Tracked<Self>),
686    {
687        f(self_);
688        self_.error = info;
689    }
690
691    fn is_unexpected_end_of_input(&self) -> bool {
692        *self == UnexpectedParse::Eoi
693    }
694
695    #[inline]
696    fn into_other<T>(self) -> T
697    where
698        T: ParseError<Item, Range, Position>,
699    {
700        T::from_error(Position::default(), StreamError::into_other(self))
701    }
702}
703
704impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for UnexpectedParse
705where
706    Position: Default,
707{
708    fn into_other_error<T, Item2, Range2, Position2>(self) -> T
709    where
710        T: ParseError<Item2, Range2, Position2>,
711        Item2: From<Item>,
712        Range2: From<Range>,
713        Position2: From<Position>,
714    {
715        T::from_error(
716            Position::default().into(),
717            StreamErrorInto::<Item, Range>::into_other_error(self),
718        )
719    }
720}
721
722impl<Item, Range> StreamErrorInto<Item, Range> for UnexpectedParse {
723    fn into_other_error<T, Item2, Range2>(self) -> T
724    where
725        T: StreamError<Item2, Range2>,
726        Item2: From<Item>,
727        Range2: From<Range>,
728    {
729        StreamError::into_other(self)
730    }
731}
732
733#[derive(Clone, Copy, Debug, PartialEq)]
734pub enum StringStreamError {
735    UnexpectedParse,
736    Eoi,
737    CharacterBoundary,
738}
739
740pub(crate) const CHAR_BOUNDARY_ERROR_MESSAGE: &str = "unexpected slice on character boundary";
741
742impl fmt::Display for StringStreamError {
743    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
744        write!(f, "{}", self.as_str())
745    }
746}
747
748#[cfg(feature = "std")]
749impl StdError for StringStreamError {
750    fn description(&self) -> &str {
751        self.as_str()
752    }
753}
754
755impl StringStreamError {
756    fn as_str(&self) -> &str {
757        use self::StringStreamError::*;
758        match *self {
759            UnexpectedParse => "unexpected parse",
760            Eoi => "unexpected end of input",
761            CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE,
762        }
763    }
764}
765
766impl<Item, Range> StreamError<Item, Range> for StringStreamError {
767    #[inline]
768    fn unexpected_token(_: Item) -> Self {
769        StringStreamError::UnexpectedParse
770    }
771    #[inline]
772    fn unexpected_range(_: Range) -> Self {
773        StringStreamError::UnexpectedParse
774    }
775    #[inline]
776    fn unexpected_format<T>(_msg: T) -> Self
777    where
778        T: fmt::Display,
779    {
780        StringStreamError::UnexpectedParse
781    }
782
783    #[inline]
784    fn expected_token(_: Item) -> Self {
785        StringStreamError::UnexpectedParse
786    }
787    #[inline]
788    fn expected_range(_: Range) -> Self {
789        StringStreamError::UnexpectedParse
790    }
791    #[inline]
792    fn expected_format<T>(_: T) -> Self
793    where
794        T: fmt::Display,
795    {
796        StringStreamError::UnexpectedParse
797    }
798    #[inline]
799    fn message_format<T>(_: T) -> Self
800    where
801        T: fmt::Display,
802    {
803        StringStreamError::UnexpectedParse
804    }
805    #[inline]
806    fn message_token(_: Item) -> Self {
807        StringStreamError::UnexpectedParse
808    }
809    #[inline]
810    fn message_range(_: Range) -> Self {
811        StringStreamError::UnexpectedParse
812    }
813    fn message_static_message(msg: &'static str) -> Self {
814        if msg == CHAR_BOUNDARY_ERROR_MESSAGE {
815            StringStreamError::CharacterBoundary
816        } else {
817            StringStreamError::UnexpectedParse
818        }
819    }
820    #[inline]
821    fn end_of_input() -> Self {
822        StringStreamError::Eoi
823    }
824    #[inline]
825    fn is_unexpected_end_of_input(&self) -> bool {
826        *self == StringStreamError::Eoi
827    }
828    #[inline]
829    fn into_other<T>(self) -> T
830    where
831        T: StreamError<Item, Range>,
832    {
833        let msg = match self {
834            StringStreamError::CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE,
835            StringStreamError::UnexpectedParse => "parse",
836            StringStreamError::Eoi => return T::end_of_input(),
837        };
838        T::unexpected_static_message(msg)
839    }
840}
841impl<Item, Range, Position> ParseError<Item, Range, Position> for StringStreamError
842where
843    Position: Default,
844{
845    type StreamError = Self;
846    #[inline]
847    fn empty(_position: Position) -> Self {
848        StringStreamError::UnexpectedParse
849    }
850    #[inline]
851    fn from_error(_: Position, err: Self::StreamError) -> Self {
852        err
853    }
854
855    fn position(&self) -> Position {
856        Position::default()
857    }
858
859    #[inline]
860    fn set_position(&mut self, _position: Position) {}
861
862    #[inline]
863    fn add(&mut self, err: Self::StreamError) {
864        *self = match (*self, err) {
865            (StringStreamError::Eoi, _) => StringStreamError::Eoi,
866            (_, err) => err,
867        };
868    }
869
870    #[inline]
871    fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
872    where
873        F: FnOnce(&mut Tracked<Self>),
874    {
875        f(self_);
876        self_.error = info;
877    }
878
879    fn is_unexpected_end_of_input(&self) -> bool {
880        *self == StringStreamError::Eoi
881    }
882
883    #[inline]
884    fn into_other<T>(self) -> T
885    where
886        T: ParseError<Item, Range, Position>,
887    {
888        T::from_error(Position::default(), StreamError::into_other(self))
889    }
890}
891
892impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for StringStreamError
893where
894    Position: Default,
895{
896    fn into_other_error<T, Item2, Range2, Position2>(self) -> T
897    where
898        T: ParseError<Item2, Range2, Position2>,
899        Item2: From<Item>,
900        Range2: From<Range>,
901        Position2: From<Position>,
902    {
903        T::from_error(
904            Position::default().into(),
905            StreamErrorInto::<Item, Range>::into_other_error(self),
906        )
907    }
908}
909
910impl<Item, Range> StreamErrorInto<Item, Range> for StringStreamError {
911    fn into_other_error<T, Item2, Range2>(self) -> T
912    where
913        T: StreamError<Item2, Range2>,
914        Item2: From<Item>,
915        Range2: From<Range>,
916    {
917        StreamError::into_other(self)
918    }
919}
920
921/// Error wrapper which lets parsers track which parser in a sequence of sub-parsers has emitted
922/// the error. `Tracked::from` can be used to construct this and it should otherwise be
923/// ignored outside of combine.
924#[derive(Clone, PartialEq, Debug, Copy)]
925pub struct Tracked<E> {
926    /// The error returned
927    pub error: E,
928    #[doc(hidden)]
929    pub offset: ErrorOffset,
930}
931
932impl<E> From<E> for Tracked<E> {
933    fn from(error: E) -> Self {
934        Tracked {
935            error,
936            offset: ErrorOffset(1),
937        }
938    }
939}
940
941/// A `Result` type which has the committed status flattened into the result.
942/// Conversions to and from `std::result::Result` can be done using `result.into()` or
943/// `From::from(result)`
944#[derive(Clone, PartialEq, Debug, Copy)]
945pub enum ParseResult<T, E> {
946    /// The parser has succeeded and has committed to this parse. If a parser after this fails,
947    /// other parser alternatives will not be attempted (`CommitErr` will be returned)
948    CommitOk(T),
949    /// The parser has succeeded and has not committed to this parse. If a parser after this fails,
950    /// other parser alternatives will be attempted (`PeekErr` will be returned)
951    PeekOk(T),
952    /// The parser failed other parse alternatives will not be attempted.
953    CommitErr(E),
954    /// The parser failed but other parse alternatives may be attempted.
955    PeekErr(Tracked<E>),
956}
957
958impl<T, E> ParseResult<T, E> {
959    #[inline]
960    pub fn is_ok(&self) -> bool {
961        match *self {
962            CommitOk(_) | PeekOk(_) => true,
963            CommitErr(_) | PeekErr(_) => false,
964        }
965    }
966
967    #[inline]
968    pub fn is_err(&self) -> bool {
969        !self.is_ok()
970    }
971
972    pub fn as_ref(&self) -> ParseResult<&T, &E> {
973        match *self {
974            CommitOk(ref t) => CommitOk(t),
975            PeekOk(ref t) => PeekOk(t),
976            CommitErr(ref e) => CommitErr(e),
977            PeekErr(ref e) => PeekErr(Tracked {
978                error: &e.error,
979                offset: e.offset,
980            }),
981        }
982    }
983
984    pub fn and_then<F, T2>(self, f: F) -> F::Output
985    where
986        F: FnOnce(T) -> ParseResult<T2, E>,
987    {
988        match self {
989            CommitOk(t) => match f(t) {
990                CommitOk(t2) | PeekOk(t2) => CommitOk(t2),
991                PeekErr(e) => CommitErr(e.error),
992                CommitErr(e) => CommitErr(e),
993            },
994            PeekOk(t) => f(t),
995            CommitErr(e) => CommitErr(e),
996            PeekErr(e) => PeekErr(e),
997        }
998    }
999
1000    pub fn map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output>
1001    where
1002        F: FnOnce(E) -> E2,
1003    {
1004        match self {
1005            CommitOk(t) => CommitOk(t),
1006            PeekOk(t) => PeekOk(t),
1007            CommitErr(e) => CommitErr(f(e)),
1008            PeekErr(e) => PeekErr(Tracked {
1009                error: f(e.error),
1010                offset: e.offset,
1011            }),
1012        }
1013    }
1014
1015    pub fn map<F, T2>(self, f: F) -> ParseResult<F::Output, E>
1016    where
1017        F: FnOnce(T) -> T2,
1018    {
1019        match self {
1020            CommitOk(t) => CommitOk(f(t)),
1021            PeekOk(t) => PeekOk(f(t)),
1022            CommitErr(e) => CommitErr(e),
1023            PeekErr(e) => PeekErr(e),
1024        }
1025    }
1026}
1027
1028impl<O, E> ParseResult<O, E> {
1029    pub fn into_result(self) -> StdParseResult2<O, E> {
1030        self.into()
1031    }
1032}
1033
1034impl<T, E> Into<Result<Commit<T>, Commit<Tracked<E>>>> for ParseResult<T, E> {
1035    #[inline]
1036    fn into(self) -> Result<Commit<T>, Commit<Tracked<E>>> {
1037        match self {
1038            CommitOk(t) => Ok(Commit::Commit(t)),
1039            PeekOk(t) => Ok(Commit::Peek(t)),
1040            CommitErr(e) => Err(Commit::Commit(e.into())),
1041            PeekErr(e) => Err(Commit::Peek(e)),
1042        }
1043    }
1044}
1045
1046impl<O, E> Into<StdParseResult2<O, E>> for ParseResult<O, E> {
1047    #[inline]
1048    fn into(self) -> StdParseResult2<O, E> {
1049        use self::ParseResult::*;
1050
1051        match self {
1052            CommitOk(t) => Ok((t, Commit::Commit(()))),
1053            PeekOk(t) => Ok((t, Commit::Peek(()))),
1054            CommitErr(e) => Err(Commit::Commit(e.into())),
1055            PeekErr(e) => Err(Commit::Peek(e)),
1056        }
1057    }
1058}
1059
1060impl<O, E> From<StdParseResult2<O, E>> for ParseResult<O, E> {
1061    #[inline]
1062    fn from(result: StdParseResult2<O, E>) -> ParseResult<O, E> {
1063        use self::ParseResult::*;
1064
1065        match result {
1066            Ok((t, Commit::Commit(()))) => CommitOk(t),
1067            Ok((t, Commit::Peek(()))) => PeekOk(t),
1068            Err(Commit::Commit(e)) => CommitErr(e.error),
1069            Err(Commit::Peek(e)) => PeekErr(e),
1070        }
1071    }
1072}
1073
1074#[cfg(all(feature = "std", test))]
1075mod tests_std {
1076
1077    use crate::Parser;
1078
1079    #[derive(Clone, PartialEq, Debug)]
1080    struct CloneOnly {
1081        s: String,
1082    }
1083
1084    #[test]
1085    fn parse_clone_but_not_copy() {
1086        // This verifies we can parse slice references with an token type that is Clone but not Copy.
1087        let input = &[
1088            CloneOnly { s: "x".to_string() },
1089            CloneOnly { s: "y".to_string() },
1090        ][..];
1091        let result = crate::parser::range::take_while(|c: CloneOnly| c.s == "x").parse(input);
1092        assert_eq!(
1093            result,
1094            Ok((
1095                &[CloneOnly { s: "x".to_string() }][..],
1096                &[CloneOnly { s: "y".to_string() }][..]
1097            ))
1098        );
1099    }
1100}