• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     ///           Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
300     /// {
301     ///     let (c, committed) = satisfy(|c| c != '"').parse_stream(input).into_result()?;
302     ///     match c {
303     ///         //Since the `char` parser has already committed some of the input `combine` is used
304     ///         //propagate the committed state to the next part of the parser
305     ///         '\\' => committed.combine(|_| {
306     ///             satisfy(|c| c == '"' || c == '\\')
307     ///                 .map(|c| {
308     ///                     match c {
309     ///                         '"' => '"',
310     ///                         '\\' => '\\',
311     ///                         c => c
312     ///                     }
313     ///                 })
314     ///                 .parse_stream(input)
315     ///                 .into_result()
316     ///             }),
317     ///         _ => Ok((c, committed))
318     ///     }
319     /// }
320     /// let result = many(parser(char))
321     ///     .easy_parse(r#"abc\"\\"#);
322     /// assert_eq!(result, Ok((r#"abc"\"#.to_string(), "")));
323     /// }
324     /// ```
combine<F, U, E>(self, f: F) -> StdParseResult2<U, E> where F: FnOnce(T) -> StdParseResult2<U, E>,325     pub fn combine<F, U, E>(self, f: F) -> StdParseResult2<U, E>
326     where
327         F: FnOnce(T) -> StdParseResult2<U, E>,
328     {
329         match self {
330             Commit::Commit(x) => match f(x) {
331                 Ok((v, Commit::Peek(()))) => Ok((v, Commit::Commit(()))),
332                 Err(Commit::Peek(err)) => Err(Commit::Commit(err)),
333                 y => y,
334             },
335             Commit::Peek(x) => f(x),
336         }
337     }
combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E> where F: FnOnce(T) -> ParseResult<U, E>,338     pub fn combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E>
339     where
340         F: FnOnce(T) -> ParseResult<U, E>,
341     {
342         use self::ParseResult::*;
343 
344         match self {
345             Commit::Commit(x) => match f(x) {
346                 PeekOk(v) => CommitOk(v),
347                 PeekErr(err) => CommitErr(err.error),
348                 y => y,
349             },
350             Commit::Peek(x) => f(x),
351         }
352     }
353 }
354 
355 /// A type alias over the specific `Result` type used by parsers to indicate whether they were
356 /// successful or not.
357 /// `O` is the type that is output on success.
358 /// `Input` is the specific stream type used in the parser.
359 pub type StdParseResult<O, Input> =
360     Result<(O, Commit<()>), Commit<Tracked<<Input as StreamOnce>::Error>>>;
361 pub type StdParseResult2<O, E> = Result<(O, Commit<()>), Commit<Tracked<E>>>;
362 
363 /// `StreamError` represents a single error returned from a `Stream` or a `Parser`.
364 ///
365 /// Usually multiple instances of `StreamError` is composed into a `ParseError` to build the final
366 /// error value.
367 pub trait StreamError<Item, Range>: Sized {
unexpected_token(token: Item) -> Self368     fn unexpected_token(token: Item) -> Self;
unexpected_range(token: Range) -> Self369     fn unexpected_range(token: Range) -> Self;
unexpected_format<T>(msg: T) -> Self where T: fmt::Display370     fn unexpected_format<T>(msg: T) -> Self
371     where
372         T: fmt::Display;
unexpected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,373     fn unexpected<E>(info: E) -> Self
374     where
375         E: for<'s> ErrorInfo<'s, Item, Range>,
376     {
377         match info.into_info() {
378             Info::Token(b) => Self::unexpected_token(b),
379             Info::Range(b) => Self::unexpected_range(b),
380             Info::Static(b) => Self::unexpected_static_message(b),
381             Info::Format(b) => Self::unexpected_format(b),
382         }
383     }
unexpected_static_message(msg: &'static str) -> Self384     fn unexpected_static_message(msg: &'static str) -> Self {
385         Self::unexpected_format(msg)
386     }
387 
expected_token(token: Item) -> Self388     fn expected_token(token: Item) -> Self;
expected_range(token: Range) -> Self389     fn expected_range(token: Range) -> Self;
expected_format<T>(msg: T) -> Self where T: fmt::Display390     fn expected_format<T>(msg: T) -> Self
391     where
392         T: fmt::Display;
expected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,393     fn expected<E>(info: E) -> Self
394     where
395         E: for<'s> ErrorInfo<'s, Item, Range>,
396     {
397         match info.into_info() {
398             Info::Token(b) => Self::expected_token(b),
399             Info::Range(b) => Self::expected_range(b),
400             Info::Static(b) => Self::expected_static_message(b),
401             Info::Format(b) => Self::expected_format(b),
402         }
403     }
expected_static_message(msg: &'static str) -> Self404     fn expected_static_message(msg: &'static str) -> Self {
405         Self::expected_format(msg)
406     }
407 
message_token(token: Item) -> Self408     fn message_token(token: Item) -> Self;
message_range(token: Range) -> Self409     fn message_range(token: Range) -> Self;
message_format<T>(msg: T) -> Self where T: fmt::Display410     fn message_format<T>(msg: T) -> Self
411     where
412         T: fmt::Display;
message_static_message(msg: &'static str) -> Self413     fn message_static_message(msg: &'static str) -> Self {
414         Self::message_format(msg)
415     }
message<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,416     fn message<E>(info: E) -> Self
417     where
418         E: for<'s> ErrorInfo<'s, Item, Range>,
419     {
420         match info.into_info() {
421             Info::Token(b) => Self::message_token(b),
422             Info::Range(b) => Self::message_range(b),
423             Info::Static(b) => Self::message_static_message(b),
424             Info::Format(b) => Self::message_format(b),
425         }
426     }
427 
428     #[cfg(feature = "std")]
other<E>(err: E) -> Self where E: StdError + Send + Sync + 'static,429     fn other<E>(err: E) -> Self
430     where
431         E: StdError + Send + Sync + 'static,
432     {
433         Self::message_format(err)
434     }
435 
end_of_input() -> Self436     fn end_of_input() -> Self {
437         Self::unexpected_static_message("end of input")
438     }
439 
is_unexpected_end_of_input(&self) -> bool440     fn is_unexpected_end_of_input(&self) -> bool;
441 
442     /// Converts `self` into a different `StreamError` type.
443     ///
444     /// This should aim to preserve as much information as possible into the returned `T` value but
445     /// if `Self` ignores some information passed to it using one of the constructors that
446     /// information is naturally lost.
into_other<T>(self) -> T where T: StreamError<Item, Range>447     fn into_other<T>(self) -> T
448     where
449         T: StreamError<Item, Range>;
450 }
451 
452 /// Trait which defines a combine parse error.
453 ///
454 /// A parse error is composed of zero or more `StreamError` instances which gets added to it as
455 /// errors are encountered during parsing.
456 pub trait ParseError<Item, Range, Position>: Sized + PartialEq {
457     type StreamError: StreamError<Item, Range>;
458 
459     /// Constructs an empty error.
460     ///
461     /// An empty error is expected to be cheap to create as it is frequently created and discarded.
empty(position: Position) -> Self462     fn empty(position: Position) -> Self;
463 
464     /// Creates a `ParseError` from a single `Self::StreamError`
from_error(position: Position, err: Self::StreamError) -> Self465     fn from_error(position: Position, err: Self::StreamError) -> Self {
466         let mut errors = Self::empty(position);
467         errors.add(err);
468         errors
469     }
470 
position(&self) -> Position471     fn position(&self) -> Position {
472         // TODO Remove the default implementation in a breaking release
473         unimplemented!()
474     }
475 
476     /// Sets the position of this `ParseError`
set_position(&mut self, position: Position)477     fn set_position(&mut self, position: Position);
478 
479     /// Merges two errors. If they exist at the same position the errors of `other` are
480     /// added to `self` (using the semantics of `add`). If they are not at the same
481     /// position the error furthest ahead are returned, ignoring the other `ParseError`.
merge(self, other: Self) -> Self482     fn merge(self, other: Self) -> Self {
483         other
484     }
485 
486     /// Adds a `StreamError` to `self`.
487     ///
488     /// It is up to each individual error type to define what adding an error does, some may push
489     /// it to a vector while others may only keep `self` or `err` to avoid allocation
add(&mut self, err: Self::StreamError)490     fn add(&mut self, err: Self::StreamError);
491 
add_expected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,492     fn add_expected<E>(&mut self, info: E)
493     where
494         E: for<'s> ErrorInfo<'s, Item, Range>,
495     {
496         self.add(Self::StreamError::expected(info))
497     }
498 
add_unexpected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,499     fn add_unexpected<E>(&mut self, info: E)
500     where
501         E: for<'s> ErrorInfo<'s, Item, Range>,
502     {
503         self.add(Self::StreamError::unexpected(info))
504     }
505 
add_message<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,506     fn add_message<E>(&mut self, info: E)
507     where
508         E: for<'s> ErrorInfo<'s, Item, Range>,
509     {
510         self.add(Self::StreamError::message(info))
511     }
512 
513     /// 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>)514     fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
515     where
516         F: FnOnce(&mut Tracked<Self>);
517 
518     /// Removes any expected errors currently in `self`
clear_expected(&mut self)519     fn clear_expected(&mut self) {}
520 
is_unexpected_end_of_input(&self) -> bool521     fn is_unexpected_end_of_input(&self) -> bool;
522 
523     /// Does a best-effort conversion of `self` into another `ParseError`
into_other<T>(self) -> T where T: ParseError<Item, Range, Position>524     fn into_other<T>(self) -> T
525     where
526         T: ParseError<Item, Range, Position>;
527 }
528 
529 /// Defines a conversion between two parse error types.
530 ///
531 /// Like `ParseError::into_other` but with a more general signature
532 /// (This will take the place of `into_other` on breaking release of combine)
533 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>534     fn into_other_error<T, Item2, Range2, Position2>(self) -> T
535     where
536         T: ParseError<Item2, Range2, Position2>,
537         Item2: From<Item>,
538         Range2: From<Range>,
539         Position2: From<Position>;
540 }
541 
542 /// Defines a conversion between two stream error types.
543 ///
544 /// Like `StreamError::into_other` but with a more general signature
545 /// (This will take the place of `into_other` on breaking release of combine)
546 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>547     fn into_other_error<T, Item2, Range2>(self) -> T
548     where
549         T: StreamError<Item2, Range2>,
550         Item2: From<Item>,
551         Range2: From<Range>;
552 }
553 
554 #[derive(Clone, Copy, Debug, PartialEq)]
555 pub enum UnexpectedParse {
556     Eoi,
557     Unexpected,
558 }
559 
560 impl fmt::Display for UnexpectedParse {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result561     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
562         write!(f, "{}", self.as_str())
563     }
564 }
565 
566 #[cfg(feature = "std")]
567 impl StdError for UnexpectedParse {
description(&self) -> &str568     fn description(&self) -> &str {
569         self.as_str()
570     }
571 }
572 
573 impl UnexpectedParse {
as_str(&self) -> &str574     fn as_str(&self) -> &str {
575         use self::UnexpectedParse::*;
576         match *self {
577             Unexpected => "unexpected parse",
578             Eoi => "unexpected end of input",
579         }
580     }
581 }
582 
583 impl<Item, Range> StreamError<Item, Range> for UnexpectedParse {
584     #[inline]
unexpected_token(_: Item) -> Self585     fn unexpected_token(_: Item) -> Self {
586         UnexpectedParse::Unexpected
587     }
588     #[inline]
unexpected_range(_: Range) -> Self589     fn unexpected_range(_: Range) -> Self {
590         UnexpectedParse::Unexpected
591     }
592     #[inline]
unexpected_format<T>(_: T) -> Self where T: fmt::Display,593     fn unexpected_format<T>(_: T) -> Self
594     where
595         T: fmt::Display,
596     {
597         UnexpectedParse::Unexpected
598     }
599 
600     #[inline]
expected_token(_: Item) -> Self601     fn expected_token(_: Item) -> Self {
602         UnexpectedParse::Unexpected
603     }
604     #[inline]
expected_range(_: Range) -> Self605     fn expected_range(_: Range) -> Self {
606         UnexpectedParse::Unexpected
607     }
608     #[inline]
expected_format<T>(_: T) -> Self where T: fmt::Display,609     fn expected_format<T>(_: T) -> Self
610     where
611         T: fmt::Display,
612     {
613         UnexpectedParse::Unexpected
614     }
615     #[inline]
message_format<T>(_: T) -> Self where T: fmt::Display,616     fn message_format<T>(_: T) -> Self
617     where
618         T: fmt::Display,
619     {
620         UnexpectedParse::Unexpected
621     }
622     #[inline]
message_token(_: Item) -> Self623     fn message_token(_: Item) -> Self {
624         UnexpectedParse::Unexpected
625     }
626     #[inline]
message_range(_: Range) -> Self627     fn message_range(_: Range) -> Self {
628         UnexpectedParse::Unexpected
629     }
630 
631     #[inline]
end_of_input() -> Self632     fn end_of_input() -> Self {
633         UnexpectedParse::Eoi
634     }
635 
636     #[inline]
is_unexpected_end_of_input(&self) -> bool637     fn is_unexpected_end_of_input(&self) -> bool {
638         *self == UnexpectedParse::Eoi
639     }
640 
641     #[inline]
into_other<T>(self) -> T where T: StreamError<Item, Range>,642     fn into_other<T>(self) -> T
643     where
644         T: StreamError<Item, Range>,
645     {
646         match self {
647             UnexpectedParse::Unexpected => T::unexpected_static_message("parse"),
648             UnexpectedParse::Eoi => T::end_of_input(),
649         }
650     }
651 }
652 
653 impl<Item, Range, Position> ParseError<Item, Range, Position> for UnexpectedParse
654 where
655     Position: Default,
656 {
657     type StreamError = Self;
658     #[inline]
empty(_position: Position) -> Self659     fn empty(_position: Position) -> Self {
660         UnexpectedParse::Unexpected
661     }
662 
663     #[inline]
from_error(_: Position, err: Self::StreamError) -> Self664     fn from_error(_: Position, err: Self::StreamError) -> Self {
665         err
666     }
667 
position(&self) -> Position668     fn position(&self) -> Position {
669         Position::default()
670     }
671 
672     #[inline]
set_position(&mut self, _position: Position)673     fn set_position(&mut self, _position: Position) {}
674 
675     #[inline]
add(&mut self, err: Self::StreamError)676     fn add(&mut self, err: Self::StreamError) {
677         *self = match (*self, err) {
678             (UnexpectedParse::Eoi, _) => UnexpectedParse::Eoi,
679             (_, err) => err,
680         };
681     }
682 
683     #[inline]
set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),684     fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
685     where
686         F: FnOnce(&mut Tracked<Self>),
687     {
688         f(self_);
689         self_.error = info;
690     }
691 
is_unexpected_end_of_input(&self) -> bool692     fn is_unexpected_end_of_input(&self) -> bool {
693         *self == UnexpectedParse::Eoi
694     }
695 
696     #[inline]
into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,697     fn into_other<T>(self) -> T
698     where
699         T: ParseError<Item, Range, Position>,
700     {
701         T::from_error(Position::default(), StreamError::into_other(self))
702     }
703 }
704 
705 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for UnexpectedParse
706 where
707     Position: Default,
708 {
into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,709     fn into_other_error<T, Item2, Range2, Position2>(self) -> T
710     where
711         T: ParseError<Item2, Range2, Position2>,
712         Item2: From<Item>,
713         Range2: From<Range>,
714         Position2: From<Position>,
715     {
716         T::from_error(
717             Position::default().into(),
718             StreamErrorInto::<Item, Range>::into_other_error(self),
719         )
720     }
721 }
722 
723 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>,724     fn into_other_error<T, Item2, Range2>(self) -> T
725     where
726         T: StreamError<Item2, Range2>,
727         Item2: From<Item>,
728         Range2: From<Range>,
729     {
730         StreamError::into_other(self)
731     }
732 }
733 
734 #[derive(Clone, Copy, Debug, PartialEq)]
735 pub enum StringStreamError {
736     UnexpectedParse,
737     Eoi,
738     CharacterBoundary,
739 }
740 
741 pub(crate) const CHAR_BOUNDARY_ERROR_MESSAGE: &str = "unexpected slice on character boundary";
742 
743 impl fmt::Display for StringStreamError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result744     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
745         write!(f, "{}", self.as_str())
746     }
747 }
748 
749 #[cfg(feature = "std")]
750 impl StdError for StringStreamError {
description(&self) -> &str751     fn description(&self) -> &str {
752         self.as_str()
753     }
754 }
755 
756 impl StringStreamError {
as_str(&self) -> &str757     fn as_str(&self) -> &str {
758         use self::StringStreamError::*;
759         match *self {
760             UnexpectedParse => "unexpected parse",
761             Eoi => "unexpected end of input",
762             CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE,
763         }
764     }
765 }
766 
767 impl<Item, Range> StreamError<Item, Range> for StringStreamError {
768     #[inline]
unexpected_token(_: Item) -> Self769     fn unexpected_token(_: Item) -> Self {
770         StringStreamError::UnexpectedParse
771     }
772     #[inline]
unexpected_range(_: Range) -> Self773     fn unexpected_range(_: Range) -> Self {
774         StringStreamError::UnexpectedParse
775     }
776     #[inline]
unexpected_format<T>(_msg: T) -> Self where T: fmt::Display,777     fn unexpected_format<T>(_msg: T) -> Self
778     where
779         T: fmt::Display,
780     {
781         StringStreamError::UnexpectedParse
782     }
783 
784     #[inline]
expected_token(_: Item) -> Self785     fn expected_token(_: Item) -> Self {
786         StringStreamError::UnexpectedParse
787     }
788     #[inline]
expected_range(_: Range) -> Self789     fn expected_range(_: Range) -> Self {
790         StringStreamError::UnexpectedParse
791     }
792     #[inline]
expected_format<T>(_: T) -> Self where T: fmt::Display,793     fn expected_format<T>(_: T) -> Self
794     where
795         T: fmt::Display,
796     {
797         StringStreamError::UnexpectedParse
798     }
799     #[inline]
message_format<T>(_: T) -> Self where T: fmt::Display,800     fn message_format<T>(_: T) -> Self
801     where
802         T: fmt::Display,
803     {
804         StringStreamError::UnexpectedParse
805     }
806     #[inline]
message_token(_: Item) -> Self807     fn message_token(_: Item) -> Self {
808         StringStreamError::UnexpectedParse
809     }
810     #[inline]
message_range(_: Range) -> Self811     fn message_range(_: Range) -> Self {
812         StringStreamError::UnexpectedParse
813     }
message_static_message(msg: &'static str) -> Self814     fn message_static_message(msg: &'static str) -> Self {
815         if msg == CHAR_BOUNDARY_ERROR_MESSAGE {
816             StringStreamError::CharacterBoundary
817         } else {
818             StringStreamError::UnexpectedParse
819         }
820     }
821     #[inline]
end_of_input() -> Self822     fn end_of_input() -> Self {
823         StringStreamError::Eoi
824     }
825     #[inline]
is_unexpected_end_of_input(&self) -> bool826     fn is_unexpected_end_of_input(&self) -> bool {
827         *self == StringStreamError::Eoi
828     }
829     #[inline]
into_other<T>(self) -> T where T: StreamError<Item, Range>,830     fn into_other<T>(self) -> T
831     where
832         T: StreamError<Item, Range>,
833     {
834         let msg = match self {
835             StringStreamError::CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE,
836             StringStreamError::UnexpectedParse => "parse",
837             StringStreamError::Eoi => return T::end_of_input(),
838         };
839         T::unexpected_static_message(msg)
840     }
841 }
842 impl<Item, Range, Position> ParseError<Item, Range, Position> for StringStreamError
843 where
844     Position: Default,
845 {
846     type StreamError = Self;
847     #[inline]
empty(_position: Position) -> Self848     fn empty(_position: Position) -> Self {
849         StringStreamError::UnexpectedParse
850     }
851     #[inline]
from_error(_: Position, err: Self::StreamError) -> Self852     fn from_error(_: Position, err: Self::StreamError) -> Self {
853         err
854     }
855 
position(&self) -> Position856     fn position(&self) -> Position {
857         Position::default()
858     }
859 
860     #[inline]
set_position(&mut self, _position: Position)861     fn set_position(&mut self, _position: Position) {}
862 
863     #[inline]
add(&mut self, err: Self::StreamError)864     fn add(&mut self, err: Self::StreamError) {
865         *self = match (*self, err) {
866             (StringStreamError::Eoi, _) => StringStreamError::Eoi,
867             (_, err) => err,
868         };
869     }
870 
871     #[inline]
set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),872     fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
873     where
874         F: FnOnce(&mut Tracked<Self>),
875     {
876         f(self_);
877         self_.error = info;
878     }
879 
is_unexpected_end_of_input(&self) -> bool880     fn is_unexpected_end_of_input(&self) -> bool {
881         *self == StringStreamError::Eoi
882     }
883 
884     #[inline]
into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,885     fn into_other<T>(self) -> T
886     where
887         T: ParseError<Item, Range, Position>,
888     {
889         T::from_error(Position::default(), StreamError::into_other(self))
890     }
891 }
892 
893 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for StringStreamError
894 where
895     Position: Default,
896 {
into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,897     fn into_other_error<T, Item2, Range2, Position2>(self) -> T
898     where
899         T: ParseError<Item2, Range2, Position2>,
900         Item2: From<Item>,
901         Range2: From<Range>,
902         Position2: From<Position>,
903     {
904         T::from_error(
905             Position::default().into(),
906             StreamErrorInto::<Item, Range>::into_other_error(self),
907         )
908     }
909 }
910 
911 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>,912     fn into_other_error<T, Item2, Range2>(self) -> T
913     where
914         T: StreamError<Item2, Range2>,
915         Item2: From<Item>,
916         Range2: From<Range>,
917     {
918         StreamError::into_other(self)
919     }
920 }
921 
922 /// Error wrapper which lets parsers track which parser in a sequence of sub-parsers has emitted
923 /// the error. `Tracked::from` can be used to construct this and it should otherwise be
924 /// ignored outside of combine.
925 #[derive(Clone, PartialEq, Debug, Copy)]
926 pub struct Tracked<E> {
927     /// The error returned
928     pub error: E,
929     #[doc(hidden)]
930     pub offset: ErrorOffset,
931 }
932 
933 impl<E> From<E> for Tracked<E> {
from(error: E) -> Self934     fn from(error: E) -> Self {
935         Tracked {
936             error,
937             offset: ErrorOffset(1),
938         }
939     }
940 }
941 
942 /// A `Result` type which has the committed status flattened into the result.
943 /// Conversions to and from `std::result::Result` can be done using `result.into()` or
944 /// `From::from(result)`
945 #[derive(Clone, PartialEq, Debug, Copy)]
946 pub enum ParseResult<T, E> {
947     /// The parser has succeeded and has committed to this parse. If a parser after this fails,
948     /// other parser alternatives will not be attempted (`CommitErr` will be returned)
949     CommitOk(T),
950     /// The parser has succeeded and has not committed to this parse. If a parser after this fails,
951     /// other parser alternatives will be attempted (`PeekErr` will be returned)
952     PeekOk(T),
953     /// The parser failed other parse alternatives will not be attempted.
954     CommitErr(E),
955     /// The parser failed but other parse alternatives may be attempted.
956     PeekErr(Tracked<E>),
957 }
958 
959 impl<T, E> ParseResult<T, E> {
960     #[inline]
is_ok(&self) -> bool961     pub fn is_ok(&self) -> bool {
962         match *self {
963             CommitOk(_) | PeekOk(_) => true,
964             CommitErr(_) | PeekErr(_) => false,
965         }
966     }
967 
968     #[inline]
is_err(&self) -> bool969     pub fn is_err(&self) -> bool {
970         !self.is_ok()
971     }
972 
as_ref(&self) -> ParseResult<&T, &E>973     pub fn as_ref(&self) -> ParseResult<&T, &E> {
974         match *self {
975             CommitOk(ref t) => CommitOk(t),
976             PeekOk(ref t) => PeekOk(t),
977             CommitErr(ref e) => CommitErr(e),
978             PeekErr(ref e) => PeekErr(Tracked {
979                 error: &e.error,
980                 offset: e.offset,
981             }),
982         }
983     }
984 
and_then<F, T2>(self, f: F) -> F::Output where F: FnOnce(T) -> ParseResult<T2, E>,985     pub fn and_then<F, T2>(self, f: F) -> F::Output
986     where
987         F: FnOnce(T) -> ParseResult<T2, E>,
988     {
989         match self {
990             CommitOk(t) => match f(t) {
991                 CommitOk(t2) | PeekOk(t2) => CommitOk(t2),
992                 PeekErr(e) => CommitErr(e.error),
993                 CommitErr(e) => CommitErr(e),
994             },
995             PeekOk(t) => f(t),
996             CommitErr(e) => CommitErr(e),
997             PeekErr(e) => PeekErr(e),
998         }
999     }
1000 
map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output> where F: FnOnce(E) -> E2,1001     pub fn map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output>
1002     where
1003         F: FnOnce(E) -> E2,
1004     {
1005         match self {
1006             CommitOk(t) => CommitOk(t),
1007             PeekOk(t) => PeekOk(t),
1008             CommitErr(e) => CommitErr(f(e)),
1009             PeekErr(e) => PeekErr(Tracked {
1010                 error: f(e.error),
1011                 offset: e.offset,
1012             }),
1013         }
1014     }
1015 
map<F, T2>(self, f: F) -> ParseResult<F::Output, E> where F: FnOnce(T) -> T2,1016     pub fn map<F, T2>(self, f: F) -> ParseResult<F::Output, E>
1017     where
1018         F: FnOnce(T) -> T2,
1019     {
1020         match self {
1021             CommitOk(t) => CommitOk(f(t)),
1022             PeekOk(t) => PeekOk(f(t)),
1023             CommitErr(e) => CommitErr(e),
1024             PeekErr(e) => PeekErr(e),
1025         }
1026     }
1027 }
1028 
1029 impl<O, E> ParseResult<O, E> {
into_result(self) -> StdParseResult2<O, E>1030     pub fn into_result(self) -> StdParseResult2<O, E> {
1031         self.into()
1032     }
1033 }
1034 
1035 impl<T, E> Into<Result<Commit<T>, Commit<Tracked<E>>>> for ParseResult<T, E> {
1036     #[inline]
into(self) -> Result<Commit<T>, Commit<Tracked<E>>>1037     fn into(self) -> Result<Commit<T>, Commit<Tracked<E>>> {
1038         match self {
1039             CommitOk(t) => Ok(Commit::Commit(t)),
1040             PeekOk(t) => Ok(Commit::Peek(t)),
1041             CommitErr(e) => Err(Commit::Commit(e.into())),
1042             PeekErr(e) => Err(Commit::Peek(e)),
1043         }
1044     }
1045 }
1046 
1047 impl<O, E> Into<StdParseResult2<O, E>> for ParseResult<O, E> {
1048     #[inline]
into(self) -> StdParseResult2<O, E>1049     fn into(self) -> StdParseResult2<O, E> {
1050         use self::ParseResult::*;
1051 
1052         match self {
1053             CommitOk(t) => Ok((t, Commit::Commit(()))),
1054             PeekOk(t) => Ok((t, Commit::Peek(()))),
1055             CommitErr(e) => Err(Commit::Commit(e.into())),
1056             PeekErr(e) => Err(Commit::Peek(e)),
1057         }
1058     }
1059 }
1060 
1061 impl<O, E> From<StdParseResult2<O, E>> for ParseResult<O, E> {
1062     #[inline]
from(result: StdParseResult2<O, E>) -> ParseResult<O, E>1063     fn from(result: StdParseResult2<O, E>) -> ParseResult<O, E> {
1064         use self::ParseResult::*;
1065 
1066         match result {
1067             Ok((t, Commit::Commit(()))) => CommitOk(t),
1068             Ok((t, Commit::Peek(()))) => PeekOk(t),
1069             Err(Commit::Commit(e)) => CommitErr(e.error),
1070             Err(Commit::Peek(e)) => PeekErr(e),
1071         }
1072     }
1073 }
1074 
1075 #[cfg(all(feature = "std", test))]
1076 mod tests_std {
1077 
1078     use crate::Parser;
1079 
1080     #[derive(Clone, PartialEq, Debug)]
1081     struct CloneOnly {
1082         s: String,
1083     }
1084 
1085     #[test]
parse_clone_but_not_copy()1086     fn parse_clone_but_not_copy() {
1087         // This verifies we can parse slice references with an token type that is Clone but not Copy.
1088         let input = &[
1089             CloneOnly { s: "x".to_string() },
1090             CloneOnly { s: "y".to_string() },
1091         ][..];
1092         let result = crate::parser::range::take_while(|c: CloneOnly| c.s == "x").parse(input);
1093         assert_eq!(
1094             result,
1095             Ok((
1096                 &[CloneOnly { s: "x".to_string() }][..],
1097                 &[CloneOnly { s: "y".to_string() }][..]
1098             ))
1099         );
1100     }
1101 }
1102