summaryrefslogtreecommitdiffstats
path: root/vendor/winnow/src/combinator
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
commit2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch)
tree033cc839730fda84ff08db877037977be94e5e3a /vendor/winnow/src/combinator
parentInitial commit. (diff)
downloadcargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.tar.xz
cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.zip
Adding upstream version 0.70.1+ds1.upstream/0.70.1+ds1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/winnow/src/combinator')
-rw-r--r--vendor/winnow/src/combinator/branch.rs297
-rw-r--r--vendor/winnow/src/combinator/core.rs491
-rw-r--r--vendor/winnow/src/combinator/mod.rs172
-rw-r--r--vendor/winnow/src/combinator/multi.rs945
-rw-r--r--vendor/winnow/src/combinator/parser.rs863
-rw-r--r--vendor/winnow/src/combinator/sequence.rs164
-rw-r--r--vendor/winnow/src/combinator/tests.rs1292
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!(
+ &not_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!(
+ &not_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
+ )))
+ );
+}