|  | use crate::lib::fmt; | 
|  |  | 
|  | #[cfg(feature = "std")] | 
|  | use std::error::Error as StdError; | 
|  |  | 
|  | use crate::{stream::StreamOnce, ErrorOffset}; | 
|  |  | 
|  | use self::ParseResult::*; | 
|  |  | 
|  | pub(crate) trait ResultExt<E, T> { | 
|  | fn committed(self) -> ParseResult<E, T>; | 
|  | } | 
|  |  | 
|  | impl<E, T> ResultExt<E, T> for Result<E, T> { | 
|  | fn committed(self) -> ParseResult<E, T> { | 
|  | match self { | 
|  | Ok(x) => CommitOk(x), | 
|  | Err(x) => CommitErr(x), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[macro_export] | 
|  | #[doc(hidden)] | 
|  | macro_rules! ctry { | 
|  | ($result:expr) => { | 
|  | match $result { | 
|  | $crate::error::ParseResult::CommitOk(x) => (x, $crate::error::Commit::Commit(())), | 
|  | $crate::error::ParseResult::PeekOk(x) => (x, $crate::error::Commit::Peek(())), | 
|  | $crate::error::ParseResult::CommitErr(err) => { | 
|  | return $crate::error::ParseResult::CommitErr(err.into()) | 
|  | } | 
|  | $crate::error::ParseResult::PeekErr(err) => { | 
|  | return $crate::error::ParseResult::PeekErr(err.into()) | 
|  | } | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | /// Trait for types which can be used to construct error information. | 
|  | /// | 
|  | /// To call functions expecting this trait, use the wrapper types defined in this module | 
|  | /// `Token`, `Range`, `Format` or `Static`/`&'static str` | 
|  | pub trait ErrorInfo<'s, T, R> { | 
|  | type Format: fmt::Display; | 
|  |  | 
|  | #[allow(clippy::wrong_self_convention)] | 
|  | fn into_info(&'s self) -> Info<T, R, Self::Format>; | 
|  | } | 
|  |  | 
|  | impl<'s, 'a, T, R, F> ErrorInfo<'s, T, R> for &'a F | 
|  | where | 
|  | F: ErrorInfo<'s, T, R>, | 
|  | { | 
|  | type Format = F::Format; | 
|  | fn into_info(&'s self) -> Info<T, R, Self::Format> { | 
|  | (**self).into_info() | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug)] | 
|  | pub enum Info<T, R, F = &'static str> { | 
|  | Token(T), | 
|  | Range(R), | 
|  | Static(&'static str), | 
|  | Format(F), | 
|  | } | 
|  |  | 
|  | impl<'s, T, R, F> ErrorInfo<'s, T, R> for Info<T, R, F> | 
|  | where | 
|  | T: Clone, | 
|  | R: Clone, | 
|  | F: fmt::Display + 's, | 
|  | { | 
|  | type Format = &'s F; | 
|  | fn into_info(&'s self) -> Info<T, R, <Self as ErrorInfo<'_, T, R>>::Format> { | 
|  | match self { | 
|  | Info::Token(b) => Info::Token(b.clone()), | 
|  | Info::Range(b) => Info::Range(b.clone()), | 
|  | Info::Static(b) => Info::Static(*b), | 
|  | Info::Format(b) => Info::Format(b), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<R, F> From<char> for Info<char, R, F> { | 
|  | fn from(s: char) -> Self { | 
|  | Info::Token(s) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'s, R> ErrorInfo<'s, char, R> for char { | 
|  | type Format = &'static str; | 
|  | fn into_info(&self) -> Info<char, R, Self::Format> { | 
|  | Info::Token(*self) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<T, R, F> From<&'static str> for Info<T, R, F> { | 
|  | fn from(s: &'static str) -> Self { | 
|  | Info::Static(s) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'s, T, R> ErrorInfo<'s, T, R> for &'static str { | 
|  | type Format = &'static str; | 
|  | fn into_info(&self) -> Info<T, R, Self::Format> { | 
|  | Info::Static(*self) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<R, F> From<u8> for Info<u8, R, F> { | 
|  | fn from(s: u8) -> Self { | 
|  | Info::Token(s) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<R> ErrorInfo<'_, Self, R> for u8 { | 
|  | type Format = &'static str; | 
|  | fn into_info(&self) -> Info<Self, R, Self::Format> { | 
|  | Info::Token(*self) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Newtype which constructs an `Info::Token` through `ErrorInfo` | 
|  | pub struct Token<T>(pub T); | 
|  |  | 
|  | impl<T, R> From<Token<T>> for Info<T, R, &'static str> { | 
|  | fn from(s: Token<T>) -> Self { | 
|  | Info::Token(s.0) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'s, T, R> ErrorInfo<'s, T, R> for Token<T> | 
|  | where | 
|  | T: Clone, | 
|  | { | 
|  | type Format = &'static str; | 
|  | fn into_info(&'s self) -> Info<T, R, Self::Format> { | 
|  | Info::Token(self.0.clone()) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Newtype which constructs an `Info::Range` through `ErrorInfo` | 
|  | pub struct Range<R>(pub R); | 
|  |  | 
|  | impl<T, R> From<Range<R>> for Info<T, R, &'static str> { | 
|  | fn from(s: Range<R>) -> Self { | 
|  | Info::Range(s.0) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'s, T, R> ErrorInfo<'s, T, R> for Range<R> | 
|  | where | 
|  | R: Clone, | 
|  | { | 
|  | type Format = &'static str; | 
|  | fn into_info(&'s self) -> Info<T, R, Self::Format> { | 
|  | Info::Range(self.0.clone()) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Newtype which constructs an `Info::Static` through `ErrorInfo` | 
|  | /// A plain `&'static str` can also be used, this exists for consistency. | 
|  | pub struct Static(&'static str); | 
|  |  | 
|  | impl<T, R, F> From<Static> for Info<T, R, F> | 
|  | where | 
|  | F: fmt::Display, | 
|  | { | 
|  | fn from(s: Static) -> Self { | 
|  | Info::Static(s.0) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'s, T, R> ErrorInfo<'s, T, R> for Static { | 
|  | type Format = &'static str; | 
|  | fn into_info(&'s self) -> Info<T, R, Self::Format> { | 
|  | Info::Static(self.0) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Newtype which constructs an `Info::Format` through `ErrorInfo` | 
|  | pub struct Format<F>(pub F) | 
|  | where | 
|  | F: fmt::Display; | 
|  |  | 
|  | impl<T, R, F> From<Format<F>> for Info<T, R, F> | 
|  | where | 
|  | F: fmt::Display, | 
|  | { | 
|  | fn from(s: Format<F>) -> Self { | 
|  | Info::Format(s.0) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'s, T, R, F> ErrorInfo<'s, T, R> for Format<F> | 
|  | where | 
|  | F: fmt::Display + 's, | 
|  | { | 
|  | type Format = &'s F; | 
|  | fn into_info(&'s self) -> Info<T, R, Self::Format> { | 
|  | Info::Format(&self.0) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Enum used to indicate if a parser committed any items of the stream it was given as an input. | 
|  | /// | 
|  | /// This is used by parsers such as `or` and `choice` to determine if they should try to parse | 
|  | /// with another parser as they will only be able to provide good error reporting if the preceding | 
|  | /// parser did not commit to the parse. | 
|  | #[derive(Clone, PartialEq, Debug, Copy)] | 
|  | pub enum Commit<T> { | 
|  | /// Constructor indicating that the parser has committed to this parse. If a parser after this fails, | 
|  | /// other parser alternatives will not be attempted (`CommitErr` will be returned) | 
|  | Commit(T), | 
|  | /// Constructor indicating that the parser has not committed to this parse. If a parser after this fails, | 
|  | /// other parser alternatives will be attempted (`EmptyErr` will be returned) | 
|  | Peek(T), | 
|  | } | 
|  |  | 
|  | impl<T> AsMut<T> for Commit<T> { | 
|  | fn as_mut(&mut self) -> &mut T { | 
|  | match *self { | 
|  | Commit::Peek(ref mut t) | Commit::Commit(ref mut t) => t, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<T> AsRef<T> for Commit<T> { | 
|  | fn as_ref(&self) -> &T { | 
|  | match *self { | 
|  | Commit::Peek(ref t) | Commit::Commit(ref t) => t, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<T> Commit<T> { | 
|  | /// Returns true if `self` is peek. | 
|  | pub fn is_peek(&self) -> bool { | 
|  | match *self { | 
|  | Commit::Peek(_) => true, | 
|  | Commit::Commit(_) => false, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Extracts the contained value. | 
|  | pub fn into_inner(self) -> T { | 
|  | match self { | 
|  | Commit::Peek(x) | Commit::Commit(x) => x, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Converts `self` into the `Commit` state. | 
|  | pub fn into_commit(self) -> Commit<T> { | 
|  | Commit::Commit(self.into_inner()) | 
|  | } | 
|  |  | 
|  | /// Converts `self` into the `Peek` state. | 
|  | pub fn into_peek(self) -> Commit<T> { | 
|  | Commit::Peek(self.into_inner()) | 
|  | } | 
|  |  | 
|  | /// Maps over the contained value without changing the committed state. | 
|  | pub fn map<F, U>(self, f: F) -> Commit<U> | 
|  | where | 
|  | F: FnOnce(T) -> U, | 
|  | { | 
|  | match self { | 
|  | Commit::Peek(x) => Commit::Peek(f(x)), | 
|  | Commit::Commit(x) => Commit::Commit(f(x)), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn merge(&self, current: Commit<T>) -> Commit<T> { | 
|  | match *self { | 
|  | Commit::Peek(_) => current, | 
|  | Commit::Commit(_) => current.into_commit(), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Combines the `Commit` flags from `self` and the result of `f`. | 
|  | /// | 
|  | /// ```text | 
|  | /// Peek    <> Peek    -> Peek | 
|  | /// Commit <> Peek    -> Commit | 
|  | /// Peek    <> Commit -> Commit | 
|  | /// Commit <> Commit -> Commit | 
|  | /// ``` | 
|  | /// | 
|  | /// ``` | 
|  | /// # extern crate combine as pc; | 
|  | /// # use pc::*; | 
|  | /// # fn main() { | 
|  | /// //Parses a character of string literal and handles the escaped characters \\ and \" as \ | 
|  | /// //and " respectively | 
|  | /// fn char<Input>(input: &mut Input) -> StdParseResult<char, Input> | 
|  | ///     where Input: Stream<Token = char>, | 
|  | /// { | 
|  | ///     let (c, committed) = satisfy(|c| c != '"').parse_stream(input).into_result()?; | 
|  | ///     match c { | 
|  | ///         //Since the `char` parser has already committed some of the input `combine` is used | 
|  | ///         //propagate the committed state to the next part of the parser | 
|  | ///         '\\' => committed.combine(|_| { | 
|  | ///             satisfy(|c| c == '"' || c == '\\') | 
|  | ///                 .map(|c| { | 
|  | ///                     match c { | 
|  | ///                         '"' => '"', | 
|  | ///                         '\\' => '\\', | 
|  | ///                         c => c | 
|  | ///                     } | 
|  | ///                 }) | 
|  | ///                 .parse_stream(input) | 
|  | ///                 .into_result() | 
|  | ///             }), | 
|  | ///         _ => Ok((c, committed)) | 
|  | ///     } | 
|  | /// } | 
|  | /// let result = many(parser(char)) | 
|  | ///     .easy_parse(r#"abc\"\\"#); | 
|  | /// assert_eq!(result, Ok((r#"abc"\"#.to_string(), ""))); | 
|  | /// } | 
|  | /// ``` | 
|  | pub fn combine<F, U, E>(self, f: F) -> StdParseResult2<U, E> | 
|  | where | 
|  | F: FnOnce(T) -> StdParseResult2<U, E>, | 
|  | { | 
|  | match self { | 
|  | Commit::Commit(x) => match f(x) { | 
|  | Ok((v, Commit::Peek(()))) => Ok((v, Commit::Commit(()))), | 
|  | Err(Commit::Peek(err)) => Err(Commit::Commit(err)), | 
|  | y => y, | 
|  | }, | 
|  | Commit::Peek(x) => f(x), | 
|  | } | 
|  | } | 
|  | pub fn combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E> | 
|  | where | 
|  | F: FnOnce(T) -> ParseResult<U, E>, | 
|  | { | 
|  | use self::ParseResult::*; | 
|  |  | 
|  | match self { | 
|  | Commit::Commit(x) => match f(x) { | 
|  | PeekOk(v) => CommitOk(v), | 
|  | PeekErr(err) => CommitErr(err.error), | 
|  | y => y, | 
|  | }, | 
|  | Commit::Peek(x) => f(x), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// A type alias over the specific `Result` type used by parsers to indicate whether they were | 
|  | /// successful or not. | 
|  | /// `O` is the type that is output on success. | 
|  | /// `Input` is the specific stream type used in the parser. | 
|  | pub type StdParseResult<O, Input> = | 
|  | Result<(O, Commit<()>), Commit<Tracked<<Input as StreamOnce>::Error>>>; | 
|  | pub type StdParseResult2<O, E> = Result<(O, Commit<()>), Commit<Tracked<E>>>; | 
|  |  | 
|  | /// `StreamError` represents a single error returned from a `Stream` or a `Parser`. | 
|  | /// | 
|  | /// Usually multiple instances of `StreamError` is composed into a `ParseError` to build the final | 
|  | /// error value. | 
|  | pub trait StreamError<Item, Range>: Sized { | 
|  | fn unexpected_token(token: Item) -> Self; | 
|  | fn unexpected_range(token: Range) -> Self; | 
|  | fn unexpected_format<T>(msg: T) -> Self | 
|  | where | 
|  | T: fmt::Display; | 
|  | fn unexpected<E>(info: E) -> Self | 
|  | where | 
|  | E: for<'s> ErrorInfo<'s, Item, Range>, | 
|  | { | 
|  | match info.into_info() { | 
|  | Info::Token(b) => Self::unexpected_token(b), | 
|  | Info::Range(b) => Self::unexpected_range(b), | 
|  | Info::Static(b) => Self::unexpected_static_message(b), | 
|  | Info::Format(b) => Self::unexpected_format(b), | 
|  | } | 
|  | } | 
|  | fn unexpected_static_message(msg: &'static str) -> Self { | 
|  | Self::unexpected_format(msg) | 
|  | } | 
|  |  | 
|  | fn expected_token(token: Item) -> Self; | 
|  | fn expected_range(token: Range) -> Self; | 
|  | fn expected_format<T>(msg: T) -> Self | 
|  | where | 
|  | T: fmt::Display; | 
|  | fn expected<E>(info: E) -> Self | 
|  | where | 
|  | E: for<'s> ErrorInfo<'s, Item, Range>, | 
|  | { | 
|  | match info.into_info() { | 
|  | Info::Token(b) => Self::expected_token(b), | 
|  | Info::Range(b) => Self::expected_range(b), | 
|  | Info::Static(b) => Self::expected_static_message(b), | 
|  | Info::Format(b) => Self::expected_format(b), | 
|  | } | 
|  | } | 
|  | fn expected_static_message(msg: &'static str) -> Self { | 
|  | Self::expected_format(msg) | 
|  | } | 
|  |  | 
|  | fn message_token(token: Item) -> Self; | 
|  | fn message_range(token: Range) -> Self; | 
|  | fn message_format<T>(msg: T) -> Self | 
|  | where | 
|  | T: fmt::Display; | 
|  | fn message_static_message(msg: &'static str) -> Self { | 
|  | Self::message_format(msg) | 
|  | } | 
|  | fn message<E>(info: E) -> Self | 
|  | where | 
|  | E: for<'s> ErrorInfo<'s, Item, Range>, | 
|  | { | 
|  | match info.into_info() { | 
|  | Info::Token(b) => Self::message_token(b), | 
|  | Info::Range(b) => Self::message_range(b), | 
|  | Info::Static(b) => Self::message_static_message(b), | 
|  | Info::Format(b) => Self::message_format(b), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(feature = "std")] | 
|  | fn other<E>(err: E) -> Self | 
|  | where | 
|  | E: StdError + Send + Sync + 'static, | 
|  | { | 
|  | Self::message_format(err) | 
|  | } | 
|  |  | 
|  | fn end_of_input() -> Self { | 
|  | Self::unexpected_static_message("end of input") | 
|  | } | 
|  |  | 
|  | fn is_unexpected_end_of_input(&self) -> bool; | 
|  |  | 
|  | /// Converts `self` into a different `StreamError` type. | 
|  | /// | 
|  | /// This should aim to preserve as much information as possible into the returned `T` value but | 
|  | /// if `Self` ignores some information passed to it using one of the constructors that | 
|  | /// information is naturally lost. | 
|  | fn into_other<T>(self) -> T | 
|  | where | 
|  | T: StreamError<Item, Range>; | 
|  | } | 
|  |  | 
|  | /// Trait which defines a combine parse error. | 
|  | /// | 
|  | /// A parse error is composed of zero or more `StreamError` instances which gets added to it as | 
|  | /// errors are encountered during parsing. | 
|  | pub trait ParseError<Item, Range, Position>: Sized + PartialEq { | 
|  | type StreamError: StreamError<Item, Range>; | 
|  |  | 
|  | /// Constructs an empty error. | 
|  | /// | 
|  | /// An empty error is expected to be cheap to create as it is frequently created and discarded. | 
|  | fn empty(position: Position) -> Self; | 
|  |  | 
|  | /// Creates a `ParseError` from a single `Self::StreamError` | 
|  | fn from_error(position: Position, err: Self::StreamError) -> Self { | 
|  | let mut errors = Self::empty(position); | 
|  | errors.add(err); | 
|  | errors | 
|  | } | 
|  |  | 
|  | fn position(&self) -> Position { | 
|  | // TODO Remove the default implementation in a breaking release | 
|  | unimplemented!() | 
|  | } | 
|  |  | 
|  | /// Sets the position of this `ParseError` | 
|  | fn set_position(&mut self, position: Position); | 
|  |  | 
|  | /// Merges two errors. If they exist at the same position the errors of `other` are | 
|  | /// added to `self` (using the semantics of `add`). If they are not at the same | 
|  | /// position the error furthest ahead are returned, ignoring the other `ParseError`. | 
|  | fn merge(self, other: Self) -> Self { | 
|  | other | 
|  | } | 
|  |  | 
|  | /// Adds a `StreamError` to `self`. | 
|  | /// | 
|  | /// It is up to each individual error type to define what adding an error does, some may push | 
|  | /// it to a vector while others may only keep `self` or `err` to avoid allocation | 
|  | fn add(&mut self, err: Self::StreamError); | 
|  |  | 
|  | fn add_expected<E>(&mut self, info: E) | 
|  | where | 
|  | E: for<'s> ErrorInfo<'s, Item, Range>, | 
|  | { | 
|  | self.add(Self::StreamError::expected(info)) | 
|  | } | 
|  |  | 
|  | fn add_unexpected<E>(&mut self, info: E) | 
|  | where | 
|  | E: for<'s> ErrorInfo<'s, Item, Range>, | 
|  | { | 
|  | self.add(Self::StreamError::unexpected(info)) | 
|  | } | 
|  |  | 
|  | fn add_message<E>(&mut self, info: E) | 
|  | where | 
|  | E: for<'s> ErrorInfo<'s, Item, Range>, | 
|  | { | 
|  | self.add(Self::StreamError::message(info)) | 
|  | } | 
|  |  | 
|  | /// Sets `info` as the *only* `Expected` error of `self` | 
|  | fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) | 
|  | where | 
|  | F: FnOnce(&mut Tracked<Self>); | 
|  |  | 
|  | /// Removes any expected errors currently in `self` | 
|  | fn clear_expected(&mut self) {} | 
|  |  | 
|  | fn is_unexpected_end_of_input(&self) -> bool; | 
|  |  | 
|  | /// Does a best-effort conversion of `self` into another `ParseError` | 
|  | fn into_other<T>(self) -> T | 
|  | where | 
|  | T: ParseError<Item, Range, Position>; | 
|  | } | 
|  |  | 
|  | /// Defines a conversion between two parse error types. | 
|  | /// | 
|  | /// Like `ParseError::into_other` but with a more general signature | 
|  | /// (This will take the place of `into_other` on breaking release of combine) | 
|  | pub trait ParseErrorInto<Item, Range, Position>: Sized { | 
|  | fn into_other_error<T, Item2, Range2, Position2>(self) -> T | 
|  | where | 
|  | T: ParseError<Item2, Range2, Position2>, | 
|  | Item2: From<Item>, | 
|  | Range2: From<Range>, | 
|  | Position2: From<Position>; | 
|  | } | 
|  |  | 
|  | /// Defines a conversion between two stream error types. | 
|  | /// | 
|  | /// Like `StreamError::into_other` but with a more general signature | 
|  | /// (This will take the place of `into_other` on breaking release of combine) | 
|  | pub trait StreamErrorInto<Item, Range>: Sized { | 
|  | fn into_other_error<T, Item2, Range2>(self) -> T | 
|  | where | 
|  | T: StreamError<Item2, Range2>, | 
|  | Item2: From<Item>, | 
|  | Range2: From<Range>; | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq)] | 
|  | pub enum UnexpectedParse { | 
|  | Eoi, | 
|  | Unexpected, | 
|  | } | 
|  |  | 
|  | impl fmt::Display for UnexpectedParse { | 
|  | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | write!(f, "{}", self.as_str()) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(feature = "std")] | 
|  | impl StdError for UnexpectedParse { | 
|  | fn description(&self) -> &str { | 
|  | self.as_str() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl UnexpectedParse { | 
|  | fn as_str(&self) -> &str { | 
|  | use self::UnexpectedParse::*; | 
|  | match *self { | 
|  | Unexpected => "unexpected parse", | 
|  | Eoi => "unexpected end of input", | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<Item, Range> StreamError<Item, Range> for UnexpectedParse { | 
|  | #[inline] | 
|  | fn unexpected_token(_: Item) -> Self { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  | #[inline] | 
|  | fn unexpected_range(_: Range) -> Self { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  | #[inline] | 
|  | fn unexpected_format<T>(_: T) -> Self | 
|  | where | 
|  | T: fmt::Display, | 
|  | { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn expected_token(_: Item) -> Self { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  | #[inline] | 
|  | fn expected_range(_: Range) -> Self { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  | #[inline] | 
|  | fn expected_format<T>(_: T) -> Self | 
|  | where | 
|  | T: fmt::Display, | 
|  | { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  | #[inline] | 
|  | fn message_format<T>(_: T) -> Self | 
|  | where | 
|  | T: fmt::Display, | 
|  | { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  | #[inline] | 
|  | fn message_token(_: Item) -> Self { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  | #[inline] | 
|  | fn message_range(_: Range) -> Self { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn end_of_input() -> Self { | 
|  | UnexpectedParse::Eoi | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn is_unexpected_end_of_input(&self) -> bool { | 
|  | *self == UnexpectedParse::Eoi | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn into_other<T>(self) -> T | 
|  | where | 
|  | T: StreamError<Item, Range>, | 
|  | { | 
|  | match self { | 
|  | UnexpectedParse::Unexpected => T::unexpected_static_message("parse"), | 
|  | UnexpectedParse::Eoi => T::end_of_input(), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<Item, Range, Position> ParseError<Item, Range, Position> for UnexpectedParse | 
|  | where | 
|  | Position: Default, | 
|  | { | 
|  | type StreamError = Self; | 
|  | #[inline] | 
|  | fn empty(_position: Position) -> Self { | 
|  | UnexpectedParse::Unexpected | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn from_error(_: Position, err: Self::StreamError) -> Self { | 
|  | err | 
|  | } | 
|  |  | 
|  | fn position(&self) -> Position { | 
|  | Position::default() | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn set_position(&mut self, _position: Position) {} | 
|  |  | 
|  | #[inline] | 
|  | fn add(&mut self, err: Self::StreamError) { | 
|  | *self = match (*self, err) { | 
|  | (UnexpectedParse::Eoi, _) => UnexpectedParse::Eoi, | 
|  | (_, err) => err, | 
|  | }; | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) | 
|  | where | 
|  | F: FnOnce(&mut Tracked<Self>), | 
|  | { | 
|  | f(self_); | 
|  | self_.error = info; | 
|  | } | 
|  |  | 
|  | fn is_unexpected_end_of_input(&self) -> bool { | 
|  | *self == UnexpectedParse::Eoi | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn into_other<T>(self) -> T | 
|  | where | 
|  | T: ParseError<Item, Range, Position>, | 
|  | { | 
|  | T::from_error(Position::default(), StreamError::into_other(self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for UnexpectedParse | 
|  | where | 
|  | Position: Default, | 
|  | { | 
|  | fn into_other_error<T, Item2, Range2, Position2>(self) -> T | 
|  | where | 
|  | T: ParseError<Item2, Range2, Position2>, | 
|  | Item2: From<Item>, | 
|  | Range2: From<Range>, | 
|  | Position2: From<Position>, | 
|  | { | 
|  | T::from_error( | 
|  | Position::default().into(), | 
|  | StreamErrorInto::<Item, Range>::into_other_error(self), | 
|  | ) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<Item, Range> StreamErrorInto<Item, Range> for UnexpectedParse { | 
|  | fn into_other_error<T, Item2, Range2>(self) -> T | 
|  | where | 
|  | T: StreamError<Item2, Range2>, | 
|  | Item2: From<Item>, | 
|  | Range2: From<Range>, | 
|  | { | 
|  | StreamError::into_other(self) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq)] | 
|  | pub enum StringStreamError { | 
|  | UnexpectedParse, | 
|  | Eoi, | 
|  | CharacterBoundary, | 
|  | } | 
|  |  | 
|  | pub(crate) const CHAR_BOUNDARY_ERROR_MESSAGE: &str = "unexpected slice on character boundary"; | 
|  |  | 
|  | impl fmt::Display for StringStreamError { | 
|  | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | write!(f, "{}", self.as_str()) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(feature = "std")] | 
|  | impl StdError for StringStreamError { | 
|  | fn description(&self) -> &str { | 
|  | self.as_str() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl StringStreamError { | 
|  | fn as_str(&self) -> &str { | 
|  | use self::StringStreamError::*; | 
|  | match *self { | 
|  | UnexpectedParse => "unexpected parse", | 
|  | Eoi => "unexpected end of input", | 
|  | CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<Item, Range> StreamError<Item, Range> for StringStreamError { | 
|  | #[inline] | 
|  | fn unexpected_token(_: Item) -> Self { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn unexpected_range(_: Range) -> Self { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn unexpected_format<T>(_msg: T) -> Self | 
|  | where | 
|  | T: fmt::Display, | 
|  | { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn expected_token(_: Item) -> Self { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn expected_range(_: Range) -> Self { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn expected_format<T>(_: T) -> Self | 
|  | where | 
|  | T: fmt::Display, | 
|  | { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn message_format<T>(_: T) -> Self | 
|  | where | 
|  | T: fmt::Display, | 
|  | { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn message_token(_: Item) -> Self { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn message_range(_: Range) -> Self { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | fn message_static_message(msg: &'static str) -> Self { | 
|  | if msg == CHAR_BOUNDARY_ERROR_MESSAGE { | 
|  | StringStreamError::CharacterBoundary | 
|  | } else { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | } | 
|  | #[inline] | 
|  | fn end_of_input() -> Self { | 
|  | StringStreamError::Eoi | 
|  | } | 
|  | #[inline] | 
|  | fn is_unexpected_end_of_input(&self) -> bool { | 
|  | *self == StringStreamError::Eoi | 
|  | } | 
|  | #[inline] | 
|  | fn into_other<T>(self) -> T | 
|  | where | 
|  | T: StreamError<Item, Range>, | 
|  | { | 
|  | let msg = match self { | 
|  | StringStreamError::CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE, | 
|  | StringStreamError::UnexpectedParse => "parse", | 
|  | StringStreamError::Eoi => return T::end_of_input(), | 
|  | }; | 
|  | T::unexpected_static_message(msg) | 
|  | } | 
|  | } | 
|  | impl<Item, Range, Position> ParseError<Item, Range, Position> for StringStreamError | 
|  | where | 
|  | Position: Default, | 
|  | { | 
|  | type StreamError = Self; | 
|  | #[inline] | 
|  | fn empty(_position: Position) -> Self { | 
|  | StringStreamError::UnexpectedParse | 
|  | } | 
|  | #[inline] | 
|  | fn from_error(_: Position, err: Self::StreamError) -> Self { | 
|  | err | 
|  | } | 
|  |  | 
|  | fn position(&self) -> Position { | 
|  | Position::default() | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn set_position(&mut self, _position: Position) {} | 
|  |  | 
|  | #[inline] | 
|  | fn add(&mut self, err: Self::StreamError) { | 
|  | *self = match (*self, err) { | 
|  | (StringStreamError::Eoi, _) => StringStreamError::Eoi, | 
|  | (_, err) => err, | 
|  | }; | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) | 
|  | where | 
|  | F: FnOnce(&mut Tracked<Self>), | 
|  | { | 
|  | f(self_); | 
|  | self_.error = info; | 
|  | } | 
|  |  | 
|  | fn is_unexpected_end_of_input(&self) -> bool { | 
|  | *self == StringStreamError::Eoi | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn into_other<T>(self) -> T | 
|  | where | 
|  | T: ParseError<Item, Range, Position>, | 
|  | { | 
|  | T::from_error(Position::default(), StreamError::into_other(self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for StringStreamError | 
|  | where | 
|  | Position: Default, | 
|  | { | 
|  | fn into_other_error<T, Item2, Range2, Position2>(self) -> T | 
|  | where | 
|  | T: ParseError<Item2, Range2, Position2>, | 
|  | Item2: From<Item>, | 
|  | Range2: From<Range>, | 
|  | Position2: From<Position>, | 
|  | { | 
|  | T::from_error( | 
|  | Position::default().into(), | 
|  | StreamErrorInto::<Item, Range>::into_other_error(self), | 
|  | ) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<Item, Range> StreamErrorInto<Item, Range> for StringStreamError { | 
|  | fn into_other_error<T, Item2, Range2>(self) -> T | 
|  | where | 
|  | T: StreamError<Item2, Range2>, | 
|  | Item2: From<Item>, | 
|  | Range2: From<Range>, | 
|  | { | 
|  | StreamError::into_other(self) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Error wrapper which lets parsers track which parser in a sequence of sub-parsers has emitted | 
|  | /// the error. `Tracked::from` can be used to construct this and it should otherwise be | 
|  | /// ignored outside of combine. | 
|  | #[derive(Clone, PartialEq, Debug, Copy)] | 
|  | pub struct Tracked<E> { | 
|  | /// The error returned | 
|  | pub error: E, | 
|  | #[doc(hidden)] | 
|  | pub offset: ErrorOffset, | 
|  | } | 
|  |  | 
|  | impl<E> From<E> for Tracked<E> { | 
|  | fn from(error: E) -> Self { | 
|  | Tracked { | 
|  | error, | 
|  | offset: ErrorOffset(1), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// A `Result` type which has the committed status flattened into the result. | 
|  | /// Conversions to and from `std::result::Result` can be done using `result.into()` or | 
|  | /// `From::from(result)` | 
|  | #[derive(Clone, PartialEq, Debug, Copy)] | 
|  | pub enum ParseResult<T, E> { | 
|  | /// The parser has succeeded and has committed to this parse. If a parser after this fails, | 
|  | /// other parser alternatives will not be attempted (`CommitErr` will be returned) | 
|  | CommitOk(T), | 
|  | /// The parser has succeeded and has not committed to this parse. If a parser after this fails, | 
|  | /// other parser alternatives will be attempted (`PeekErr` will be returned) | 
|  | PeekOk(T), | 
|  | /// The parser failed other parse alternatives will not be attempted. | 
|  | CommitErr(E), | 
|  | /// The parser failed but other parse alternatives may be attempted. | 
|  | PeekErr(Tracked<E>), | 
|  | } | 
|  |  | 
|  | impl<T, E> ParseResult<T, E> { | 
|  | #[inline] | 
|  | pub fn is_ok(&self) -> bool { | 
|  | match *self { | 
|  | CommitOk(_) | PeekOk(_) => true, | 
|  | CommitErr(_) | PeekErr(_) => false, | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_err(&self) -> bool { | 
|  | !self.is_ok() | 
|  | } | 
|  |  | 
|  | pub fn as_ref(&self) -> ParseResult<&T, &E> { | 
|  | match *self { | 
|  | CommitOk(ref t) => CommitOk(t), | 
|  | PeekOk(ref t) => PeekOk(t), | 
|  | CommitErr(ref e) => CommitErr(e), | 
|  | PeekErr(ref e) => PeekErr(Tracked { | 
|  | error: &e.error, | 
|  | offset: e.offset, | 
|  | }), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn and_then<F, T2>(self, f: F) -> F::Output | 
|  | where | 
|  | F: FnOnce(T) -> ParseResult<T2, E>, | 
|  | { | 
|  | match self { | 
|  | CommitOk(t) => match f(t) { | 
|  | CommitOk(t2) | PeekOk(t2) => CommitOk(t2), | 
|  | PeekErr(e) => CommitErr(e.error), | 
|  | CommitErr(e) => CommitErr(e), | 
|  | }, | 
|  | PeekOk(t) => f(t), | 
|  | CommitErr(e) => CommitErr(e), | 
|  | PeekErr(e) => PeekErr(e), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output> | 
|  | where | 
|  | F: FnOnce(E) -> E2, | 
|  | { | 
|  | match self { | 
|  | CommitOk(t) => CommitOk(t), | 
|  | PeekOk(t) => PeekOk(t), | 
|  | CommitErr(e) => CommitErr(f(e)), | 
|  | PeekErr(e) => PeekErr(Tracked { | 
|  | error: f(e.error), | 
|  | offset: e.offset, | 
|  | }), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn map<F, T2>(self, f: F) -> ParseResult<F::Output, E> | 
|  | where | 
|  | F: FnOnce(T) -> T2, | 
|  | { | 
|  | match self { | 
|  | CommitOk(t) => CommitOk(f(t)), | 
|  | PeekOk(t) => PeekOk(f(t)), | 
|  | CommitErr(e) => CommitErr(e), | 
|  | PeekErr(e) => PeekErr(e), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<O, E> ParseResult<O, E> { | 
|  | pub fn into_result(self) -> StdParseResult2<O, E> { | 
|  | self.into() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<T, E> Into<Result<Commit<T>, Commit<Tracked<E>>>> for ParseResult<T, E> { | 
|  | #[inline] | 
|  | fn into(self) -> Result<Commit<T>, Commit<Tracked<E>>> { | 
|  | match self { | 
|  | CommitOk(t) => Ok(Commit::Commit(t)), | 
|  | PeekOk(t) => Ok(Commit::Peek(t)), | 
|  | CommitErr(e) => Err(Commit::Commit(e.into())), | 
|  | PeekErr(e) => Err(Commit::Peek(e)), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<O, E> Into<StdParseResult2<O, E>> for ParseResult<O, E> { | 
|  | #[inline] | 
|  | fn into(self) -> StdParseResult2<O, E> { | 
|  | use self::ParseResult::*; | 
|  |  | 
|  | match self { | 
|  | CommitOk(t) => Ok((t, Commit::Commit(()))), | 
|  | PeekOk(t) => Ok((t, Commit::Peek(()))), | 
|  | CommitErr(e) => Err(Commit::Commit(e.into())), | 
|  | PeekErr(e) => Err(Commit::Peek(e)), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<O, E> From<StdParseResult2<O, E>> for ParseResult<O, E> { | 
|  | #[inline] | 
|  | fn from(result: StdParseResult2<O, E>) -> ParseResult<O, E> { | 
|  | use self::ParseResult::*; | 
|  |  | 
|  | match result { | 
|  | Ok((t, Commit::Commit(()))) => CommitOk(t), | 
|  | Ok((t, Commit::Peek(()))) => PeekOk(t), | 
|  | Err(Commit::Commit(e)) => CommitErr(e.error), | 
|  | Err(Commit::Peek(e)) => PeekErr(e), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(all(feature = "std", test))] | 
|  | mod tests_std { | 
|  |  | 
|  | use crate::Parser; | 
|  |  | 
|  | #[derive(Clone, PartialEq, Debug)] | 
|  | struct CloneOnly { | 
|  | s: String, | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn parse_clone_but_not_copy() { | 
|  | // This verifies we can parse slice references with an token type that is Clone but not Copy. | 
|  | let input = &[ | 
|  | CloneOnly { s: "x".to_string() }, | 
|  | CloneOnly { s: "y".to_string() }, | 
|  | ][..]; | 
|  | let result = crate::parser::range::take_while(|c: CloneOnly| c.s == "x").parse(input); | 
|  | assert_eq!( | 
|  | result, | 
|  | Ok(( | 
|  | &[CloneOnly { s: "x".to_string() }][..], | 
|  | &[CloneOnly { s: "y".to_string() }][..] | 
|  | )) | 
|  | ); | 
|  | } | 
|  | } |