diff options
Diffstat (limited to 'vendor/winnow/src/combinator')
-rw-r--r-- | vendor/winnow/src/combinator/branch.rs | 297 | ||||
-rw-r--r-- | vendor/winnow/src/combinator/core.rs | 491 | ||||
-rw-r--r-- | vendor/winnow/src/combinator/mod.rs | 172 | ||||
-rw-r--r-- | vendor/winnow/src/combinator/multi.rs | 945 | ||||
-rw-r--r-- | vendor/winnow/src/combinator/parser.rs | 863 | ||||
-rw-r--r-- | vendor/winnow/src/combinator/sequence.rs | 164 | ||||
-rw-r--r-- | vendor/winnow/src/combinator/tests.rs | 1292 |
7 files changed, 4224 insertions, 0 deletions
diff --git a/vendor/winnow/src/combinator/branch.rs b/vendor/winnow/src/combinator/branch.rs new file mode 100644 index 0000000..b909ff1 --- /dev/null +++ b/vendor/winnow/src/combinator/branch.rs @@ -0,0 +1,297 @@ +use crate::error::{ErrMode, ErrorKind, ParserError}; +use crate::stream::Stream; +use crate::trace::trace; +use crate::*; + +#[doc(inline)] +pub use crate::dispatch; + +/// Helper trait for the [alt()] combinator. +/// +/// This trait is implemented for tuples of up to 21 elements +pub trait Alt<I, O, E> { + /// Tests each parser in the tuple and returns the result of the first one that succeeds + fn choice(&mut self, input: &mut I) -> PResult<O, E>; +} + +/// Pick the first successful parser +/// +/// For tight control over the error, add a final case using [`fail`][crate::combinator::fail]. +/// Alternatively, with a [custom error type][crate::_topic::error], it is possible to track all +/// errors or return the error of the parser that went the farthest in the input data. +/// +/// When the alternative cases have unique prefixes, [`dispatch`] can offer better performance. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::InputError,error::ErrorKind, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::ascii::{alpha1, digit1}; +/// use winnow::combinator::alt; +/// # fn main() { +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt((alpha1, digit1)).parse_peek(input) +/// }; +/// +/// // the first parser, alpha1, recognizes the input +/// assert_eq!(parser("abc"), Ok(("", "abc"))); +/// +/// // the first parser returns an error, so alt tries the second one +/// assert_eq!(parser("123456"), Ok(("", "123456"))); +/// +/// // both parsers failed, and with the default error type, alt will return the last error +/// assert_eq!(parser(" "), Err(ErrMode::Backtrack(InputError::new(" ", ErrorKind::Slice)))); +/// # } +/// ``` +#[doc(alias = "choice")] +pub fn alt<I: Stream, O, E: ParserError<I>, List: Alt<I, O, E>>( + mut l: List, +) -> impl Parser<I, O, E> { + trace("alt", move |i: &mut I| l.choice(i)) +} + +/// Helper trait for the [permutation()] combinator. +/// +/// This trait is implemented for tuples of up to 21 elements +pub trait Permutation<I, O, E> { + /// Tries to apply all parsers in the tuple in various orders until all of them succeed + fn permutation(&mut self, input: &mut I) -> PResult<O, E>; +} + +/// Applies a list of parsers in any order. +/// +/// Permutation will succeed if all of the child parsers succeeded. +/// It takes as argument a tuple of parsers, and returns a +/// tuple of the parser results. +/// +/// ```rust +/// # use winnow::{error::ErrMode,error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::ascii::{alpha1, digit1}; +/// use winnow::combinator::permutation; +/// # fn main() { +/// fn parser(input: &str) -> IResult<&str, (&str, &str)> { +/// permutation((alpha1, digit1)).parse_peek(input) +/// } +/// +/// // permutation recognizes alphabetic characters then digit +/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123")))); +/// +/// // but also in inverse order +/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123")))); +/// +/// // it will fail if one of the parsers failed +/// assert_eq!(parser("abc;"), Err(ErrMode::Backtrack(InputError::new(";", ErrorKind::Slice)))); +/// # } +/// ``` +/// +/// The parsers are applied greedily: if there are multiple unapplied parsers +/// that could parse the next slice of input, the first one is used. +/// ```rust +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}}; +/// # use winnow::prelude::*; +/// use winnow::combinator::permutation; +/// use winnow::token::any; +/// +/// fn parser(input: &str) -> IResult<&str, (char, char)> { +/// permutation((any, 'a')).parse_peek(input) +/// } +/// +/// // any parses 'b', then char('a') parses 'a' +/// assert_eq!(parser("ba"), Ok(("", ('b', 'a')))); +/// +/// // any parses 'a', then char('a') fails on 'b', +/// // even though char('a') followed by any would succeed +/// assert_eq!(parser("ab"), Err(ErrMode::Backtrack(InputError::new("b", ErrorKind::Verify)))); +/// ``` +/// +pub fn permutation<I: Stream, O, E: ParserError<I>, List: Permutation<I, O, E>>( + mut l: List, +) -> impl Parser<I, O, E> { + trace("permutation", move |i: &mut I| l.permutation(i)) +} + +impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] { + fn choice(&mut self, input: &mut I) -> PResult<O, E> { + let mut error: Option<E> = None; + + let start = input.checkpoint(); + for branch in self { + input.reset(start.clone()); + match branch.parse_next(input) { + Err(ErrMode::Backtrack(e)) => { + error = match error { + Some(error) => Some(error.or(e)), + None => Some(e), + }; + } + res => return res, + } + } + + match error { + Some(e) => Err(ErrMode::Backtrack(e.append(input, ErrorKind::Alt))), + None => Err(ErrMode::assert(input, "`alt` needs at least one parser")), + } + } +} + +macro_rules! alt_trait( + ($first:ident $second:ident $($id: ident)+) => ( + alt_trait!(__impl $first $second; $($id)+); + ); + (__impl $($current:ident)*; $head:ident $($id: ident)+) => ( + alt_trait_impl!($($current)*); + + alt_trait!(__impl $($current)* $head; $($id)+); + ); + (__impl $($current:ident)*; $head:ident) => ( + alt_trait_impl!($($current)*); + alt_trait_impl!($($current)* $head); + ); +); + +macro_rules! alt_trait_impl( + ($($id:ident)+) => ( + impl< + I: Stream, Output, Error: ParserError<I>, + $($id: Parser<I, Output, Error>),+ + > Alt<I, Output, Error> for ( $($id),+ ) { + + fn choice(&mut self, input: &mut I) -> PResult<Output, Error> { + let start = input.checkpoint(); + match self.0.parse_next(input) { + Err(ErrMode::Backtrack(e)) => alt_trait_inner!(1, self, input, start, e, $($id)+), + res => res, + } + } + } + ); +); + +macro_rules! alt_trait_inner( + ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident $($id:ident)+) => ({ + $input.reset($start.clone()); + match $self.$it.parse_next($input) { + Err(ErrMode::Backtrack(e)) => { + let err = $err.or(e); + succ!($it, alt_trait_inner!($self, $input, $start, err, $($id)+)) + } + res => res, + } + }); + ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident) => ({ + Err(ErrMode::Backtrack($err.append($input, ErrorKind::Alt))) + }); +); + +alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10 Alt11 Alt12 Alt13 Alt14 Alt15 Alt16 Alt17 Alt18 Alt19 Alt20 Alt21 Alt22); + +// Manually implement Alt for (A,), the 1-tuple type +impl<I, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) { + fn choice(&mut self, input: &mut I) -> PResult<O, E> { + self.0.parse_next(input) + } +} + +macro_rules! permutation_trait( + ( + $name1:ident $ty1:ident $item1:ident + $name2:ident $ty2:ident $item2:ident + $($name3:ident $ty3:ident $item3:ident)* + ) => ( + permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*); + ); + ( + __impl $($name:ident $ty:ident $item:ident),+; + $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)* + ) => ( + permutation_trait_impl!($($name $ty $item),+); + permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*); + ); + (__impl $($name:ident $ty:ident $item:ident),+;) => ( + permutation_trait_impl!($($name $ty $item),+); + ); +); + +macro_rules! permutation_trait_impl( + ($($name:ident $ty:ident $item:ident),+) => ( + impl< + I: Stream, $($ty),+ , Error: ParserError<I>, + $($name: Parser<I, $ty, Error>),+ + > Permutation<I, ( $($ty),+ ), Error> for ( $($name),+ ) { + + fn permutation(&mut self, input: &mut I) -> PResult<( $($ty),+ ), Error> { + let mut res = ($(Option::<$ty>::None),+); + + loop { + let mut err: Option<Error> = None; + let start = input.checkpoint(); + permutation_trait_inner!(0, self, input, start, res, err, $($name)+); + + // If we reach here, every iterator has either been applied before, + // or errored on the remaining input + if let Some(err) = err { + // There are remaining parsers, and all errored on the remaining input + input.reset(start.clone()); + return Err(ErrMode::Backtrack(err.append(input, ErrorKind::Alt))); + } + + // All parsers were applied + match res { + ($(Some($item)),+) => return Ok(($($item),+)), + _ => unreachable!(), + } + } + } + } + ); +); + +macro_rules! permutation_trait_inner( + ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => ( + if $res.$it.is_none() { + $input.reset($start.clone()); + match $self.$it.parse_next($input) { + Ok(o) => { + $res.$it = Some(o); + continue; + } + Err(ErrMode::Backtrack(e)) => { + $err = Some(match $err { + Some(err) => err.or(e), + None => e, + }); + } + Err(e) => return Err(e), + }; + } + succ!($it, permutation_trait_inner!($self, $input, $start, $res, $err, $($id)*)); + ); + ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr,) => (); +); + +permutation_trait!( + P1 O1 o1 + P2 O2 o2 + P3 O3 o3 + P4 O4 o4 + P5 O5 o5 + P6 O6 o6 + P7 O7 o7 + P8 O8 o8 + P9 O9 o9 + P10 O10 o10 + P11 O11 o11 + P12 O12 o12 + P13 O13 o13 + P14 O14 o14 + P15 O15 o15 + P16 O16 o16 + P17 O17 o17 + P18 O18 o18 + P19 O19 o19 + P20 O20 o20 + P21 O21 o21 +); diff --git a/vendor/winnow/src/combinator/core.rs b/vendor/winnow/src/combinator/core.rs new file mode 100644 index 0000000..d784b4e --- /dev/null +++ b/vendor/winnow/src/combinator/core.rs @@ -0,0 +1,491 @@ +use crate::error::{ErrMode, ErrorKind, Needed, ParserError}; +use crate::stream::Stream; +use crate::trace::trace; +use crate::*; + +/// Return the remaining input. +/// +/// # Example +/// +/// ```rust +/// # use winnow::prelude::*; +/// # use winnow::error::ErrorKind; +/// # use winnow::error::InputError; +/// use winnow::combinator::rest; +/// assert_eq!(rest::<_,InputError<_>>.parse_peek("abc"), Ok(("", "abc"))); +/// assert_eq!(rest::<_,InputError<_>>.parse_peek(""), Ok(("", ""))); +/// ``` +#[inline] +pub fn rest<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E> +where + I: Stream, +{ + trace("rest", move |input: &mut I| Ok(input.finish())).parse_next(input) +} + +/// Return the length of the remaining input. +/// +/// Note: this does not advance the [`Stream`] +/// +/// # Example +/// +/// ```rust +/// # use winnow::prelude::*; +/// # use winnow::error::ErrorKind; +/// # use winnow::error::InputError; +/// use winnow::combinator::rest_len; +/// assert_eq!(rest_len::<_,InputError<_>>.parse_peek("abc"), Ok(("abc", 3))); +/// assert_eq!(rest_len::<_,InputError<_>>.parse_peek(""), Ok(("", 0))); +/// ``` +#[inline] +pub fn rest_len<I, E: ParserError<I>>(input: &mut I) -> PResult<usize, E> +where + I: Stream, +{ + trace("rest_len", move |input: &mut I| { + let len = input.eof_offset(); + Ok(len) + }) + .parse_next(input) +} + +/// Apply a [`Parser`], producing `None` on [`ErrMode::Backtrack`]. +/// +/// To chain an error up, see [`cut_err`]. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; +/// # use winnow::prelude::*; +/// use winnow::combinator::opt; +/// use winnow::ascii::alpha1; +/// # fn main() { +/// +/// fn parser(i: &str) -> IResult<&str, Option<&str>> { +/// opt(alpha1).parse_peek(i) +/// } +/// +/// assert_eq!(parser("abcd;"), Ok((";", Some("abcd")))); +/// assert_eq!(parser("123;"), Ok(("123;", None))); +/// # } +/// ``` +pub fn opt<I: Stream, O, E: ParserError<I>, F>(mut f: F) -> impl Parser<I, Option<O>, E> +where + F: Parser<I, O, E>, +{ + trace("opt", move |input: &mut I| { + let start = input.checkpoint(); + match f.parse_next(input) { + Ok(o) => Ok(Some(o)), + Err(ErrMode::Backtrack(_)) => { + input.reset(start); + Ok(None) + } + Err(e) => Err(e), + } + }) +} + +/// Calls the parser if the condition is met. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, IResult}; +/// # use winnow::prelude::*; +/// use winnow::combinator::cond; +/// use winnow::ascii::alpha1; +/// # fn main() { +/// +/// fn parser(b: bool, i: &str) -> IResult<&str, Option<&str>> { +/// cond(b, alpha1).parse_peek(i) +/// } +/// +/// assert_eq!(parser(true, "abcd;"), Ok((";", Some("abcd")))); +/// assert_eq!(parser(false, "abcd;"), Ok(("abcd;", None))); +/// assert_eq!(parser(true, "123;"), Err(ErrMode::Backtrack(InputError::new("123;", ErrorKind::Slice)))); +/// assert_eq!(parser(false, "123;"), Ok(("123;", None))); +/// # } +/// ``` +pub fn cond<I, O, E: ParserError<I>, F>(b: bool, mut f: F) -> impl Parser<I, Option<O>, E> +where + I: Stream, + F: Parser<I, O, E>, +{ + trace("cond", move |input: &mut I| { + if b { + f.parse_next(input).map(Some) + } else { + Ok(None) + } + }) +} + +/// Tries to apply its parser without consuming the input. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, IResult}; +/// # use winnow::prelude::*; +/// use winnow::combinator::peek; +/// use winnow::ascii::alpha1; +/// # fn main() { +/// +/// let mut parser = peek(alpha1); +/// +/// assert_eq!(parser.parse_peek("abcd;"), Ok(("abcd;", "abcd"))); +/// assert_eq!(parser.parse_peek("123;"), Err(ErrMode::Backtrack(InputError::new("123;", ErrorKind::Slice)))); +/// # } +/// ``` +#[doc(alias = "look_ahead")] +#[doc(alias = "rewind")] +pub fn peek<I: Stream, O, E: ParserError<I>, F>(mut f: F) -> impl Parser<I, O, E> +where + F: Parser<I, O, E>, +{ + trace("peek", move |input: &mut I| { + let start = input.checkpoint(); + let res = f.parse_next(input); + input.reset(start); + res + }) +} + +/// Match the end of the [`Stream`] +/// +/// Otherwise, it will error. +/// +/// # Example +/// +/// ```rust +/// # use std::str; +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; +/// # use winnow::combinator::eof; +/// # use winnow::prelude::*; +/// +/// let mut parser = eof; +/// assert_eq!(parser.parse_peek("abc"), Err(ErrMode::Backtrack(InputError::new("abc", ErrorKind::Eof)))); +/// assert_eq!(parser.parse_peek(""), Ok(("", ""))); +/// ``` +#[doc(alias = "end")] +#[doc(alias = "eoi")] +pub fn eof<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E> +where + I: Stream, +{ + trace("eof", move |input: &mut I| { + if input.eof_offset() == 0 { + Ok(input.next_slice(0)) + } else { + Err(ErrMode::from_error_kind(input, ErrorKind::Eof)) + } + }) + .parse_next(input) +} + +/// Succeeds if the child parser returns an error. +/// +/// **Note:** This does not advance the [`Stream`] +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, IResult}; +/// # use winnow::prelude::*; +/// use winnow::combinator::not; +/// use winnow::ascii::alpha1; +/// # fn main() { +/// +/// let mut parser = not(alpha1); +/// +/// assert_eq!(parser.parse_peek("123"), Ok(("123", ()))); +/// assert_eq!(parser.parse_peek("abcd"), Err(ErrMode::Backtrack(InputError::new("abcd", ErrorKind::Not)))); +/// # } +/// ``` +pub fn not<I: Stream, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, (), E> +where + F: Parser<I, O, E>, +{ + trace("not", move |input: &mut I| { + let start = input.checkpoint(); + let res = parser.parse_next(input); + input.reset(start); + match res { + Ok(_) => Err(ErrMode::from_error_kind(input, ErrorKind::Not)), + Err(ErrMode::Backtrack(_)) => Ok(()), + Err(e) => Err(e), + } + }) +} + +/// Transforms an [`ErrMode::Backtrack`] (recoverable) to [`ErrMode::Cut`] (unrecoverable) +/// +/// This commits the parse result, preventing alternative branch paths like with +/// [`winnow::combinator::alt`][crate::combinator::alt]. +/// +/// # Example +/// +/// Without `cut_err`: +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; +/// # use winnow::token::one_of; +/// # use winnow::ascii::digit1; +/// # use winnow::combinator::rest; +/// # use winnow::combinator::alt; +/// # use winnow::combinator::preceded; +/// # use winnow::prelude::*; +/// # fn main() { +/// +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt(( +/// preceded(one_of(['+', '-']), digit1), +/// rest +/// )).parse_peek(input) +/// } +/// +/// assert_eq!(parser("+10 ab"), Ok((" ab", "10"))); +/// assert_eq!(parser("ab"), Ok(("", "ab"))); +/// assert_eq!(parser("+"), Ok(("", "+"))); +/// # } +/// ``` +/// +/// With `cut_err`: +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; +/// # use winnow::prelude::*; +/// # use winnow::token::one_of; +/// # use winnow::ascii::digit1; +/// # use winnow::combinator::rest; +/// # use winnow::combinator::alt; +/// # use winnow::combinator::preceded; +/// use winnow::combinator::cut_err; +/// # fn main() { +/// +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt(( +/// preceded(one_of(['+', '-']), cut_err(digit1)), +/// rest +/// )).parse_peek(input) +/// } +/// +/// assert_eq!(parser("+10 ab"), Ok((" ab", "10"))); +/// assert_eq!(parser("ab"), Ok(("", "ab"))); +/// assert_eq!(parser("+"), Err(ErrMode::Cut(InputError::new("", ErrorKind::Slice )))); +/// # } +/// ``` +pub fn cut_err<I, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, O, E> +where + I: Stream, + F: Parser<I, O, E>, +{ + trace("cut_err", move |input: &mut I| { + parser.parse_next(input).map_err(|e| e.cut()) + }) +} + +/// Transforms an [`ErrMode::Cut`] (unrecoverable) to [`ErrMode::Backtrack`] (recoverable) +/// +/// This attempts the parse, allowing other parsers to be tried on failure, like with +/// [`winnow::combinator::alt`][crate::combinator::alt]. +pub fn backtrack_err<I, O, E: ParserError<I>, F>(mut parser: F) -> impl Parser<I, O, E> +where + I: Stream, + F: Parser<I, O, E>, +{ + trace("backtrack_err", move |input: &mut I| { + parser.parse_next(input).map_err(|e| e.backtrack()) + }) +} + +/// A placeholder for a not-yet-implemented [`Parser`] +/// +/// This is analogous to the [`todo!`] macro and helps with prototyping. +/// +/// # Panic +/// +/// This will panic when parsing +/// +/// # Example +/// +/// ```rust +/// # use winnow::prelude::*; +/// # use winnow::combinator::todo; +/// +/// fn parser(input: &mut &str) -> PResult<u64> { +/// todo(input) +/// } +/// ``` +#[track_caller] +pub fn todo<I, O, E>(input: &mut I) -> PResult<O, E> +where + I: Stream, +{ + #![allow(clippy::todo)] + trace("todo", move |_input: &mut I| todo!("unimplemented parse")).parse_next(input) +} + +/// Repeats the embedded parser, lazily returning the results +/// +/// Call the iterator's [`ParserIterator::finish`] method to get the remaining input if successful, +/// or the error value if we encountered an error. +/// +/// On [`ErrMode::Backtrack`], iteration will stop. To instead chain an error up, see [`cut_err`]. +/// +/// # Example +/// +/// ```rust +/// use winnow::{combinator::iterator, IResult, token::tag, ascii::alpha1, combinator::terminated}; +/// use std::collections::HashMap; +/// +/// let data = "abc|defg|hijkl|mnopqr|123"; +/// let mut it = iterator(data, terminated(alpha1, "|")); +/// +/// let parsed = it.map(|v| (v, v.len())).collect::<HashMap<_,_>>(); +/// let res: IResult<_,_> = it.finish(); +/// +/// assert_eq!(parsed, [("abc", 3usize), ("defg", 4), ("hijkl", 5), ("mnopqr", 6)].iter().cloned().collect()); +/// assert_eq!(res, Ok(("123", ()))); +/// ``` +pub fn iterator<I, O, E, F>(input: I, parser: F) -> ParserIterator<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, + E: ParserError<I>, +{ + ParserIterator { + parser, + input, + state: Some(State::Running), + o: Default::default(), + } +} + +/// Main structure associated to [`iterator`]. +pub struct ParserIterator<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + parser: F, + input: I, + state: Option<State<E>>, + o: core::marker::PhantomData<O>, +} + +impl<F, I, O, E> ParserIterator<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + /// Returns the remaining input if parsing was successful, or the error if we encountered an error. + pub fn finish(mut self) -> PResult<(I, ()), E> { + match self.state.take().unwrap() { + State::Running | State::Done => Ok((self.input, ())), + State::Failure(e) => Err(ErrMode::Cut(e)), + State::Incomplete(i) => Err(ErrMode::Incomplete(i)), + } + } +} + +impl<'a, F, I, O, E> core::iter::Iterator for &'a mut ParserIterator<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + type Item = O; + + fn next(&mut self) -> Option<Self::Item> { + if let State::Running = self.state.take().unwrap() { + let start = self.input.checkpoint(); + + match self.parser.parse_next(&mut self.input) { + Ok(o) => { + self.state = Some(State::Running); + Some(o) + } + Err(ErrMode::Backtrack(_)) => { + self.input.reset(start); + self.state = Some(State::Done); + None + } + Err(ErrMode::Cut(e)) => { + self.state = Some(State::Failure(e)); + None + } + Err(ErrMode::Incomplete(i)) => { + self.state = Some(State::Incomplete(i)); + None + } + } + } else { + None + } + } +} + +enum State<E> { + Running, + Done, + Failure(E), + Incomplete(Needed), +} + +/// Always succeeds with given value without consuming any input. +/// +/// For example, it can be used as the last alternative in `alt` to +/// specify the default case. +/// +/// **Note:** This never advances the [`Stream`] +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; +/// # use winnow::prelude::*; +/// use winnow::combinator::alt; +/// use winnow::combinator::success; +/// +/// let mut parser = success::<_,_,InputError<_>>(10); +/// assert_eq!(parser.parse_peek("xyz"), Ok(("xyz", 10))); +/// +/// fn sign(input: &str) -> IResult<&str, isize> { +/// alt(( +/// '-'.value(-1), +/// '+'.value(1), +/// success::<_,_,InputError<_>>(1) +/// )).parse_peek(input) +/// } +/// assert_eq!(sign("+10"), Ok(("10", 1))); +/// assert_eq!(sign("-10"), Ok(("10", -1))); +/// assert_eq!(sign("10"), Ok(("10", 1))); +/// ``` +#[doc(alias = "value")] +#[doc(alias = "empty")] +pub fn success<I: Stream, O: Clone, E: ParserError<I>>(val: O) -> impl Parser<I, O, E> { + trace("success", move |_input: &mut I| Ok(val.clone())) +} + +/// A parser which always fails. +/// +/// For example, it can be used as the last alternative in `alt` to +/// control the error message given. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, IResult}; +/// # use winnow::prelude::*; +/// use winnow::combinator::fail; +/// +/// let s = "string"; +/// assert_eq!(fail::<_, &str, _>.parse_peek(s), Err(ErrMode::Backtrack(InputError::new(s, ErrorKind::Fail)))); +/// ``` +#[doc(alias = "unexpected")] +pub fn fail<I: Stream, O, E: ParserError<I>>(i: &mut I) -> PResult<O, E> { + trace("fail", |i: &mut I| { + Err(ErrMode::from_error_kind(i, ErrorKind::Fail)) + }) + .parse_next(i) +} diff --git a/vendor/winnow/src/combinator/mod.rs b/vendor/winnow/src/combinator/mod.rs new file mode 100644 index 0000000..3be56bc --- /dev/null +++ b/vendor/winnow/src/combinator/mod.rs @@ -0,0 +1,172 @@ +//! # List of parsers and combinators +//! +//! **Note**: this list is meant to provide a nicer way to find a parser than reading through the documentation on docs.rs. Function combinators are organized in module so they are a bit easier to find. +//! +//! ## Basic elements +//! +//! Those are used to recognize the lowest level elements of your grammar, like, "here is a dot", or "here is an big endian integer". +//! +//! | combinator | usage | input | output | comment | +//! |---|---|---|---|---| +//! | [`one_of`][crate::token::one_of] | `one_of(['a', 'b', 'c'])` | `"abc"` | `Ok(("bc", 'a'))` |Matches one of the provided characters (works with non ASCII characters too)| +//! | [`none_of`][crate::token::none_of] | `none_of(['a', 'b', 'c'])` | `"xyab"` | `Ok(("yab", 'x'))` |Matches anything but the provided characters| +//! | [`tag`][crate::token::tag] | `"hello"` | `"hello world"` | `Ok((" world", "hello"))` |Recognizes a specific suite of characters or bytes| +//! | [`tag_no_case`][crate::token::tag_no_case] | `tag_no_case("hello")` | `"HeLLo World"` | `Ok((" World", "HeLLo"))` |Case insensitive comparison. Note that case insensitive comparison is not well defined for unicode, and that you might have bad surprises| +//! | [`take`][crate::token::take] | `take(4)` | `"hello"` | `Ok(("o", "hell"))` |Takes a specific number of bytes or characters| +//! | [`take_while`][crate::token::take_while] | `take_while(0.., is_alphabetic)` | `"abc123"` | `Ok(("123", "abc"))` |Returns the longest list of bytes for which the provided pattern matches.| +//! | [`take_till0`][crate::token::take_till0] | `take_till0(is_alphabetic)` | `"123abc"` | `Ok(("abc", "123"))` |Returns the longest list of bytes or characters until the provided pattern matches. `take_till1` does the same, but must return at least one character. This is the reverse behaviour from `take_while`: `take_till(f)` is equivalent to `take_while(0.., \|c\| !f(c))`| +//! | [`take_until0`][crate::token::take_until0] | `take_until0("world")` | `"Hello world"` | `Ok(("world", "Hello "))` |Returns the longest list of bytes or characters until the provided tag is found. `take_until1` does the same, but must return at least one character| +//! +//! ## Choice combinators +//! +//! | combinator | usage | input | output | comment | +//! |---|---|---|---|---| +//! | [`alt`] | `alt(("ab", "cd"))` | `"cdef"` | `Ok(("ef", "cd"))` |Try a list of parsers and return the result of the first successful one| +//! | [`dispatch`] | \- | \- | \- | `match` for parsers | +//! | [`permutation`] | `permutation(("ab", "cd", "12"))` | `"cd12abc"` | `Ok(("c", ("ab", "cd", "12"))` |Succeeds when all its child parser have succeeded, whatever the order| +//! +//! ## Sequence combinators +//! +//! | combinator | usage | input | output | comment | +//! |---|---|---|---|---| +//! | [`(...)` (tuples)][crate::Parser] | `("ab", "XY", take(1))` | `"abXYZ!"` | `Ok(("!", ("ab", "XY", "Z")))` |Chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple| +//! | [`delimited`] | `delimited(char('('), take(2), char(')'))` | `"(ab)cd"` | `Ok(("cd", "ab"))` || +//! | [`preceded`] | `preceded("ab", "XY")` | `"abXYZ"` | `Ok(("Z", "XY"))` || +//! | [`terminated`] | `terminated("ab", "XY")` | `"abXYZ"` | `Ok(("Z", "ab"))` || +//! | [`separated_pair`] | `separated_pair("hello", char(','), "world")` | `"hello,world!"` | `Ok(("!", ("hello", "world")))` || +//! +//! ## Applying a parser multiple times +//! +//! | combinator | usage | input | output | comment | +//! |---|---|---|---|---| +//! | [`repeat`] | `repeat(1..=3, "ab")` | `"ababc"` | `Ok(("c", vec!["ab", "ab"]))` |Applies the parser between m and n times (n included) and returns the list of results in a Vec| +//! | [`repeat_till0`] | `repeat_till0(tag( "ab" ), tag( "ef" ))` | `"ababefg"` | `Ok(("g", (vec!["ab", "ab"], "ef")))` |Applies the first parser until the second applies. Returns a tuple containing the list of results from the first in a Vec and the result of the second| +//! | [`separated0`] | `separated0("ab", ",")` | `"ab,ab,ab."` | `Ok((".", vec!["ab", "ab", "ab"]))` |`separated1` works like `separated0` but must returns at least one element| +//! | [`fold_repeat`] | `fold_repeat(1..=2, be_u8, \|\| 0, \|acc, item\| acc + item)` | `[1, 2, 3]` | `Ok(([3], 3))` |Applies the parser between m and n times (n included) and folds the list of return value| +//! +//! ## Partial related +//! +//! - [`eof`]: Returns its input if it is at the end of input data +//! - [`Parser::complete_err`]: Replaces an `Incomplete` returned by the child parser with an `Backtrack` +//! +//! ## Modifiers +//! +//! - [`cond`]: Conditional combinator. Wraps another parser and calls it if the condition is met +//! - [`Parser::flat_map`]: method to map a new parser from the output of the first parser, then apply that parser over the rest of the input +//! - [`Parser::value`]: method to replace the result of a parser +//! - [`Parser::map`]: method to map a function on the result of a parser +//! - [`Parser::and_then`]: Applies a second parser over the output of the first one +//! - [`Parser::verify_map`]: Maps a function returning an `Option` on the output of a parser +//! - [`Parser::try_map`]: Maps a function returning a `Result` on the output of a parser +//! - [`Parser::parse_to`]: Apply [`std::str::FromStr`] to the output of the parser +//! - [`not`]: Returns a result only if the embedded parser returns `Backtrack` or `Incomplete`. Does not consume the input +//! - [`opt`]: Make the underlying parser optional +//! - [`peek`]: Returns a result without consuming the input +//! - [`Parser::recognize`]: If the child parser was successful, return the consumed input as the produced value +//! - [`Parser::with_recognized`]: If the child parser was successful, return a tuple of the consumed input and the produced output. +//! - [`Parser::span`]: If the child parser was successful, return the location of the consumed input as the produced value +//! - [`Parser::with_span`]: If the child parser was successful, return a tuple of the location of the consumed input and the produced output. +//! - [`Parser::verify`]: Returns the result of the child parser if it satisfies a verification function +//! +//! ## Error management and debugging +//! +//! - [`cut_err`]: Commit the parse result, disallowing alternative parsers from being attempted +//! - [`backtrack_err`]: Attemmpts a parse, allowing alternative parsers to be attempted despite +//! use of `cut_err` +//! - [`Parser::context`]: Add context to the error if the parser fails +//! - [`trace`][crate::trace::trace]: Print the parse state with the `debug` feature flag +//! - [`todo()`]: Placeholder parser +//! +//! ## Remaining combinators +//! +//! - [`success`]: Returns a value without consuming any input, always succeeds +//! - [`fail`]: Inversion of `success`. Always fails. +//! - [`Parser::by_ref`]: Allow moving `&mut impl Parser` into other parsers +//! +//! ## Text parsing +//! +//! - [`any`][crate::token::any]: Matches one token +//! - [`tab`][crate::ascii::tab]: Matches a tab character `\t` +//! - [`crlf`][crate::ascii::crlf]: Recognizes the string `\r\n` +//! - [`line_ending`][crate::ascii::line_ending]: Recognizes an end of line (both `\n` and `\r\n`) +//! - [`newline`][crate::ascii::newline]: Matches a newline character `\n` +//! - [`not_line_ending`][crate::ascii::not_line_ending]: Recognizes a string of any char except `\r` or `\n` +//! - [`rest`]: Return the remaining input +//! +//! - [`alpha0`][crate::ascii::alpha0]: Recognizes zero or more lowercase and uppercase alphabetic characters: `[a-zA-Z]`. [`alpha1`][crate::ascii::alpha1] does the same but returns at least one character +//! - [`alphanumeric0`][crate::ascii::alphanumeric0]: Recognizes zero or more numerical and alphabetic characters: `[0-9a-zA-Z]`. [`alphanumeric1`][crate::ascii::alphanumeric1] does the same but returns at least one character +//! - [`space0`][crate::ascii::space0]: Recognizes zero or more spaces and tabs. [`space1`][crate::ascii::space1] does the same but returns at least one character +//! - [`multispace0`][crate::ascii::multispace0]: Recognizes zero or more spaces, tabs, carriage returns and line feeds. [`multispace1`][crate::ascii::multispace1] does the same but returns at least one character +//! - [`digit0`][crate::ascii::digit0]: Recognizes zero or more numerical characters: `[0-9]`. [`digit1`][crate::ascii::digit1] does the same but returns at least one character +//! - [`hex_digit0`][crate::ascii::hex_digit0]: Recognizes zero or more hexadecimal numerical characters: `[0-9A-Fa-f]`. [`hex_digit1`][crate::ascii::hex_digit1] does the same but returns at least one character +//! - [`oct_digit0`][crate::ascii::oct_digit0]: Recognizes zero or more octal characters: `[0-7]`. [`oct_digit1`][crate::ascii::oct_digit1] does the same but returns at least one character +//! +//! - [`float`][crate::ascii::float]: Parse a floating point number in a byte string +//! - [`dec_int`][crate::ascii::dec_uint]: Decode a variable-width, decimal signed integer +//! - [`dec_uint`][crate::ascii::dec_uint]: Decode a variable-width, decimal unsigned integer +//! - [`hex_uint`][crate::ascii::hex_uint]: Decode a variable-width, hexadecimal integer +//! +//! - [`escaped`][crate::ascii::escaped]: Matches a byte string with escaped characters +//! - [`escaped_transform`][crate::ascii::escaped_transform]: Matches a byte string with escaped characters, and returns a new string with the escaped characters replaced +//! +//! ### Character test functions +//! +//! Use these functions with a combinator like `take_while`: +//! +//! - [`AsChar::is_alpha`][crate::stream::AsChar::is_alpha]: Tests if byte is ASCII alphabetic: `[A-Za-z]` +//! - [`AsChar::is_alphanum`][crate::stream::AsChar::is_alphanum]: Tests if byte is ASCII alphanumeric: `[A-Za-z0-9]` +//! - [`AsChar::is_dec_digit`][crate::stream::AsChar::is_dec_digit]: Tests if byte is ASCII digit: `[0-9]` +//! - [`AsChar::is_hex_digit`][crate::stream::AsChar::is_hex_digit]: Tests if byte is ASCII hex digit: `[0-9A-Fa-f]` +//! - [`AsChar::is_oct_digit`][crate::stream::AsChar::is_oct_digit]: Tests if byte is ASCII octal digit: `[0-7]` +//! - [`AsChar::is_space`][crate::stream::AsChar::is_space]: Tests if byte is ASCII space or tab: `[ \t]` +//! - [`AsChar::is_newline`][crate::stream::AsChar::is_newline]: Tests if byte is ASCII newline: `[\n]` +//! +//! ## Binary format parsing +//! +//! - [`length_count`][crate::binary::length_count] Gets a number from the first parser, then applies the second parser that many times +//! - [`length_data`][crate::binary::length_data]: Gets a number from the first parser, then takes a subslice of the input of that size, and returns that subslice +//! - [`length_value`][crate::binary::length_value]: Gets a number from the first parser, takes a subslice of the input of that size, then applies the second parser on that subslice. If the second parser returns `Incomplete`, `length_value` will return an error +//! +//! ### Integers +//! +//! Parsing integers from binary formats can be done in two ways: With parser functions, or combinators with configurable endianness. +//! +//! - **configurable endianness:** [`i16`][crate::binary::i16], [`i32`][crate::binary::i32], +//! [`i64`][crate::binary::i64], [`u16`][crate::binary::u16], [`u32`][crate::binary::u32], +//! [`u64`][crate::binary::u64] are combinators that take as argument a +//! [`winnow::binary::Endianness`][crate::binary::Endianness], like this: `i16(endianness)`. If the +//! parameter is `winnow::binary::Endianness::Big`, parse a big endian `i16` integer, otherwise a +//! little endian `i16` integer. +//! - **fixed endianness**: The functions are prefixed by `be_` for big endian numbers, and by `le_` for little endian numbers, and the suffix is the type they parse to. As an example, `be_u32` parses a big endian unsigned integer stored in 32 bits. +//! - [`be_f32`][crate::binary::be_f32], [`be_f64`][crate::binary::be_f64]: Big endian floating point numbers +//! - [`le_f32`][crate::binary::le_f32], [`le_f64`][crate::binary::le_f64]: Little endian floating point numbers +//! - [`be_i8`][crate::binary::be_i8], [`be_i16`][crate::binary::be_i16], [`be_i24`][crate::binary::be_i24], [`be_i32`][crate::binary::be_i32], [`be_i64`][crate::binary::be_i64], [`be_i128`][crate::binary::be_i128]: Big endian signed integers +//! - [`be_u8`][crate::binary::be_u8], [`be_u16`][crate::binary::be_u16], [`be_u24`][crate::binary::be_u24], [`be_u32`][crate::binary::be_u32], [`be_u64`][crate::binary::be_u64], [`be_u128`][crate::binary::be_u128]: Big endian unsigned integers +//! - [`le_i8`][crate::binary::le_i8], [`le_i16`][crate::binary::le_i16], [`le_i24`][crate::binary::le_i24], [`le_i32`][crate::binary::le_i32], [`le_i64`][crate::binary::le_i64], [`le_i128`][crate::binary::le_i128]: Little endian signed integers +//! - [`le_u8`][crate::binary::le_u8], [`le_u16`][crate::binary::le_u16], [`le_u24`][crate::binary::le_u24], [`le_u32`][crate::binary::le_u32], [`le_u64`][crate::binary::le_u64], [`le_u128`][crate::binary::le_u128]: Little endian unsigned integers +//! +//! ### Bit stream parsing +//! +//! - [`bits`][crate::binary::bits::bits]: Transforms the current input type (byte slice `&[u8]`) to a bit stream on which bit specific parsers and more general combinators can be applied +//! - [`bytes`][crate::binary::bits::bytes]: Transforms its bits stream input back into a byte slice for the underlying parser +//! - [`take`][crate::binary::bits::take]: Take a set number of its +//! - [`tag`][crate::binary::bits::tag]: Check if a set number of bis matches a pattern +//! - [`bool`][crate::binary::bits::bool]: Match any one bit + +mod branch; +mod core; +mod multi; +mod parser; +mod sequence; + +#[cfg(test)] +mod tests; + +pub use self::branch::*; +pub use self::core::*; +pub use self::multi::*; +pub use self::parser::*; +pub use self::sequence::*; + +#[allow(unused_imports)] +use crate::Parser; diff --git a/vendor/winnow/src/combinator/multi.rs b/vendor/winnow/src/combinator/multi.rs new file mode 100644 index 0000000..913b6d9 --- /dev/null +++ b/vendor/winnow/src/combinator/multi.rs @@ -0,0 +1,945 @@ +//! Combinators applying their child parser multiple times + +use crate::error::ErrMode; +use crate::error::ErrorKind; +use crate::error::ParserError; +use crate::stream::Accumulate; +use crate::stream::Range; +use crate::stream::Stream; +use crate::trace::trace; +use crate::PResult; +use crate::Parser; + +/// [`Accumulate`] the output of a parser into a container, like `Vec` +/// +/// This stops before `n` when the parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see +/// [`cut_err`][crate::combinator::cut_err]. +/// +/// # Arguments +/// * `m` The minimum number of iterations. +/// * `n` The maximum number of iterations. +/// * `f` The parser to apply. +/// +/// To recognize a series of tokens, [`Accumulate`] into a `()` and then [`Parser::recognize`]. +/// +/// **Warning:** If the parser passed to `repeat` accepts empty inputs +/// (like `alpha0` or `digit0`), `repeat` will return an error, +/// to prevent going into an infinite loop. +/// +/// # Example +/// +/// Zero or more reptitions: +/// ```rust +/// # #[cfg(feature = "std")] { +/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::repeat; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// repeat(0.., "abc").parse_peek(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// # } +/// ``` +/// +/// One or more reptitions: +/// ```rust +/// # #[cfg(feature = "std")] { +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::repeat; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// repeat(1.., "abc").parse_peek(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Err(ErrMode::Backtrack(InputError::new("123123", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// # } +/// ``` +/// +/// Fixed number of repeitions: +/// ```rust +/// # #[cfg(feature = "std")] { +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::repeat; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// repeat(2, "abc").parse_peek(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag)))); +/// assert_eq!(parser("123123"), Err(ErrMode::Backtrack(InputError::new("123123", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// # } +/// ``` +/// +/// Arbitrary reptitions: +/// ```rust +/// # #[cfg(feature = "std")] { +/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::repeat; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// repeat(0..=2, "abc").parse_peek(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// # } +/// ``` +#[doc(alias = "many0")] +#[doc(alias = "count")] +#[doc(alias = "many0_count")] +#[doc(alias = "many1")] +#[doc(alias = "many1_count")] +#[doc(alias = "many_m_n")] +#[doc(alias = "repeated")] +#[doc(alias = "skip_many")] +#[doc(alias = "skip_many1")] +#[inline(always)] +pub fn repeat<I, O, C, E, F>(range: impl Into<Range>, mut f: F) -> impl Parser<I, C, E> +where + I: Stream, + C: Accumulate<O>, + F: Parser<I, O, E>, + E: ParserError<I>, +{ + let Range { + start_inclusive, + end_inclusive, + } = range.into(); + trace("repeat", move |i: &mut I| { + match (start_inclusive, end_inclusive) { + (0, None) => repeat0_(&mut f, i), + (1, None) => repeat1_(&mut f, i), + (start, end) if Some(start) == end => repeat_n_(start, &mut f, i), + (start, end) => repeat_m_n_(start, end.unwrap_or(usize::MAX), &mut f, i), + } + }) +} + +fn repeat0_<I, O, C, E, F>(f: &mut F, i: &mut I) -> PResult<C, E> +where + I: Stream, + C: Accumulate<O>, + F: Parser<I, O, E>, + E: ParserError<I>, +{ + let mut acc = C::initial(None); + loop { + let start = i.checkpoint(); + let len = i.eof_offset(); + match f.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(acc); + } + Err(e) => return Err(e), + Ok(o) => { + // infinite loop check: the parser must always consume + if i.eof_offset() == len { + return Err(ErrMode::assert(i, "`repeat` parsers must always consume")); + } + + acc.accumulate(o); + } + } + } +} + +fn repeat1_<I, O, C, E, F>(f: &mut F, i: &mut I) -> PResult<C, E> +where + I: Stream, + C: Accumulate<O>, + F: Parser<I, O, E>, + E: ParserError<I>, +{ + match f.parse_next(i) { + Err(e) => Err(e.append(i, ErrorKind::Many)), + Ok(o) => { + let mut acc = C::initial(None); + acc.accumulate(o); + + loop { + let start = i.checkpoint(); + let len = i.eof_offset(); + match f.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(acc); + } + Err(e) => return Err(e), + Ok(o) => { + // infinite loop check: the parser must always consume + if i.eof_offset() == len { + return Err(ErrMode::assert(i, "`repeat` parsers must always consume")); + } + + acc.accumulate(o); + } + } + } + } + } +} + +/// [`Accumulate`] the output of parser `f` into a container, like `Vec`, until the parser `g` +/// produces a result. +/// +/// Returns a tuple of the results of `f` in a `Vec` and the result of `g`. +/// +/// `f` keeps going so long as `g` produces [`ErrMode::Backtrack`]. To instead chain an error up, see [`cut_err`][crate::combinator::cut_err]. +/// +/// To recognize a series of tokens, [`Accumulate`] into a `()` and then [`Parser::recognize`]. +/// +/// # Example +/// +/// ```rust +/// # #[cfg(feature = "std")] { +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::repeat_till0; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, (Vec<&str>, &str)> { +/// repeat_till0("abc", "end").parse_peek(s) +/// }; +/// +/// assert_eq!(parser("abcabcend"), Ok(("", (vec!["abc", "abc"], "end")))); +/// assert_eq!(parser("abc123end"), Err(ErrMode::Backtrack(InputError::new("123end", ErrorKind::Tag)))); +/// assert_eq!(parser("123123end"), Err(ErrMode::Backtrack(InputError::new("123123end", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("abcendefg"), Ok(("efg", (vec!["abc"], "end")))); +/// # } +/// ``` +#[doc(alias = "many_till0")] +pub fn repeat_till0<I, O, C, P, E, F, G>(mut f: F, mut g: G) -> impl Parser<I, (C, P), E> +where + I: Stream, + C: Accumulate<O>, + F: Parser<I, O, E>, + G: Parser<I, P, E>, + E: ParserError<I>, +{ + trace("repeat_till0", move |i: &mut I| { + let mut res = C::initial(None); + loop { + let start = i.checkpoint(); + let len = i.eof_offset(); + match g.parse_next(i) { + Ok(o) => return Ok((res, o)), + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + match f.parse_next(i) { + Err(e) => return Err(e.append(i, ErrorKind::Many)), + Ok(o) => { + // infinite loop check: the parser must always consume + if i.eof_offset() == len { + return Err(ErrMode::assert( + i, + "`repeat` parsers must always consume", + )); + } + + res.accumulate(o); + } + } + } + Err(e) => return Err(e), + } + } + }) +} + +/// [`Accumulate`] the output of a parser, interleaved with `sep` +/// +/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see +/// [`cut_err`][crate::combinator::cut_err]. +/// +/// # Arguments +/// * `parser` Parses the elements of the list. +/// * `sep` Parses the separator between list elements. +/// +/// # Example +/// +/// ```rust +/// # #[cfg(feature = "std")] { +/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::separated0; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// separated0("abc", "|").parse_peek(s) +/// } +/// +/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"]))); +/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"]))); +/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("def|abc"), Ok(("def|abc", vec![]))); +/// # } +/// ``` +#[doc(alias = "sep_by")] +#[doc(alias = "separated_list0")] +pub fn separated0<I, O, C, O2, E, P, S>(mut parser: P, mut sep: S) -> impl Parser<I, C, E> +where + I: Stream, + C: Accumulate<O>, + P: Parser<I, O, E>, + S: Parser<I, O2, E>, + E: ParserError<I>, +{ + trace("separated0", move |i: &mut I| { + let mut res = C::initial(None); + + let start = i.checkpoint(); + match parser.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(res); + } + Err(e) => return Err(e), + Ok(o) => { + res.accumulate(o); + } + } + + loop { + let start = i.checkpoint(); + let len = i.eof_offset(); + match sep.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(res); + } + Err(e) => return Err(e), + Ok(_) => { + // infinite loop check: the parser must always consume + if i.eof_offset() == len { + return Err(ErrMode::assert(i, "sep parsers must always consume")); + } + + match parser.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(res); + } + Err(e) => return Err(e), + Ok(o) => { + res.accumulate(o); + } + } + } + } + } + }) +} + +/// [`Accumulate`] the output of a parser, interleaved with `sep` +/// +/// Fails if the element parser does not produce at least one element.$ +/// +/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see +/// [`cut_err`][crate::combinator::cut_err]. +/// +/// # Arguments +/// * `sep` Parses the separator between list elements. +/// * `f` Parses the elements of the list. +/// +/// # Example +/// +/// ```rust +/// # #[cfg(feature = "std")] { +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::separated1; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// separated1("abc", "|").parse_peek(s) +/// } +/// +/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"]))); +/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"]))); +/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"]))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("def|abc"), Err(ErrMode::Backtrack(InputError::new("def|abc", ErrorKind::Tag)))); +/// # } +/// ``` +#[doc(alias = "sep_by1")] +#[doc(alias = "separated_list1")] +pub fn separated1<I, O, C, O2, E, P, S>(mut parser: P, mut sep: S) -> impl Parser<I, C, E> +where + I: Stream, + C: Accumulate<O>, + P: Parser<I, O, E>, + S: Parser<I, O2, E>, + E: ParserError<I>, +{ + trace("separated1", move |i: &mut I| { + let mut res = C::initial(None); + + // Parse the first element + match parser.parse_next(i) { + Err(e) => return Err(e), + Ok(o) => { + res.accumulate(o); + } + } + + loop { + let start = i.checkpoint(); + let len = i.eof_offset(); + match sep.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(res); + } + Err(e) => return Err(e), + Ok(_) => { + // infinite loop check: the parser must always consume + if i.eof_offset() == len { + return Err(ErrMode::assert(i, "sep parsers must always consume")); + } + + match parser.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(res); + } + Err(e) => return Err(e), + Ok(o) => { + res.accumulate(o); + } + } + } + } + } + }) +} + +/// Alternates between two parsers, merging the results (left associative) +/// +/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see +/// [`cut_err`][crate::combinator::cut_err]. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::separated_foldl1; +/// use winnow::ascii::dec_int; +/// +/// fn parser(s: &str) -> IResult<&str, i32> { +/// separated_foldl1(dec_int, "-", |l, _, r| l - r).parse_peek(s) +/// } +/// +/// assert_eq!(parser("9-3-5"), Ok(("", 1))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice)))); +/// assert_eq!(parser("def|abc"), Err(ErrMode::Backtrack(InputError::new("def|abc", ErrorKind::Slice)))); +/// ``` +pub fn separated_foldl1<I, O, O2, E, P, S, Op>( + mut parser: P, + mut sep: S, + op: Op, +) -> impl Parser<I, O, E> +where + I: Stream, + P: Parser<I, O, E>, + S: Parser<I, O2, E>, + E: ParserError<I>, + Op: Fn(O, O2, O) -> O, +{ + trace("separated_foldl1", move |i: &mut I| { + let mut ol = parser.parse_next(i)?; + + loop { + let start = i.checkpoint(); + let len = i.eof_offset(); + match sep.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(ol); + } + Err(e) => return Err(e), + Ok(s) => { + // infinite loop check: the parser must always consume + if i.eof_offset() == len { + return Err(ErrMode::assert(i, "`repeat` parsers must always consume")); + } + + match parser.parse_next(i) { + Err(ErrMode::Backtrack(_)) => { + i.reset(start); + return Ok(ol); + } + Err(e) => return Err(e), + Ok(or) => { + ol = op(ol, s, or); + } + } + } + } + } + }) +} + +/// Alternates between two parsers, merging the results (right associative) +/// +/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see +/// [`cut_err`][crate::combinator::cut_err]. +/// +/// # Example +/// +/// ``` +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::separated_foldr1; +/// use winnow::ascii::dec_uint; +/// +/// fn parser(s: &str) -> IResult<&str, u32> { +/// separated_foldr1(dec_uint, "^", |l: u32, _, r: u32| l.pow(r)).parse_peek(s) +/// } +/// +/// assert_eq!(parser("2^3^2"), Ok(("", 512))); +/// assert_eq!(parser("2"), Ok(("", 2))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice)))); +/// assert_eq!(parser("def|abc"), Err(ErrMode::Backtrack(InputError::new("def|abc", ErrorKind::Slice)))); +/// ``` +#[cfg(feature = "alloc")] +pub fn separated_foldr1<I, O, O2, E, P, S, Op>( + mut parser: P, + mut sep: S, + op: Op, +) -> impl Parser<I, O, E> +where + I: Stream, + P: Parser<I, O, E>, + S: Parser<I, O2, E>, + E: ParserError<I>, + Op: Fn(O, O2, O) -> O, +{ + trace("separated_foldr1", move |i: &mut I| { + let ol = parser.parse_next(i)?; + let all: crate::lib::std::vec::Vec<(O2, O)> = + repeat(0.., (sep.by_ref(), parser.by_ref())).parse_next(i)?; + if let Some((s, or)) = all + .into_iter() + .rev() + .reduce(|(sr, or), (sl, ol)| (sl, op(ol, sr, or))) + { + let merged = op(ol, s, or); + Ok(merged) + } else { + Ok(ol) + } + }) +} + +fn repeat_m_n_<I, O, C, E, F>(min: usize, max: usize, parse: &mut F, input: &mut I) -> PResult<C, E> +where + I: Stream, + C: Accumulate<O>, + F: Parser<I, O, E>, + E: ParserError<I>, +{ + if min > max { + return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many))); + } + + let mut res = C::initial(Some(min)); + for count in 0..max { + let start = input.checkpoint(); + let len = input.eof_offset(); + match parse.parse_next(input) { + Ok(value) => { + // infinite loop check: the parser must always consume + if input.eof_offset() == len { + return Err(ErrMode::assert( + input, + "`repeat` parsers must always consume", + )); + } + + res.accumulate(value); + } + Err(ErrMode::Backtrack(e)) => { + if count < min { + return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many))); + } else { + input.reset(start); + return Ok(res); + } + } + Err(e) => { + return Err(e); + } + } + } + + Ok(res) +} + +fn repeat_n_<I, O, C, E, F>(count: usize, f: &mut F, i: &mut I) -> PResult<C, E> +where + I: Stream, + C: Accumulate<O>, + F: Parser<I, O, E>, + E: ParserError<I>, +{ + let mut res = C::initial(Some(count)); + + for _ in 0..count { + match f.parse_next(i) { + Ok(o) => { + res.accumulate(o); + } + Err(e) => { + return Err(e.append(i, ErrorKind::Many)); + } + } + } + + Ok(res) +} + +/// Repeats the embedded parser, filling the given slice with results. +/// +/// This parser fails if the input runs out before the given slice is full. +/// +/// # Arguments +/// * `f` The parser to apply. +/// * `buf` The slice to fill +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::fill; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, [&str; 2]> { +/// let mut buf = ["", ""]; +/// let (rest, ()) = fill("abc", &mut buf).parse_peek(s)?; +/// Ok((rest, buf)) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", ["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag)))); +/// assert_eq!(parser("123123"), Err(ErrMode::Backtrack(InputError::new("123123", ErrorKind::Tag)))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", ["abc", "abc"]))); +/// ``` +pub fn fill<'a, I, O, E, F>(mut f: F, buf: &'a mut [O]) -> impl Parser<I, (), E> + 'a +where + I: Stream + 'a, + F: Parser<I, O, E> + 'a, + E: ParserError<I> + 'a, +{ + trace("fill", move |i: &mut I| { + for elem in buf.iter_mut() { + match f.parse_next(i) { + Ok(o) => { + *elem = o; + } + Err(e) => { + return Err(e.append(i, ErrorKind::Many)); + } + } + } + + Ok(()) + }) +} + +/// Repeats the embedded parser `m..=n` times, calling `g` to gather the results +/// +/// This stops before `n` when the parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see +/// [`cut_err`][crate::combinator::cut_err]. +/// +/// # Arguments +/// * `m` The minimum number of iterations. +/// * `n` The maximum number of iterations. +/// * `f` The parser to apply. +/// * `init` A function returning the initial value. +/// * `g` The function that combines a result of `f` with +/// the current accumulator. +/// +/// **Warning:** If the parser passed to `fold_repeat` accepts empty inputs +/// (like `alpha0` or `digit0`), `fold_repeat` will return an error, +/// to prevent going into an infinite loop. +/// +/// # Example +/// +/// Zero or more repetitions: +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::fold_repeat; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold_repeat( +/// 0.., +/// "abc", +/// Vec::new, +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// ).parse_peek(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// ``` +/// +/// One or more repetitions: +/// ```rust +/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::fold_repeat; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold_repeat( +/// 1.., +/// "abc", +/// Vec::new, +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// ).parse_peek(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Err(ErrMode::Backtrack(InputError::new("123123", ErrorKind::Many)))); +/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Many)))); +/// ``` +/// +/// Arbitrary number of repetitions: +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed}; +/// # use winnow::prelude::*; +/// use winnow::combinator::fold_repeat; +/// use winnow::token::tag; +/// +/// fn parser(s: &str) -> IResult<&str, Vec<&str>> { +/// fold_repeat( +/// 0..=2, +/// "abc", +/// Vec::new, +/// |mut acc: Vec<_>, item| { +/// acc.push(item); +/// acc +/// } +/// ).parse_peek(s) +/// } +/// +/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"]))); +/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"]))); +/// assert_eq!(parser("123123"), Ok(("123123", vec![]))); +/// assert_eq!(parser(""), Ok(("", vec![]))); +/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); +/// ``` +#[doc(alias = "fold_many0")] +#[doc(alias = "fold_many1")] +#[doc(alias = "fold_many_m_n")] +#[inline(always)] +pub fn fold_repeat<I, O, E, F, G, H, R>( + range: impl Into<Range>, + mut f: F, + mut init: H, + mut g: G, +) -> impl Parser<I, R, E> +where + I: Stream, + F: Parser<I, O, E>, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParserError<I>, +{ + let Range { + start_inclusive, + end_inclusive, + } = range.into(); + trace("fold_repeat", move |i: &mut I| { + match (start_inclusive, end_inclusive) { + (0, None) => fold_repeat0_(&mut f, &mut init, &mut g, i), + (1, None) => fold_repeat1_(&mut f, &mut init, &mut g, i), + (start, end) => fold_repeat_m_n_( + start, + end.unwrap_or(usize::MAX), + &mut f, + &mut init, + &mut g, + i, + ), + } + }) +} + +fn fold_repeat0_<I, O, E, F, G, H, R>( + f: &mut F, + init: &mut H, + g: &mut G, + input: &mut I, +) -> PResult<R, E> +where + I: Stream, + F: Parser<I, O, E>, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParserError<I>, +{ + let mut res = init(); + + loop { + let start = input.checkpoint(); + let len = input.eof_offset(); + match f.parse_next(input) { + Ok(o) => { + // infinite loop check: the parser must always consume + if input.eof_offset() == len { + return Err(ErrMode::assert( + input, + "`repeat` parsers must always consume", + )); + } + + res = g(res, o); + } + Err(ErrMode::Backtrack(_)) => { + input.reset(start); + return Ok(res); + } + Err(e) => { + return Err(e); + } + } + } +} + +fn fold_repeat1_<I, O, E, F, G, H, R>( + f: &mut F, + init: &mut H, + g: &mut G, + input: &mut I, +) -> PResult<R, E> +where + I: Stream, + F: Parser<I, O, E>, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParserError<I>, +{ + let init = init(); + match f.parse_next(input) { + Err(ErrMode::Backtrack(_)) => Err(ErrMode::from_error_kind(input, ErrorKind::Many)), + Err(e) => Err(e), + Ok(o1) => { + let mut acc = g(init, o1); + + loop { + let start = input.checkpoint(); + let len = input.eof_offset(); + match f.parse_next(input) { + Err(ErrMode::Backtrack(_)) => { + input.reset(start); + break; + } + Err(e) => return Err(e), + Ok(o) => { + // infinite loop check: the parser must always consume + if input.eof_offset() == len { + return Err(ErrMode::assert( + input, + "`repeat` parsers must always consume", + )); + } + + acc = g(acc, o); + } + } + } + + Ok(acc) + } + } +} + +fn fold_repeat_m_n_<I, O, E, F, G, H, R>( + min: usize, + max: usize, + parse: &mut F, + init: &mut H, + fold: &mut G, + input: &mut I, +) -> PResult<R, E> +where + I: Stream, + F: Parser<I, O, E>, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParserError<I>, +{ + if min > max { + return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many))); + } + + let mut acc = init(); + for count in 0..max { + let start = input.checkpoint(); + let len = input.eof_offset(); + match parse.parse_next(input) { + Ok(value) => { + // infinite loop check: the parser must always consume + if input.eof_offset() == len { + return Err(ErrMode::assert( + input, + "`repeat` parsers must always consume", + )); + } + + acc = fold(acc, value); + } + //FInputXMError: handle failure properly + Err(ErrMode::Backtrack(err)) => { + if count < min { + return Err(ErrMode::Backtrack(err.append(input, ErrorKind::Many))); + } else { + input.reset(start); + break; + } + } + Err(e) => return Err(e), + } + } + + Ok(acc) +} diff --git a/vendor/winnow/src/combinator/parser.rs b/vendor/winnow/src/combinator/parser.rs new file mode 100644 index 0000000..c95f1f6 --- /dev/null +++ b/vendor/winnow/src/combinator/parser.rs @@ -0,0 +1,863 @@ +use crate::error::{AddContext, ErrMode, ErrorKind, FromExternalError, ParserError}; +use crate::lib::std::borrow::Borrow; +use crate::lib::std::ops::Range; +use crate::stream::StreamIsPartial; +use crate::stream::{Location, Stream}; +use crate::trace::trace; +use crate::trace::trace_result; +use crate::*; + +/// Implementation of [`Parser::by_ref`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct ByRef<'p, P> { + p: &'p mut P, +} + +impl<'p, P> ByRef<'p, P> { + #[inline(always)] + pub(crate) fn new(p: &'p mut P) -> Self { + Self { p } + } +} + +impl<'p, I, O, E, P> Parser<I, O, E> for ByRef<'p, P> +where + P: Parser<I, O, E>, +{ + #[inline(always)] + fn parse_next(&mut self, i: &mut I) -> PResult<O, E> { + self.p.parse_next(i) + } +} + +/// Implementation of [`Parser::map`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Map<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Fn(O) -> O2, +{ + parser: F, + map: G, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, +} + +impl<F, G, I, O, O2, E> Map<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Fn(O) -> O2, +{ + #[inline(always)] + pub(crate) fn new(parser: F, map: G) -> Self { + Self { + parser, + map, + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + } + } +} + +impl<F, G, I, O, O2, E> Parser<I, O2, E> for Map<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Fn(O) -> O2, +{ + #[inline] + fn parse_next(&mut self, i: &mut I) -> PResult<O2, E> { + match self.parser.parse_next(i) { + Err(e) => Err(e), + Ok(o) => Ok((self.map)(o)), + } + } +} + +/// Implementation of [`Parser::try_map`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct TryMap<F, G, I, O, O2, E, E2> +where + F: Parser<I, O, E>, + G: FnMut(O) -> Result<O2, E2>, + I: Stream, + E: FromExternalError<I, E2>, +{ + parser: F, + map: G, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, + e2: core::marker::PhantomData<E2>, +} + +impl<F, G, I, O, O2, E, E2> TryMap<F, G, I, O, O2, E, E2> +where + F: Parser<I, O, E>, + G: FnMut(O) -> Result<O2, E2>, + I: Stream, + E: FromExternalError<I, E2>, +{ + #[inline(always)] + pub(crate) fn new(parser: F, map: G) -> Self { + Self { + parser, + map, + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + e2: Default::default(), + } + } +} + +impl<F, G, I, O, O2, E, E2> Parser<I, O2, E> for TryMap<F, G, I, O, O2, E, E2> +where + F: Parser<I, O, E>, + G: FnMut(O) -> Result<O2, E2>, + I: Stream, + E: FromExternalError<I, E2>, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<O2, E> { + let start = input.checkpoint(); + let o = self.parser.parse_next(input)?; + let res = (self.map)(o).map_err(|err| { + input.reset(start); + ErrMode::from_external_error(input, ErrorKind::Verify, err) + }); + trace_result("verify", &res); + res + } +} + +/// Implementation of [`Parser::verify_map`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct VerifyMap<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: FnMut(O) -> Option<O2>, + I: Stream, + E: ParserError<I>, +{ + parser: F, + map: G, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, +} + +impl<F, G, I, O, O2, E> VerifyMap<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: FnMut(O) -> Option<O2>, + I: Stream, + E: ParserError<I>, +{ + #[inline(always)] + pub(crate) fn new(parser: F, map: G) -> Self { + Self { + parser, + map, + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + } + } +} + +impl<F, G, I, O, O2, E> Parser<I, O2, E> for VerifyMap<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: FnMut(O) -> Option<O2>, + I: Stream, + E: ParserError<I>, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<O2, E> { + let start = input.checkpoint(); + let o = self.parser.parse_next(input)?; + let res = (self.map)(o).ok_or_else(|| { + input.reset(start); + ErrMode::from_error_kind(input, ErrorKind::Verify) + }); + trace_result("verify", &res); + res + } +} + +/// Implementation of [`Parser::and_then`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct AndThen<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Parser<O, O2, E>, + O: StreamIsPartial, + I: Stream, +{ + outer: F, + inner: G, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, +} + +impl<F, G, I, O, O2, E> AndThen<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Parser<O, O2, E>, + O: StreamIsPartial, + I: Stream, +{ + #[inline(always)] + pub(crate) fn new(outer: F, inner: G) -> Self { + Self { + outer, + inner, + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + } + } +} + +impl<F, G, I, O, O2, E> Parser<I, O2, E> for AndThen<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Parser<O, O2, E>, + O: StreamIsPartial, + I: Stream, +{ + #[inline(always)] + fn parse_next(&mut self, i: &mut I) -> PResult<O2, E> { + let start = i.checkpoint(); + let mut o = self.outer.parse_next(i)?; + let _ = o.complete(); + let o2 = self.inner.parse_next(&mut o).map_err(|err| { + i.reset(start); + err + })?; + Ok(o2) + } +} + +/// Implementation of [`Parser::parse_to`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct ParseTo<P, I, O, O2, E> +where + P: Parser<I, O, E>, + I: Stream, + O: crate::stream::ParseSlice<O2>, + E: ParserError<I>, +{ + p: P, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, +} + +impl<P, I, O, O2, E> ParseTo<P, I, O, O2, E> +where + P: Parser<I, O, E>, + I: Stream, + O: crate::stream::ParseSlice<O2>, + E: ParserError<I>, +{ + #[inline(always)] + pub(crate) fn new(p: P) -> Self { + Self { + p, + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + } + } +} + +impl<P, I, O, O2, E> Parser<I, O2, E> for ParseTo<P, I, O, O2, E> +where + P: Parser<I, O, E>, + I: Stream, + O: crate::stream::ParseSlice<O2>, + E: ParserError<I>, +{ + #[inline] + fn parse_next(&mut self, i: &mut I) -> PResult<O2, E> { + let start = i.checkpoint(); + let o = self.p.parse_next(i)?; + let res = o.parse_slice().ok_or_else(|| { + i.reset(start); + ErrMode::from_error_kind(i, ErrorKind::Verify) + }); + trace_result("verify", &res); + res + } +} + +/// Implementation of [`Parser::flat_map`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct FlatMap<F, G, H, I, O, O2, E> +where + F: Parser<I, O, E>, + G: FnMut(O) -> H, + H: Parser<I, O2, E>, +{ + f: F, + g: G, + h: core::marker::PhantomData<H>, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, +} + +impl<F, G, H, I, O, O2, E> FlatMap<F, G, H, I, O, O2, E> +where + F: Parser<I, O, E>, + G: FnMut(O) -> H, + H: Parser<I, O2, E>, +{ + #[inline(always)] + pub(crate) fn new(f: F, g: G) -> Self { + Self { + f, + g, + h: Default::default(), + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + } + } +} + +impl<F, G, H, I, O, O2, E> Parser<I, O2, E> for FlatMap<F, G, H, I, O, O2, E> +where + F: Parser<I, O, E>, + G: FnMut(O) -> H, + H: Parser<I, O2, E>, +{ + #[inline(always)] + fn parse_next(&mut self, i: &mut I) -> PResult<O2, E> { + let o = self.f.parse_next(i)?; + (self.g)(o).parse_next(i) + } +} + +/// Implementation of [`Parser::complete_err`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct CompleteErr<F> { + f: F, +} + +impl<F> CompleteErr<F> { + #[inline(always)] + pub(crate) fn new(f: F) -> Self { + Self { f } + } +} + +impl<F, I, O, E> Parser<I, O, E> for CompleteErr<F> +where + I: Stream, + F: Parser<I, O, E>, + E: ParserError<I>, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<O, E> { + trace("complete_err", |input: &mut I| { + match (self.f).parse_next(input) { + Err(ErrMode::Incomplete(_)) => { + Err(ErrMode::from_error_kind(input, ErrorKind::Complete)) + } + rest => rest, + } + }) + .parse_next(input) + } +} + +/// Implementation of [`Parser::verify`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Verify<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Fn(&O2) -> bool, + I: Stream, + O: Borrow<O2>, + O2: ?Sized, + E: ParserError<I>, +{ + parser: F, + filter: G, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, +} + +impl<F, G, I, O, O2, E> Verify<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Fn(&O2) -> bool, + I: Stream, + O: Borrow<O2>, + O2: ?Sized, + E: ParserError<I>, +{ + #[inline(always)] + pub(crate) fn new(parser: F, filter: G) -> Self { + Self { + parser, + filter, + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + } + } +} + +impl<F, G, I, O, O2, E> Parser<I, O, E> for Verify<F, G, I, O, O2, E> +where + F: Parser<I, O, E>, + G: Fn(&O2) -> bool, + I: Stream, + O: Borrow<O2>, + O2: ?Sized, + E: ParserError<I>, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<O, E> { + let start = input.checkpoint(); + let o = self.parser.parse_next(input)?; + let res = (self.filter)(o.borrow()).then_some(o).ok_or_else(|| { + input.reset(start); + ErrMode::from_error_kind(input, ErrorKind::Verify) + }); + trace_result("verify", &res); + res + } +} + +/// Implementation of [`Parser::value`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Value<F, I, O, O2, E> +where + F: Parser<I, O, E>, + O2: Clone, +{ + parser: F, + val: O2, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, O2, E> Value<F, I, O, O2, E> +where + F: Parser<I, O, E>, + O2: Clone, +{ + #[inline(always)] + pub(crate) fn new(parser: F, val: O2) -> Self { + Self { + parser, + val, + i: Default::default(), + o: Default::default(), + e: Default::default(), + } + } +} + +impl<F, I, O, O2, E> Parser<I, O2, E> for Value<F, I, O, O2, E> +where + F: Parser<I, O, E>, + O2: Clone, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<O2, E> { + (self.parser).parse_next(input).map(|_| self.val.clone()) + } +} + +/// Implementation of [`Parser::void`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Void<F, I, O, E> +where + F: Parser<I, O, E>, +{ + parser: F, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, E> Void<F, I, O, E> +where + F: Parser<I, O, E>, +{ + #[inline(always)] + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + i: Default::default(), + o: Default::default(), + e: Default::default(), + } + } +} + +impl<F, I, O, E> Parser<I, (), E> for Void<F, I, O, E> +where + F: Parser<I, O, E>, +{ + #[inline(always)] + fn parse_next(&mut self, input: &mut I) -> PResult<(), E> { + (self.parser).parse_next(input).map(|_| ()) + } +} + +/// Implementation of [`Parser::recognize`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Recognize<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + parser: F, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, E> Recognize<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + #[inline(always)] + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + i: Default::default(), + o: Default::default(), + e: Default::default(), + } + } +} + +impl<I, O, E, F> Parser<I, <I as Stream>::Slice, E> for Recognize<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<<I as Stream>::Slice, E> { + let checkpoint = input.checkpoint(); + match (self.parser).parse_next(input) { + Ok(_) => { + let offset = input.offset_from(&checkpoint); + input.reset(checkpoint); + let recognized = input.next_slice(offset); + Ok(recognized) + } + Err(e) => Err(e), + } + } +} + +/// Implementation of [`Parser::with_recognized`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct WithRecognized<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + parser: F, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, E> WithRecognized<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + #[inline(always)] + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + i: Default::default(), + o: Default::default(), + e: Default::default(), + } + } +} + +impl<F, I, O, E> Parser<I, (O, <I as Stream>::Slice), E> for WithRecognized<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<(O, <I as Stream>::Slice), E> { + let checkpoint = input.checkpoint(); + match (self.parser).parse_next(input) { + Ok(result) => { + let offset = input.offset_from(&checkpoint); + input.reset(checkpoint); + let recognized = input.next_slice(offset); + Ok((result, recognized)) + } + Err(e) => Err(e), + } + } +} + +/// Implementation of [`Parser::span`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Span<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream + Location, +{ + parser: F, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, E> Span<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream + Location, +{ + #[inline(always)] + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + i: Default::default(), + o: Default::default(), + e: Default::default(), + } + } +} + +impl<I, O, E, F> Parser<I, Range<usize>, E> for Span<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream + Location, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<Range<usize>, E> { + let start = input.location(); + self.parser.parse_next(input).map(move |_| { + let end = input.location(); + start..end + }) + } +} + +/// Implementation of [`Parser::with_span`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct WithSpan<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream + Location, +{ + parser: F, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, E> WithSpan<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream + Location, +{ + #[inline(always)] + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + i: Default::default(), + o: Default::default(), + e: Default::default(), + } + } +} + +impl<F, I, O, E> Parser<I, (O, Range<usize>), E> for WithSpan<F, I, O, E> +where + F: Parser<I, O, E>, + I: Stream + Location, +{ + #[inline] + fn parse_next(&mut self, input: &mut I) -> PResult<(O, Range<usize>), E> { + let start = input.location(); + self.parser.parse_next(input).map(move |output| { + let end = input.location(); + (output, (start..end)) + }) + } +} + +/// Implementation of [`Parser::output_into`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct OutputInto<F, I, O, O2, E> +where + F: Parser<I, O, E>, + O: Into<O2>, +{ + parser: F, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + o2: core::marker::PhantomData<O2>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, O2, E> OutputInto<F, I, O, O2, E> +where + F: Parser<I, O, E>, + O: Into<O2>, +{ + #[inline(always)] + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + i: Default::default(), + o: Default::default(), + o2: Default::default(), + e: Default::default(), + } + } +} + +impl<F, I, O, O2, E> Parser<I, O2, E> for OutputInto<F, I, O, O2, E> +where + F: Parser<I, O, E>, + O: Into<O2>, +{ + #[inline] + fn parse_next(&mut self, i: &mut I) -> PResult<O2, E> { + self.parser.parse_next(i).map(|o| o.into()) + } +} + +/// Implementation of [`Parser::err_into`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct ErrInto<F, I, O, E, E2> +where + F: Parser<I, O, E>, + E: Into<E2>, +{ + parser: F, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, + e2: core::marker::PhantomData<E2>, +} + +impl<F, I, O, E, E2> ErrInto<F, I, O, E, E2> +where + F: Parser<I, O, E>, + E: Into<E2>, +{ + #[inline(always)] + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + i: Default::default(), + o: Default::default(), + e: Default::default(), + e2: Default::default(), + } + } +} + +impl<F, I, O, E, E2> Parser<I, O, E2> for ErrInto<F, I, O, E, E2> +where + F: Parser<I, O, E>, + E: Into<E2>, +{ + #[inline] + fn parse_next(&mut self, i: &mut I) -> PResult<O, E2> { + match self.parser.parse_next(i) { + Ok(ok) => Ok(ok), + Err(ErrMode::Backtrack(e)) => Err(ErrMode::Backtrack(e.into())), + Err(ErrMode::Cut(e)) => Err(ErrMode::Cut(e.into())), + Err(ErrMode::Incomplete(e)) => Err(ErrMode::Incomplete(e)), + } + } +} + +/// Implementation of [`Parser::context`] +#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] +pub struct Context<F, I, O, E, C> +where + F: Parser<I, O, E>, + I: Stream, + E: AddContext<I, C>, + C: Clone + crate::lib::std::fmt::Debug, +{ + parser: F, + context: C, + i: core::marker::PhantomData<I>, + o: core::marker::PhantomData<O>, + e: core::marker::PhantomData<E>, +} + +impl<F, I, O, E, C> Context<F, I, O, E, C> +where + F: Parser<I, O, E>, + I: Stream, + E: AddContext<I, C>, + C: Clone + crate::lib::std::fmt::Debug, +{ + #[inline(always)] + pub(crate) fn new(parser: F, context: C) -> Self { + Self { + parser, + context, + i: Default::default(), + o: Default::default(), + e: Default::default(), + } + } +} + +impl<F, I, O, E, C> Parser<I, O, E> for Context<F, I, O, E, C> +where + F: Parser<I, O, E>, + I: Stream, + E: AddContext<I, C>, + C: Clone + crate::lib::std::fmt::Debug, +{ + #[inline] + fn parse_next(&mut self, i: &mut I) -> PResult<O, E> { + #[cfg(feature = "debug")] + let name = format!("context={:?}", self.context); + #[cfg(not(feature = "debug"))] + let name = "context"; + trace(name, move |i: &mut I| { + (self.parser) + .parse_next(i) + .map_err(|err| err.add_context(i, self.context.clone())) + }) + .parse_next(i) + } +} diff --git a/vendor/winnow/src/combinator/sequence.rs b/vendor/winnow/src/combinator/sequence.rs new file mode 100644 index 0000000..5cfeb9c --- /dev/null +++ b/vendor/winnow/src/combinator/sequence.rs @@ -0,0 +1,164 @@ +use crate::error::ParserError; +use crate::stream::Stream; +use crate::trace::trace; +use crate::*; + +/// Sequence two parsers, only returning the output from the second. +/// +/// # Arguments +/// * `first` The opening parser. +/// * `second` The second parser to get object. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed}; +/// # use winnow::prelude::*; +/// # use winnow::error::Needed::Size; +/// use winnow::combinator::preceded; +/// use winnow::token::tag; +/// +/// let mut parser = preceded("abc", "efg"); +/// +/// assert_eq!(parser.parse_peek("abcefg"), Ok(("", "efg"))); +/// assert_eq!(parser.parse_peek("abcefghij"), Ok(("hij", "efg"))); +/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag)))); +/// ``` +#[doc(alias = "ignore_then")] +pub fn preceded<I, O1, O2, E: ParserError<I>, F, G>( + mut first: F, + mut second: G, +) -> impl Parser<I, O2, E> +where + I: Stream, + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, +{ + trace("preceded", move |input: &mut I| { + let _ = first.parse_next(input)?; + second.parse_next(input) + }) +} + +/// Sequence two parsers, only returning the output of the first. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `second` The second parser to match an object. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed}; +/// # use winnow::prelude::*; +/// # use winnow::error::Needed::Size; +/// use winnow::combinator::terminated; +/// use winnow::token::tag; +/// +/// let mut parser = terminated("abc", "efg"); +/// +/// assert_eq!(parser.parse_peek("abcefg"), Ok(("", "abc"))); +/// assert_eq!(parser.parse_peek("abcefghij"), Ok(("hij", "abc"))); +/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag)))); +/// ``` +#[doc(alias = "then_ignore")] +pub fn terminated<I, O1, O2, E: ParserError<I>, F, G>( + mut first: F, + mut second: G, +) -> impl Parser<I, O1, E> +where + I: Stream, + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, +{ + trace("terminated", move |input: &mut I| { + let o1 = first.parse_next(input)?; + second.parse_next(input).map(|_| o1) + }) +} + +/// Sequence three parsers, only returning the values of the first and third. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `sep` The separator parser to apply. +/// * `second` The second parser to apply. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed}; +/// # use winnow::error::Needed::Size; +/// # use winnow::prelude::*; +/// use winnow::combinator::separated_pair; +/// use winnow::token::tag; +/// +/// let mut parser = separated_pair("abc", "|", "efg"); +/// +/// assert_eq!(parser.parse_peek("abc|efg"), Ok(("", ("abc", "efg")))); +/// assert_eq!(parser.parse_peek("abc|efghij"), Ok(("hij", ("abc", "efg")))); +/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag)))); +/// ``` +pub fn separated_pair<I, O1, O2, O3, E: ParserError<I>, F, G, H>( + mut first: F, + mut sep: G, + mut second: H, +) -> impl Parser<I, (O1, O3), E> +where + I: Stream, + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, + H: Parser<I, O3, E>, +{ + trace("separated_pair", move |input: &mut I| { + let o1 = first.parse_next(input)?; + let _ = sep.parse_next(input)?; + second.parse_next(input).map(|o2| (o1, o2)) + }) +} + +/// Sequence three parsers, only returning the output of the second. +/// +/// # Arguments +/// * `first` The first parser to apply and discard. +/// * `second` The second parser to apply. +/// * `third` The third parser to apply and discard. +/// +/// # Example +/// +/// ```rust +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed}; +/// # use winnow::error::Needed::Size; +/// # use winnow::prelude::*; +/// use winnow::combinator::delimited; +/// use winnow::token::tag; +/// +/// let mut parser = delimited("(", "abc", ")"); +/// +/// assert_eq!(parser.parse_peek("(abc)"), Ok(("", "abc"))); +/// assert_eq!(parser.parse_peek("(abc)def"), Ok(("def", "abc"))); +/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag)))); +/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag)))); +/// ``` +#[doc(alias = "between")] +#[doc(alias = "padded")] +pub fn delimited<I, O1, O2, O3, E: ParserError<I>, F, G, H>( + mut first: F, + mut second: G, + mut third: H, +) -> impl Parser<I, O2, E> +where + I: Stream, + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, + H: Parser<I, O3, E>, +{ + trace("delimited", move |input: &mut I| { + let _ = first.parse_next(input)?; + let o2 = second.parse_next(input)?; + third.parse_next(input).map(|_| o2) + }) +} diff --git a/vendor/winnow/src/combinator/tests.rs b/vendor/winnow/src/combinator/tests.rs new file mode 100644 index 0000000..9d2b49d --- /dev/null +++ b/vendor/winnow/src/combinator/tests.rs @@ -0,0 +1,1292 @@ +use super::*; + +use crate::ascii::digit1 as digit; +use crate::binary::u16; +use crate::binary::u8; +use crate::binary::Endianness; +use crate::error::ErrMode; +use crate::error::ErrorKind; +use crate::error::InputError; +use crate::error::Needed; +use crate::error::ParserError; +use crate::stream::Stream; +use crate::token::take; +use crate::unpeek; +use crate::IResult; +use crate::PResult; +use crate::Parser; +use crate::Partial; + +#[cfg(feature = "alloc")] +use crate::lib::std::vec::Vec; + +macro_rules! assert_parse( + ($left: expr, $right: expr) => { + let res: $crate::IResult<_, _, InputError<_>> = $left; + assert_eq!(res, $right); + }; +); + +#[test] +fn eof_on_slices() { + let not_over: &[u8] = &b"Hello, world!"[..]; + let is_over: &[u8] = &b""[..]; + + let res_not_over = eof.parse_peek(not_over); + assert_parse!( + res_not_over, + Err(ErrMode::Backtrack(error_position!( + ¬_over, + ErrorKind::Eof + ))) + ); + + let res_over = eof.parse_peek(is_over); + assert_parse!(res_over, Ok((is_over, is_over))); +} + +#[test] +fn eof_on_strs() { + let not_over: &str = "Hello, world!"; + let is_over: &str = ""; + + let res_not_over = eof.parse_peek(not_over); + assert_parse!( + res_not_over, + Err(ErrMode::Backtrack(error_position!( + ¬_over, + ErrorKind::Eof + ))) + ); + + let res_over = eof.parse_peek(is_over); + assert_parse!(res_over, Ok((is_over, is_over))); +} + +#[test] +fn rest_on_slices() { + let input: &[u8] = &b"Hello, world!"[..]; + let empty: &[u8] = &b""[..]; + assert_parse!(rest.parse_peek(input), Ok((empty, input))); +} + +#[test] +fn rest_on_strs() { + let input: &str = "Hello, world!"; + let empty: &str = ""; + assert_parse!(rest.parse_peek(input), Ok((empty, input))); +} + +#[test] +fn rest_len_on_slices() { + let input: &[u8] = &b"Hello, world!"[..]; + assert_parse!(rest_len.parse_peek(input), Ok((input, input.len()))); +} + +use crate::lib::std::convert::From; +impl From<u32> for CustomError { + fn from(_: u32) -> Self { + CustomError + } +} + +impl<I> ParserError<I> for CustomError { + fn from_error_kind(_: &I, _: ErrorKind) -> Self { + CustomError + } + + fn append(self, _: &I, _: ErrorKind) -> Self { + CustomError + } +} + +struct CustomError; +#[allow(dead_code)] +fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> { + //fix_error!(input, CustomError<_>, alphanumeric) + crate::ascii::alphanumeric1.parse_peek(input) +} + +#[test] +fn test_parser_flat_map() { + let input: &[u8] = &[3, 100, 101, 102, 103, 104][..]; + assert_parse!( + u8.flat_map(take).parse_peek(input), + Ok((&[103, 104][..], &[100, 101, 102][..])) + ); +} + +#[allow(dead_code)] +fn test_closure_compiles_195(input: &[u8]) -> IResult<&[u8], ()> { + u8.flat_map(|num| repeat(num as usize, u16(Endianness::Big))) + .parse_peek(input) +} + +#[test] +fn test_parser_verify_map() { + let input: &[u8] = &[50][..]; + assert_parse!( + u8.verify_map(|u| if u < 20 { Some(u) } else { None }) + .parse_peek(input), + Err(ErrMode::Backtrack(InputError::new( + &[50][..], + ErrorKind::Verify + ))) + ); + assert_parse!( + u8.verify_map(|u| if u > 20 { Some(u) } else { None }) + .parse_peek(input), + Ok((&[][..], 50)) + ); +} + +#[test] +fn test_parser_map_parser() { + let input: &[u8] = &[100, 101, 102, 103, 104][..]; + assert_parse!( + take(4usize).and_then(take(2usize)).parse_peek(input), + Ok((&[104][..], &[100, 101][..])) + ); +} + +#[test] +#[cfg(feature = "std")] +fn test_parser_into() { + use crate::error::InputError; + use crate::token::take; + + let mut parser = take::<_, _, InputError<_>>(3u8).output_into(); + let result: IResult<&[u8], Vec<u8>> = parser.parse_peek(&b"abcdefg"[..]); + + assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99]))); +} + +#[test] +fn opt_test() { + fn opt_abcd(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Option<&[u8]>> { + opt("abcd").parse_peek(i) + } + + let a = &b"abcdef"[..]; + let b = &b"bcdefg"[..]; + let c = &b"ab"[..]; + assert_eq!( + opt_abcd(Partial::new(a)), + Ok((Partial::new(&b"ef"[..]), Some(&b"abcd"[..]))) + ); + assert_eq!( + opt_abcd(Partial::new(b)), + Ok((Partial::new(&b"bcdefg"[..]), None)) + ); + assert_eq!( + opt_abcd(Partial::new(c)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); +} + +#[test] +fn peek_test() { + fn peek_tag(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> { + peek("abcd").parse_peek(i) + } + + assert_eq!( + peek_tag(Partial::new(&b"abcdef"[..])), + Ok((Partial::new(&b"abcdef"[..]), &b"abcd"[..])) + ); + assert_eq!( + peek_tag(Partial::new(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + peek_tag(Partial::new(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); +} + +#[test] +fn not_test() { + fn not_aaa(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, ()> { + not("aaa").parse_peek(i) + } + + assert_eq!( + not_aaa(Partial::new(&b"aaa"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"aaa"[..]), + ErrorKind::Not + ))) + ); + assert_eq!( + not_aaa(Partial::new(&b"aa"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + not_aaa(Partial::new(&b"abcd"[..])), + Ok((Partial::new(&b"abcd"[..]), ())) + ); +} + +#[test] +fn test_parser_verify() { + use crate::token::take; + + fn test(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> { + take(5u8) + .verify(|slice: &[u8]| slice[0] == b'a') + .parse_peek(i) + } + assert_eq!( + test(Partial::new(&b"bcd"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + test(Partial::new(&b"bcdefg"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"bcdefg"[..]), + ErrorKind::Verify + ))) + ); + assert_eq!( + test(Partial::new(&b"abcdefg"[..])), + Ok((Partial::new(&b"fg"[..]), &b"abcde"[..])) + ); +} + +#[test] +#[allow(unused)] +fn test_parser_verify_ref() { + use crate::token::take; + + let mut parser1 = take(3u8).verify(|s: &[u8]| s == &b"abc"[..]); + + assert_eq!( + parser1.parse_peek(&b"abcd"[..]), + Ok((&b"d"[..], &b"abc"[..])) + ); + assert_eq!( + parser1.parse_peek(&b"defg"[..]), + Err(ErrMode::Backtrack(InputError::new( + &b"defg"[..], + ErrorKind::Verify + ))) + ); + + fn parser2(i: &[u8]) -> IResult<&[u8], u32> { + crate::binary::be_u32 + .verify(|val: &u32| *val < 3) + .parse_peek(i) + } +} + +#[test] +#[cfg(feature = "alloc")] +fn test_parser_verify_alloc() { + use crate::token::take; + let mut parser1 = take(3u8) + .map(|s: &[u8]| s.to_vec()) + .verify(|s: &[u8]| s == &b"abc"[..]); + + assert_eq!( + parser1.parse_peek(&b"abcd"[..]), + Ok((&b"d"[..], b"abc".to_vec())) + ); + assert_eq!( + parser1.parse_peek(&b"defg"[..]), + Err(ErrMode::Backtrack(InputError::new( + &b"defg"[..], + ErrorKind::Verify + ))) + ); +} + +#[test] +fn fail_test() { + let a = "string"; + let b = "another string"; + + assert_eq!( + fail::<_, &str, _>.parse_peek(a), + Err(ErrMode::Backtrack(InputError::new(a, ErrorKind::Fail))) + ); + assert_eq!( + fail::<_, &str, _>.parse_peek(b), + Err(ErrMode::Backtrack(InputError::new(b, ErrorKind::Fail))) + ); +} + +#[test] +fn complete() { + fn err_test(i: &[u8]) -> IResult<&[u8], &[u8]> { + let (i, _) = "ijkl".parse_peek(i)?; + "mnop".parse_peek(i) + } + let a = &b"ijklmn"[..]; + + let res_a = err_test(a); + assert_eq!( + res_a, + Err(ErrMode::Backtrack(error_position!( + &&b"mn"[..], + ErrorKind::Tag + ))) + ); +} + +#[test] +fn separated_pair_test() { + #[allow(clippy::type_complexity)] + fn sep_pair_abc_def(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, (&[u8], &[u8])> { + separated_pair("abc", ",", "def").parse_peek(i) + } + + assert_eq!( + sep_pair_abc_def(Partial::new(&b"abc,defghijkl"[..])), + Ok((Partial::new(&b"ghijkl"[..]), (&b"abc"[..], &b"def"[..]))) + ); + assert_eq!( + sep_pair_abc_def(Partial::new(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + sep_pair_abc_def(Partial::new(&b"abc,d"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + sep_pair_abc_def(Partial::new(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + sep_pair_abc_def(Partial::new(&b"xxx,def"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx,def"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + sep_pair_abc_def(Partial::new(&b"abc,xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); +} + +#[test] +fn preceded_test() { + fn preceded_abcd_efgh(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> { + preceded("abcd", "efgh").parse_peek(i) + } + + assert_eq!( + preceded_abcd_efgh(Partial::new(&b"abcdefghijkl"[..])), + Ok((Partial::new(&b"ijkl"[..]), &b"efgh"[..])) + ); + assert_eq!( + preceded_abcd_efgh(Partial::new(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + preceded_abcd_efgh(Partial::new(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_eq!( + preceded_abcd_efgh(Partial::new(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + preceded_abcd_efgh(Partial::new(&b"xxxxdef"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxxxdef"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + preceded_abcd_efgh(Partial::new(&b"abcdxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); +} + +#[test] +fn terminated_test() { + fn terminated_abcd_efgh(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> { + terminated("abcd", "efgh").parse_peek(i) + } + + assert_eq!( + terminated_abcd_efgh(Partial::new(&b"abcdefghijkl"[..])), + Ok((Partial::new(&b"ijkl"[..]), &b"abcd"[..])) + ); + assert_eq!( + terminated_abcd_efgh(Partial::new(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + terminated_abcd_efgh(Partial::new(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_eq!( + terminated_abcd_efgh(Partial::new(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + terminated_abcd_efgh(Partial::new(&b"xxxxdef"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxxxdef"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + terminated_abcd_efgh(Partial::new(&b"abcdxxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxxx"[..]), + ErrorKind::Tag + ))) + ); +} + +#[test] +fn delimited_test() { + fn delimited_abc_def_ghi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> { + delimited("abc", "def", "ghi").parse_peek(i) + } + + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"abcdefghijkl"[..])), + Ok((Partial::new(&b"jkl"[..]), &b"def"[..])) + ); + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"abcdefgh"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"xxxdefghi"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxxdefghi"[..]), + ErrorKind::Tag + ),)) + ); + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"abcxxxghi"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxxghi"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + delimited_abc_def_ghi(Partial::new(&b"abcdefxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); +} + +#[cfg(feature = "alloc")] +#[test] +fn alt_test() { + #[cfg(feature = "alloc")] + use crate::{ + error::ParserError, + lib::std::{ + fmt::Debug, + string::{String, ToString}, + }, + }; + + #[cfg(feature = "alloc")] + #[derive(Debug, Clone, Eq, PartialEq)] + pub struct ErrorStr(String); + + #[cfg(feature = "alloc")] + impl From<u32> for ErrorStr { + fn from(i: u32) -> Self { + ErrorStr(format!("custom error code: {}", i)) + } + } + + #[cfg(feature = "alloc")] + impl<'a> From<&'a str> for ErrorStr { + fn from(i: &'a str) -> Self { + ErrorStr(format!("custom error message: {}", i)) + } + } + + #[cfg(feature = "alloc")] + impl<I: Debug> ParserError<I> for ErrorStr { + fn from_error_kind(input: &I, kind: ErrorKind) -> Self { + ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind)) + } + + fn append(self, input: &I, kind: ErrorKind) -> Self { + ErrorStr(format!( + "custom error message: ({:?}, {:?}) - {:?}", + input, kind, self + )) + } + } + + fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Ok(input.peek_finish()) + } + + #[allow(unused_variables)] + fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Err(ErrMode::Backtrack(ErrorStr("abcd".to_string()))) + } + + fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Ok((input, &b""[..])) + } + + fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((unpeek(dont_work), unpeek(dont_work))).parse_peek(i) + } + fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((unpeek(dont_work), unpeek(work))).parse_peek(i) + } + fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt(( + unpeek(dont_work), + unpeek(dont_work), + unpeek(work2), + unpeek(dont_work), + )) + .parse_peek(i) + } + //named!(alt1, alt!(dont_work | dont_work)); + //named!(alt2, alt!(dont_work | work)); + //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work)); + + let a = &b"abcd"[..]; + assert_eq!( + alt1(a), + Err(ErrMode::Backtrack(error_node_position!( + &a, + ErrorKind::Alt, + ErrorStr("abcd".to_string()) + ))) + ); + assert_eq!(alt2(a), Ok((&b""[..], a))); + assert_eq!(alt3(a), Ok((a, &b""[..]))); + + fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> { + alt(("abcd", "efgh")).parse_peek(i) + } + let b = &b"efgh"[..]; + assert_eq!(alt4(a), Ok((&b""[..], a))); + assert_eq!(alt4(b), Ok((&b""[..], b))); +} + +#[test] +fn alt_incomplete() { + fn alt1(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> { + alt(("a", "bc", "def")).parse_peek(i) + } + + let a = &b""[..]; + assert_eq!( + alt1(Partial::new(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + let a = &b"b"[..]; + assert_eq!( + alt1(Partial::new(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + let a = &b"bcd"[..]; + assert_eq!( + alt1(Partial::new(a)), + Ok((Partial::new(&b"d"[..]), &b"bc"[..])) + ); + let a = &b"cde"[..]; + assert_eq!( + alt1(Partial::new(a)), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(a), + ErrorKind::Tag + ))) + ); + let a = &b"de"[..]; + assert_eq!( + alt1(Partial::new(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + let a = &b"defg"[..]; + assert_eq!( + alt1(Partial::new(a)), + Ok((Partial::new(&b"g"[..]), &b"def"[..])) + ); +} + +#[test] +fn alt_array() { + fn alt1<'i>(i: &mut &'i [u8]) -> PResult<&'i [u8]> { + alt(["a", "bc", "def"]).parse_next(i) + } + + let i = &b"a"[..]; + assert_eq!(alt1.parse_peek(i), Ok((&b""[..], (&b"a"[..])))); + + let i = &b"bc"[..]; + assert_eq!(alt1.parse_peek(i), Ok((&b""[..], (&b"bc"[..])))); + + let i = &b"defg"[..]; + assert_eq!(alt1.parse_peek(i), Ok((&b"g"[..], (&b"def"[..])))); + + let i = &b"z"[..]; + assert_eq!( + alt1.parse_peek(i), + Err(ErrMode::Backtrack(error_position!(&i, ErrorKind::Tag))) + ); +} + +#[test] +fn permutation_test() { + #[allow(clippy::type_complexity)] + fn perm(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, (&[u8], &[u8], &[u8])> { + permutation(("abcd", "efg", "hi")).parse_peek(i) + } + + let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]); + + let a = &b"abcdefghijk"[..]; + assert_eq!( + perm(Partial::new(a)), + Ok((Partial::new(&b"jk"[..]), expected)) + ); + let b = &b"efgabcdhijk"[..]; + assert_eq!( + perm(Partial::new(b)), + Ok((Partial::new(&b"jk"[..]), expected)) + ); + let c = &b"hiefgabcdjk"[..]; + assert_eq!( + perm(Partial::new(c)), + Ok((Partial::new(&b"jk"[..]), expected)) + ); + + let d = &b"efgxyzabcdefghi"[..]; + assert_eq!( + perm(Partial::new(d)), + Err(ErrMode::Backtrack(error_node_position!( + &Partial::new(&b"efgxyzabcdefghi"[..]), + ErrorKind::Alt, + error_position!(&Partial::new(&b"xyzabcdefghi"[..]), ErrorKind::Tag) + ))) + ); + + let e = &b"efgabc"[..]; + assert_eq!( + perm(Partial::new(e)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn separated0_test() { + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + separated0("abcd", ",").parse_peek(i) + } + fn multi_empty(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + separated0("", ",").parse_peek(i) + } + fn multi_longsep(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + separated0("abcd", "..").parse_peek(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcd,abcdef"[..]; + let c = &b"azerty"[..]; + let d = &b",,abc"[..]; + let e = &b"abcd,abcd,ef"[..]; + let f = &b"abc"[..]; + let g = &b"abcd."[..]; + let h = &b"abcd,abc"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Partial::new(a)), Ok((Partial::new(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Partial::new(b)), Ok((Partial::new(&b"ef"[..]), res2))); + assert_eq!( + multi(Partial::new(c)), + Ok((Partial::new(&b"azerty"[..]), Vec::new())) + ); + let res3 = vec![&b""[..], &b""[..], &b""[..]]; + assert_eq!( + multi_empty(Partial::new(d)), + Ok((Partial::new(&b"abc"[..]), res3)) + ); + let res4 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!( + multi(Partial::new(e)), + Ok((Partial::new(&b",ef"[..]), res4)) + ); + + assert_eq!( + multi(Partial::new(f)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi_longsep(Partial::new(g)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi(Partial::new(h)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +#[cfg_attr(debug_assertions, should_panic)] +fn separated0_empty_sep_test() { + fn empty_sep(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + separated0("abc", "").parse_peek(i) + } + + let i = &b"abcabc"[..]; + + let i_err_pos = &i[3..]; + assert_eq!( + empty_sep(Partial::new(i)), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(i_err_pos), + ErrorKind::Assert + ))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn separated1_test() { + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + separated1("abcd", ",").parse_peek(i) + } + fn multi_longsep(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + separated1("abcd", "..").parse_peek(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcd,abcdef"[..]; + let c = &b"azerty"[..]; + let d = &b"abcd,abcd,ef"[..]; + + let f = &b"abc"[..]; + let g = &b"abcd."[..]; + let h = &b"abcd,abc"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Partial::new(a)), Ok((Partial::new(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Partial::new(b)), Ok((Partial::new(&b"ef"[..]), res2))); + assert_eq!( + multi(Partial::new(c)), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(c), + ErrorKind::Tag + ))) + ); + let res3 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!( + multi(Partial::new(d)), + Ok((Partial::new(&b",ef"[..]), res3)) + ); + + assert_eq!( + multi(Partial::new(f)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi_longsep(Partial::new(g)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi(Partial::new(h)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn repeat0_test() { + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + repeat(0.., "abcd").parse_peek(i) + } + + assert_eq!( + multi(Partial::new(&b"abcdef"[..])), + Ok((Partial::new(&b"ef"[..]), vec![&b"abcd"[..]])) + ); + assert_eq!( + multi(Partial::new(&b"abcdabcdefgh"[..])), + Ok((Partial::new(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!( + multi(Partial::new(&b"azerty"[..])), + Ok((Partial::new(&b"azerty"[..]), Vec::new())) + ); + assert_eq!( + multi(Partial::new(&b"abcdab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + multi(Partial::new(&b"abcd"[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_eq!( + multi(Partial::new(&b""[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +#[cfg_attr(debug_assertions, should_panic)] +fn repeat0_empty_test() { + fn multi_empty(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + repeat(0.., "").parse_peek(i) + } + + assert_eq!( + multi_empty(Partial::new(&b"abcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"abcdef"[..]), + ErrorKind::Assert + ))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn repeat1_test() { + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + repeat(1.., "abcd").parse_peek(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Partial::new(a)), Ok((Partial::new(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!( + multi(Partial::new(b)), + Ok((Partial::new(&b"efgh"[..]), res2)) + ); + assert_eq!( + multi(Partial::new(c)), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(c), + ErrorKind::Tag + ))) + ); + assert_eq!( + multi(Partial::new(d)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn repeat_till_test() { + #[allow(clippy::type_complexity)] + fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> { + repeat_till0("abcd", "efgh").parse_peek(i) + } + + let a = b"abcdabcdefghabcd"; + let b = b"efghabcd"; + let c = b"azerty"; + + let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]); + let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]); + assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a))); + assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b))); + assert_eq!( + multi(&c[..]), + Err(ErrMode::Backtrack(error_node_position!( + &&c[..], + ErrorKind::Many, + error_position!(&&c[..], ErrorKind::Tag) + ))) + ); +} + +#[test] +#[cfg(feature = "std")] +fn infinite_many() { + fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { + println!("input: {:?}", input); + Err(ErrMode::Backtrack(error_position!(&input, ErrorKind::Tag))) + } + + // should not go into an infinite loop + fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + repeat(0.., unpeek(tst)).parse_peek(i) + } + let a = &b"abcdef"[..]; + assert_eq!(multi0(a), Ok((a, Vec::new()))); + + fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + repeat(1.., unpeek(tst)).parse_peek(i) + } + let a = &b"abcdef"[..]; + assert_eq!( + multi1(a), + Err(ErrMode::Backtrack(error_position!(&a, ErrorKind::Tag))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn repeat_test() { + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + repeat(2..=4, "Abcd").parse_peek(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + + assert_eq!( + multi(Partial::new(a)), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"ef"[..]), + ErrorKind::Tag + ))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!( + multi(Partial::new(b)), + Ok((Partial::new(&b"efgh"[..]), res1)) + ); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!( + multi(Partial::new(c)), + Ok((Partial::new(&b"efgh"[..]), res2)) + ); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!( + multi(Partial::new(d)), + Ok((Partial::new(&b"Abcdefgh"[..]), res3)) + ); + assert_eq!( + multi(Partial::new(e)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn count_test() { + const TIMES: usize = 2; + fn cnt_2(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + repeat(TIMES, "abc").parse_peek(i) + } + + assert_eq!( + cnt_2(Partial::new(&b"abcabcabcdef"[..])), + Ok((Partial::new(&b"abcdef"[..]), vec![&b"abc"[..], &b"abc"[..]])) + ); + assert_eq!( + cnt_2(Partial::new(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + cnt_2(Partial::new(&b"abcab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + cnt_2(Partial::new(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + cnt_2(Partial::new(&b"xxxabcabcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxxabcabcdef"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + cnt_2(Partial::new(&b"abcxxxabcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"xxxabcdef"[..]), + ErrorKind::Tag + ))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn count_zero() { + const TIMES: usize = 0; + fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + repeat(TIMES, "abc").parse_peek(i) + } + + let done = &b"abcabcabcdef"[..]; + let parsed_done = Vec::new(); + let rest = done; + let incomplete_1 = &b"ab"[..]; + let parsed_incompl_1 = Vec::new(); + let incomplete_2 = &b"abcab"[..]; + let parsed_incompl_2 = Vec::new(); + let error = &b"xxx"[..]; + let error_remain = &b"xxx"[..]; + let parsed_err = Vec::new(); + let error_1 = &b"xxxabcabcdef"[..]; + let parsed_err_1 = Vec::new(); + let error_1_remain = &b"xxxabcabcdef"[..]; + let error_2 = &b"abcxxxabcdef"[..]; + let parsed_err_2 = Vec::new(); + let error_2_remain = &b"abcxxxabcdef"[..]; + + assert_eq!(counter_2(done), Ok((rest, parsed_done))); + assert_eq!( + counter_2(incomplete_1), + Ok((incomplete_1, parsed_incompl_1)) + ); + assert_eq!( + counter_2(incomplete_2), + Ok((incomplete_2, parsed_incompl_2)) + ); + assert_eq!(counter_2(error), Ok((error_remain, parsed_err))); + assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1))); + assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2))); +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct NilError; + +impl<I> From<(I, ErrorKind)> for NilError { + fn from(_: (I, ErrorKind)) -> Self { + NilError + } +} + +impl<I> ParserError<I> for NilError { + fn from_error_kind(_: &I, _: ErrorKind) -> NilError { + NilError + } + fn append(self, _: &I, _: ErrorKind) -> NilError { + NilError + } +} + +#[test] +#[cfg(feature = "alloc")] +fn fold_repeat0_test() { + fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> { + acc.push(item); + acc + } + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + fold_repeat(0.., "abcd", Vec::new, fold_into_vec).parse_peek(i) + } + + assert_eq!( + multi(Partial::new(&b"abcdef"[..])), + Ok((Partial::new(&b"ef"[..]), vec![&b"abcd"[..]])) + ); + assert_eq!( + multi(Partial::new(&b"abcdabcdefgh"[..])), + Ok((Partial::new(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!( + multi(Partial::new(&b"azerty"[..])), + Ok((Partial::new(&b"azerty"[..]), Vec::new())) + ); + assert_eq!( + multi(Partial::new(&b"abcdab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + multi(Partial::new(&b"abcd"[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_eq!( + multi(Partial::new(&b""[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +#[cfg_attr(debug_assertions, should_panic)] +fn fold_repeat0_empty_test() { + fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> { + acc.push(item); + acc + } + fn multi_empty(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + fold_repeat(0.., "", Vec::new, fold_into_vec).parse_peek(i) + } + + assert_eq!( + multi_empty(Partial::new(&b"abcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"abcdef"[..]), + ErrorKind::Assert + ))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn fold_repeat1_test() { + fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> { + acc.push(item); + acc + } + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + fold_repeat(1.., "abcd", Vec::new, fold_into_vec).parse_peek(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Partial::new(a)), Ok((Partial::new(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!( + multi(Partial::new(b)), + Ok((Partial::new(&b"efgh"[..]), res2)) + ); + assert_eq!( + multi(Partial::new(c)), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(c), + ErrorKind::Many + ))) + ); + assert_eq!( + multi(Partial::new(d)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn fold_repeat_test() { + fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> { + acc.push(item); + acc + } + fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> { + fold_repeat(2..=4, "Abcd", Vec::new, fold_into_vec).parse_peek(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + + assert_eq!( + multi(Partial::new(a)), + Err(ErrMode::Backtrack(error_position!( + &Partial::new(&b"ef"[..]), + ErrorKind::Tag + ))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!( + multi(Partial::new(b)), + Ok((Partial::new(&b"efgh"[..]), res1)) + ); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!( + multi(Partial::new(c)), + Ok((Partial::new(&b"efgh"[..]), res2)) + ); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!( + multi(Partial::new(d)), + Ok((Partial::new(&b"Abcdefgh"[..]), res3)) + ); + assert_eq!( + multi(Partial::new(e)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); +} + +#[test] +fn repeat0_count_test() { + fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> { + repeat(0.., (digit, ",")).parse_peek(i) + } + + assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1))); + + assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); + + assert_eq!( + count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), + Ok((&b"junk"[..], 10)) + ); + + assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0))); +} + +#[test] +fn repeat1_count_test() { + fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> { + repeat(1.., (digit, ",")).parse_peek(i) + } + + assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); + + assert_eq!( + count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), + Ok((&b"junk"[..], 10)) + ); + + assert_eq!( + count1_nums(&b"hello"[..]), + Err(ErrMode::Backtrack(error_position!( + &&b"hello"[..], + ErrorKind::Slice + ))) + ); +} |