1 use crate::lib::fmt;
2 
3 #[cfg(feature = "std")]
4 use std::error::Error as StdError;
5 
6 use crate::{stream::StreamOnce, ErrorOffset};
7 
8 use self::ParseResult::*;
9 
10 pub(crate) trait ResultExt<E, T> {
committed(self) -> ParseResult<E, T>11     fn committed(self) -> ParseResult<E, T>;
12 }
13 
14 impl<E, T> ResultExt<E, T> for Result<E, T> {
committed(self) -> ParseResult<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)]
25 macro_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`
44 pub trait ErrorInfo<'s, T, R> {
45     type Format: fmt::Display;
46 
47     #[allow(clippy::wrong_self_convention)]
into_info(&'s self) -> Info<T, R, Self::Format>48     fn into_info(&'s self) -> Info<T, R, Self::Format>;
49 }
50 
51 impl<'s, 'a, T, R, F> ErrorInfo<'s, T, R> for &'a F
52 where
53     F: ErrorInfo<'s, T, R>,
54 {
55     type Format = F::Format;
into_info(&'s self) -> Info<T, R, Self::Format>56     fn into_info(&'s self) -> Info<T, R, Self::Format> {
57         (**self).into_info()
58     }
59 }
60 
61 #[derive(Clone, Debug)]
62 pub enum Info<T, R, F = &'static str> {
63     Token(T),
64     Range(R),
65     Static(&'static str),
66     Format(F),
67 }
68 
69 impl<'s, T, R, F> ErrorInfo<'s, T, R> for Info<T, R, F>
70 where
71     T: Clone,
72     R: Clone,
73     F: fmt::Display + 's,
74 {
75     type Format = &'s F;
into_info(&'s self) -> Info<T, R, <Self as ErrorInfo<'_, T, R>>::Format>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 
86 impl<R, F> From<char> for Info<char, R, F> {
from(s: char) -> Self87     fn from(s: char) -> Self {
88         Info::Token(s)
89     }
90 }
91 
92 impl<'s, R> ErrorInfo<'s, char, R> for char {
93     type Format = &'static str;
into_info(&self) -> Info<char, R, Self::Format>94     fn into_info(&self) -> Info<char, R, Self::Format> {
95         Info::Token(*self)
96     }
97 }
98 
99 impl<T, R, F> From<&'static str> for Info<T, R, F> {
from(s: &'static str) -> Self100     fn from(s: &'static str) -> Self {
101         Info::Static(s)
102     }
103 }
104 
105 impl<'s, T, R> ErrorInfo<'s, T, R> for &'static str {
106     type Format = &'static str;
into_info(&self) -> Info<T, R, Self::Format>107     fn into_info(&self) -> Info<T, R, Self::Format> {
108         Info::Static(*self)
109     }
110 }
111 
112 impl<R, F> From<u8> for Info<u8, R, F> {
from(s: u8) -> Self113     fn from(s: u8) -> Self {
114         Info::Token(s)
115     }
116 }
117 
118 impl<R> ErrorInfo<'_, Self, R> for u8 {
119     type Format = &'static str;
into_info(&self) -> Info<Self, R, Self::Format>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`
126 pub struct Token<T>(pub T);
127 
128 impl<T, R> From<Token<T>> for Info<T, R, &'static str> {
from(s: Token<T>) -> Self129     fn from(s: Token<T>) -> Self {
130         Info::Token(s.0)
131     }
132 }
133 
134 impl<'s, T, R> ErrorInfo<'s, T, R> for Token<T>
135 where
136     T: Clone,
137 {
138     type Format = &'static str;
into_info(&'s self) -> Info<T, R, Self::Format>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`
145 pub struct Range<R>(pub R);
146 
147 impl<T, R> From<Range<R>> for Info<T, R, &'static str> {
from(s: Range<R>) -> Self148     fn from(s: Range<R>) -> Self {
149         Info::Range(s.0)
150     }
151 }
152 
153 impl<'s, T, R> ErrorInfo<'s, T, R> for Range<R>
154 where
155     R: Clone,
156 {
157     type Format = &'static str;
into_info(&'s self) -> Info<T, R, Self::Format>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.
165 pub struct Static(&'static str);
166 
167 impl<T, R, F> From<Static> for Info<T, R, F>
168 where
169     F: fmt::Display,
170 {
from(s: Static) -> Self171     fn from(s: Static) -> Self {
172         Info::Static(s.0)
173     }
174 }
175 
176 impl<'s, T, R> ErrorInfo<'s, T, R> for Static {
177     type Format = &'static str;
into_info(&'s self) -> Info<T, R, Self::Format>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`
184 pub struct Format<F>(pub F)
185 where
186     F: fmt::Display;
187 
188 impl<T, R, F> From<Format<F>> for Info<T, R, F>
189 where
190     F: fmt::Display,
191 {
from(s: Format<F>) -> Self192     fn from(s: Format<F>) -> Self {
193         Info::Format(s.0)
194     }
195 }
196 
197 impl<'s, T, R, F> ErrorInfo<'s, T, R> for Format<F>
198 where
199     F: fmt::Display + 's,
200 {
201     type Format = &'s F;
into_info(&'s self) -> Info<T, R, Self::Format>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)]
213 pub 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 
222 impl<T> AsMut<T> for Commit<T> {
as_mut(&mut self) -> &mut T223     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 
230 impl<T> AsRef<T> for Commit<T> {
as_ref(&self) -> &T231     fn as_ref(&self) -> &T {
232         match *self {
233             Commit::Peek(ref t) | Commit::Commit(ref t) => t,
234         }
235     }
236 }
237 
238 impl<T> Commit<T> {
239     /// Returns true if `self` is peek.
is_peek(&self) -> bool240     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.
into_inner(self) -> T248     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.
into_commit(self) -> Commit<T>255     pub fn into_commit(self) -> Commit<T> {
256         Commit::Commit(self.into_inner())
257     }
258 
259     /// Converts `self` into the `Peek` state.
into_peek(self) -> Commit<T>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.
map<F, U>(self, f: F) -> Commit<U> where F: FnOnce(T) -> U,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 
merge(&self, current: Commit<T>) -> Commit<T>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     /// ```
combine<F, U, E>(self, f: F) -> StdParseResult2<U, E> where F: FnOnce(T) -> StdParseResult2<U, E>,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     }
combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E> where F: FnOnce(T) -> ParseResult<U, E>,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.
358 pub type StdParseResult<O, Input> =
359     Result<(O, Commit<()>), Commit<Tracked<<Input as StreamOnce>::Error>>>;
360 pub 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.
366 pub trait StreamError<Item, Range>: Sized {
unexpected_token(token: Item) -> Self367     fn unexpected_token(token: Item) -> Self;
unexpected_range(token: Range) -> Self368     fn unexpected_range(token: Range) -> Self;
unexpected_format<T>(msg: T) -> Self where T: fmt::Display369     fn unexpected_format<T>(msg: T) -> Self
370     where
371         T: fmt::Display;
unexpected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,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     }
unexpected_static_message(msg: &'static str) -> Self383     fn unexpected_static_message(msg: &'static str) -> Self {
384         Self::unexpected_format(msg)
385     }
386 
expected_token(token: Item) -> Self387     fn expected_token(token: Item) -> Self;
expected_range(token: Range) -> Self388     fn expected_range(token: Range) -> Self;
expected_format<T>(msg: T) -> Self where T: fmt::Display389     fn expected_format<T>(msg: T) -> Self
390     where
391         T: fmt::Display;
expected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,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     }
expected_static_message(msg: &'static str) -> Self403     fn expected_static_message(msg: &'static str) -> Self {
404         Self::expected_format(msg)
405     }
406 
message_token(token: Item) -> Self407     fn message_token(token: Item) -> Self;
message_range(token: Range) -> Self408     fn message_range(token: Range) -> Self;
message_format<T>(msg: T) -> Self where T: fmt::Display409     fn message_format<T>(msg: T) -> Self
410     where
411         T: fmt::Display;
message_static_message(msg: &'static str) -> Self412     fn message_static_message(msg: &'static str) -> Self {
413         Self::message_format(msg)
414     }
message<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,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")]
other<E>(err: E) -> Self where E: StdError + Send + Sync + 'static,428     fn other<E>(err: E) -> Self
429     where
430         E: StdError + Send + Sync + 'static,
431     {
432         Self::message_format(err)
433     }
434 
end_of_input() -> Self435     fn end_of_input() -> Self {
436         Self::unexpected_static_message("end of input")
437     }
438 
is_unexpected_end_of_input(&self) -> bool439     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.
into_other<T>(self) -> T where T: StreamError<Item, Range>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.
455 pub 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.
empty(position: Position) -> Self461     fn empty(position: Position) -> Self;
462 
463     /// Creates a `ParseError` from a single `Self::StreamError`
from_error(position: Position, err: Self::StreamError) -> Self464     fn from_error(position: Position, err: Self::StreamError) -> Self {
465         let mut errors = Self::empty(position);
466         errors.add(err);
467         errors
468     }
469 
position(&self) -> Position470     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`
set_position(&mut self, position: Position)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`.
merge(self, other: Self) -> Self481     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
add(&mut self, err: Self::StreamError)489     fn add(&mut self, err: Self::StreamError);
490 
add_expected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,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 
add_unexpected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,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 
add_message<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,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`
set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<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`
clear_expected(&mut self)518     fn clear_expected(&mut self) {}
519 
is_unexpected_end_of_input(&self) -> bool520     fn is_unexpected_end_of_input(&self) -> bool;
521 
522     /// Does a best-effort conversion of `self` into another `ParseError`
into_other<T>(self) -> T where T: ParseError<Item, Range, Position>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)
532 pub trait ParseErrorInto<Item, Range, Position>: Sized {
into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>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)
545 pub trait StreamErrorInto<Item, Range>: Sized {
into_other_error<T, Item2, Range2>(self) -> T where T: StreamError<Item2, Range2>, Item2: From<Item>, Range2: From<Range>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)]
554 pub enum UnexpectedParse {
555     Eoi,
556     Unexpected,
557 }
558 
559 impl fmt::Display for UnexpectedParse {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result560     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561         write!(f, "{}", self.as_str())
562     }
563 }
564 
565 #[cfg(feature = "std")]
566 impl StdError for UnexpectedParse {
description(&self) -> &str567     fn description(&self) -> &str {
568         self.as_str()
569     }
570 }
571 
572 impl UnexpectedParse {
as_str(&self) -> &str573     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 
582 impl<Item, Range> StreamError<Item, Range> for UnexpectedParse {
583     #[inline]
unexpected_token(_: Item) -> Self584     fn unexpected_token(_: Item) -> Self {
585         UnexpectedParse::Unexpected
586     }
587     #[inline]
unexpected_range(_: Range) -> Self588     fn unexpected_range(_: Range) -> Self {
589         UnexpectedParse::Unexpected
590     }
591     #[inline]
unexpected_format<T>(_: T) -> Self where T: fmt::Display,592     fn unexpected_format<T>(_: T) -> Self
593     where
594         T: fmt::Display,
595     {
596         UnexpectedParse::Unexpected
597     }
598 
599     #[inline]
expected_token(_: Item) -> Self600     fn expected_token(_: Item) -> Self {
601         UnexpectedParse::Unexpected
602     }
603     #[inline]
expected_range(_: Range) -> Self604     fn expected_range(_: Range) -> Self {
605         UnexpectedParse::Unexpected
606     }
607     #[inline]
expected_format<T>(_: T) -> Self where T: fmt::Display,608     fn expected_format<T>(_: T) -> Self
609     where
610         T: fmt::Display,
611     {
612         UnexpectedParse::Unexpected
613     }
614     #[inline]
message_format<T>(_: T) -> Self where T: fmt::Display,615     fn message_format<T>(_: T) -> Self
616     where
617         T: fmt::Display,
618     {
619         UnexpectedParse::Unexpected
620     }
621     #[inline]
message_token(_: Item) -> Self622     fn message_token(_: Item) -> Self {
623         UnexpectedParse::Unexpected
624     }
625     #[inline]
message_range(_: Range) -> Self626     fn message_range(_: Range) -> Self {
627         UnexpectedParse::Unexpected
628     }
629 
630     #[inline]
end_of_input() -> Self631     fn end_of_input() -> Self {
632         UnexpectedParse::Eoi
633     }
634 
635     #[inline]
is_unexpected_end_of_input(&self) -> bool636     fn is_unexpected_end_of_input(&self) -> bool {
637         *self == UnexpectedParse::Eoi
638     }
639 
640     #[inline]
into_other<T>(self) -> T where T: StreamError<Item, Range>,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 
652 impl<Item, Range, Position> ParseError<Item, Range, Position> for UnexpectedParse
653 where
654     Position: Default,
655 {
656     type StreamError = Self;
657     #[inline]
empty(_position: Position) -> Self658     fn empty(_position: Position) -> Self {
659         UnexpectedParse::Unexpected
660     }
661 
662     #[inline]
from_error(_: Position, err: Self::StreamError) -> Self663     fn from_error(_: Position, err: Self::StreamError) -> Self {
664         err
665     }
666 
position(&self) -> Position667     fn position(&self) -> Position {
668         Position::default()
669     }
670 
671     #[inline]
set_position(&mut self, _position: Position)672     fn set_position(&mut self, _position: Position) {}
673 
674     #[inline]
add(&mut self, err: Self::StreamError)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]
set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),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 
is_unexpected_end_of_input(&self) -> bool691     fn is_unexpected_end_of_input(&self) -> bool {
692         *self == UnexpectedParse::Eoi
693     }
694 
695     #[inline]
into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,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 
704 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for UnexpectedParse
705 where
706     Position: Default,
707 {
into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,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 
722 impl<Item, Range> StreamErrorInto<Item, Range> for UnexpectedParse {
into_other_error<T, Item2, Range2>(self) -> T where T: StreamError<Item2, Range2>, Item2: From<Item>, Range2: From<Range>,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)]
734 pub enum StringStreamError {
735     UnexpectedParse,
736     Eoi,
737     CharacterBoundary,
738 }
739 
740 pub(crate) const CHAR_BOUNDARY_ERROR_MESSAGE: &str = "unexpected slice on character boundary";
741 
742 impl fmt::Display for StringStreamError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result743     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
744         write!(f, "{}", self.as_str())
745     }
746 }
747 
748 #[cfg(feature = "std")]
749 impl StdError for StringStreamError {
description(&self) -> &str750     fn description(&self) -> &str {
751         self.as_str()
752     }
753 }
754 
755 impl StringStreamError {
as_str(&self) -> &str756     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 
766 impl<Item, Range> StreamError<Item, Range> for StringStreamError {
767     #[inline]
unexpected_token(_: Item) -> Self768     fn unexpected_token(_: Item) -> Self {
769         StringStreamError::UnexpectedParse
770     }
771     #[inline]
unexpected_range(_: Range) -> Self772     fn unexpected_range(_: Range) -> Self {
773         StringStreamError::UnexpectedParse
774     }
775     #[inline]
unexpected_format<T>(_msg: T) -> Self where T: fmt::Display,776     fn unexpected_format<T>(_msg: T) -> Self
777     where
778         T: fmt::Display,
779     {
780         StringStreamError::UnexpectedParse
781     }
782 
783     #[inline]
expected_token(_: Item) -> Self784     fn expected_token(_: Item) -> Self {
785         StringStreamError::UnexpectedParse
786     }
787     #[inline]
expected_range(_: Range) -> Self788     fn expected_range(_: Range) -> Self {
789         StringStreamError::UnexpectedParse
790     }
791     #[inline]
expected_format<T>(_: T) -> Self where T: fmt::Display,792     fn expected_format<T>(_: T) -> Self
793     where
794         T: fmt::Display,
795     {
796         StringStreamError::UnexpectedParse
797     }
798     #[inline]
message_format<T>(_: T) -> Self where T: fmt::Display,799     fn message_format<T>(_: T) -> Self
800     where
801         T: fmt::Display,
802     {
803         StringStreamError::UnexpectedParse
804     }
805     #[inline]
message_token(_: Item) -> Self806     fn message_token(_: Item) -> Self {
807         StringStreamError::UnexpectedParse
808     }
809     #[inline]
message_range(_: Range) -> Self810     fn message_range(_: Range) -> Self {
811         StringStreamError::UnexpectedParse
812     }
message_static_message(msg: &'static str) -> Self813     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]
end_of_input() -> Self821     fn end_of_input() -> Self {
822         StringStreamError::Eoi
823     }
824     #[inline]
is_unexpected_end_of_input(&self) -> bool825     fn is_unexpected_end_of_input(&self) -> bool {
826         *self == StringStreamError::Eoi
827     }
828     #[inline]
into_other<T>(self) -> T where T: StreamError<Item, Range>,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 }
841 impl<Item, Range, Position> ParseError<Item, Range, Position> for StringStreamError
842 where
843     Position: Default,
844 {
845     type StreamError = Self;
846     #[inline]
empty(_position: Position) -> Self847     fn empty(_position: Position) -> Self {
848         StringStreamError::UnexpectedParse
849     }
850     #[inline]
from_error(_: Position, err: Self::StreamError) -> Self851     fn from_error(_: Position, err: Self::StreamError) -> Self {
852         err
853     }
854 
position(&self) -> Position855     fn position(&self) -> Position {
856         Position::default()
857     }
858 
859     #[inline]
set_position(&mut self, _position: Position)860     fn set_position(&mut self, _position: Position) {}
861 
862     #[inline]
add(&mut self, err: Self::StreamError)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]
set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),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 
is_unexpected_end_of_input(&self) -> bool879     fn is_unexpected_end_of_input(&self) -> bool {
880         *self == StringStreamError::Eoi
881     }
882 
883     #[inline]
into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,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 
892 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for StringStreamError
893 where
894     Position: Default,
895 {
into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,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 
910 impl<Item, Range> StreamErrorInto<Item, Range> for StringStreamError {
into_other_error<T, Item2, Range2>(self) -> T where T: StreamError<Item2, Range2>, Item2: From<Item>, Range2: From<Range>,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)]
925 pub struct Tracked<E> {
926     /// The error returned
927     pub error: E,
928     #[doc(hidden)]
929     pub offset: ErrorOffset,
930 }
931 
932 impl<E> From<E> for Tracked<E> {
from(error: E) -> Self933     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)]
945 pub 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 
958 impl<T, E> ParseResult<T, E> {
959     #[inline]
is_ok(&self) -> bool960     pub fn is_ok(&self) -> bool {
961         match *self {
962             CommitOk(_) | PeekOk(_) => true,
963             CommitErr(_) | PeekErr(_) => false,
964         }
965     }
966 
967     #[inline]
is_err(&self) -> bool968     pub fn is_err(&self) -> bool {
969         !self.is_ok()
970     }
971 
as_ref(&self) -> ParseResult<&T, &E>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 
and_then<F, T2>(self, f: F) -> F::Output where F: FnOnce(T) -> ParseResult<T2, E>,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 
map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output> where F: FnOnce(E) -> E2,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 
map<F, T2>(self, f: F) -> ParseResult<F::Output, E> where F: FnOnce(T) -> T2,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 
1028 impl<O, E> ParseResult<O, E> {
into_result(self) -> StdParseResult2<O, E>1029     pub fn into_result(self) -> StdParseResult2<O, E> {
1030         self.into()
1031     }
1032 }
1033 
1034 impl<T, E> Into<Result<Commit<T>, Commit<Tracked<E>>>> for ParseResult<T, E> {
1035     #[inline]
into(self) -> Result<Commit<T>, Commit<Tracked<E>>>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 
1046 impl<O, E> Into<StdParseResult2<O, E>> for ParseResult<O, E> {
1047     #[inline]
into(self) -> StdParseResult2<O, E>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 
1060 impl<O, E> From<StdParseResult2<O, E>> for ParseResult<O, E> {
1061     #[inline]
from(result: StdParseResult2<O, E>) -> ParseResult<O, E>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))]
1075 mod tests_std {
1076 
1077     use crate::Parser;
1078 
1079     #[derive(Clone, PartialEq, Debug)]
1080     struct CloneOnly {
1081         s: String,
1082     }
1083 
1084     #[test]
parse_clone_but_not_copy()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 }
1101