summaryrefslogtreecommitdiffstats
path: root/vendor/winnow-0.4.7/src/token
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /vendor/winnow-0.4.7/src/token
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/winnow-0.4.7/src/token')
-rw-r--r--vendor/winnow-0.4.7/src/token/mod.rs1009
-rw-r--r--vendor/winnow-0.4.7/src/token/tests.rs700
2 files changed, 1709 insertions, 0 deletions
diff --git a/vendor/winnow-0.4.7/src/token/mod.rs b/vendor/winnow-0.4.7/src/token/mod.rs
new file mode 100644
index 000000000..6f99dfa8d
--- /dev/null
+++ b/vendor/winnow-0.4.7/src/token/mod.rs
@@ -0,0 +1,1009 @@
+//! Parsers extracting tokens from the stream
+
+#[cfg(test)]
+mod tests;
+
+use crate::error::ErrMode;
+use crate::error::ErrorKind;
+use crate::error::Needed;
+use crate::error::ParseError;
+use crate::lib::std::result::Result::Ok;
+use crate::stream::Range;
+use crate::stream::{
+ split_at_offset1_complete, split_at_offset1_partial, split_at_offset_complete,
+ split_at_offset_partial, Compare, CompareResult, ContainsToken, FindSlice, SliceLen, Stream,
+};
+use crate::stream::{StreamIsPartial, ToUsize};
+use crate::trace::trace;
+use crate::IResult;
+use crate::Parser;
+
+/// Matches one token
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Partial version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{token::any, error::ErrMode, error::{Error, ErrorKind}};
+/// # use winnow::prelude::*;
+/// fn parser(input: &str) -> IResult<&str, char> {
+/// any.parse_next(input)
+/// }
+///
+/// assert_eq!(parser("abc"), Ok(("bc",'a')));
+/// assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Token))));
+/// ```
+///
+/// ```rust
+/// # use winnow::{token::any, error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// assert_eq!(any::<_, Error<_>>.parse_next(Partial::new("abc")), Ok((Partial::new("bc"),'a')));
+/// assert_eq!(any::<_, Error<_>>.parse_next(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+#[doc(alias = "token")]
+pub fn any<I, E: ParseError<I>>(input: I) -> IResult<I, <I as Stream>::Token, E>
+where
+ I: StreamIsPartial,
+ I: Stream,
+{
+ trace("any", move |input: I| {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ any_::<_, _, true>(input)
+ } else {
+ any_::<_, _, true>(input)
+ }
+ })
+ .parse_next(input)
+}
+
+fn any_<I, E: ParseError<I>, const PARTIAL: bool>(input: I) -> IResult<I, <I as Stream>::Token, E>
+where
+ I: StreamIsPartial,
+ I: Stream,
+{
+ input.next_token().ok_or_else(|| {
+ if PARTIAL && input.is_partial() {
+ ErrMode::Incomplete(Needed::new(1))
+ } else {
+ ErrMode::from_error_kind(input, ErrorKind::Token)
+ }
+ })
+}
+
+/// Recognizes a literal
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument
+///
+/// It will return `Err(ErrMode::Backtrack(Error::new(_, ErrorKind::Tag)))` if the input doesn't match the pattern
+///
+/// **Note:** [`Parser`][crate::Parser] is implemented for strings and byte strings as a convenience (complete
+/// only)
+///
+/// # Example
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// use winnow::token::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// "Hello".parse_next(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("Something"), Err(ErrMode::Backtrack(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Tag))));
+/// ```
+///
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::Partial;
+/// use winnow::token::tag;
+///
+/// fn parser(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// "Hello".parse_next(s)
+/// }
+///
+/// assert_eq!(parser(Partial::new("Hello, World!")), Ok((Partial::new(", World!"), "Hello")));
+/// assert_eq!(parser(Partial::new("Something")), Err(ErrMode::Backtrack(Error::new(Partial::new("Something"), ErrorKind::Tag))));
+/// assert_eq!(parser(Partial::new("S")), Err(ErrMode::Backtrack(Error::new(Partial::new("S"), ErrorKind::Tag))));
+/// assert_eq!(parser(Partial::new("H")), Err(ErrMode::Incomplete(Needed::new(4))));
+/// ```
+#[inline(always)]
+#[doc(alias = "literal")]
+#[doc(alias = "bytes")]
+#[doc(alias = "just")]
+pub fn tag<T, I, Error: ParseError<I>>(tag: T) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + Compare<T>,
+ T: SliceLen + Clone,
+{
+ trace("tag", move |i: I| {
+ let t = tag.clone();
+ if <I as StreamIsPartial>::is_partial_supported() {
+ tag_::<_, _, _, true>(i, t)
+ } else {
+ tag_::<_, _, _, false>(i, t)
+ }
+ })
+}
+
+fn tag_<T, I, Error: ParseError<I>, const PARTIAL: bool>(
+ i: I,
+ t: T,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + Compare<T>,
+ T: SliceLen,
+{
+ let tag_len = t.slice_len();
+ match i.compare(t) {
+ CompareResult::Ok => Ok(i.next_slice(tag_len)),
+ CompareResult::Incomplete if PARTIAL && i.is_partial() => {
+ Err(ErrMode::Incomplete(Needed::new(tag_len - i.eof_offset())))
+ }
+ CompareResult::Incomplete | CompareResult::Error => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(ErrMode::from_error_kind(i, e))
+ }
+ }
+}
+
+/// Recognizes a case insensitive literal.
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument with no regard to case.
+///
+/// It will return `Err(ErrMode::Backtrack(Error::new(_, ErrorKind::Tag)))` if the input doesn't match the pattern.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::tag_no_case;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag_no_case("hello").parse_next(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
+/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
+/// assert_eq!(parser("Something"), Err(ErrMode::Backtrack(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Tag))));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::tag_no_case;
+///
+/// fn parser(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// tag_no_case("hello").parse_next(s)
+/// }
+///
+/// assert_eq!(parser(Partial::new("Hello, World!")), Ok((Partial::new(", World!"), "Hello")));
+/// assert_eq!(parser(Partial::new("hello, World!")), Ok((Partial::new(", World!"), "hello")));
+/// assert_eq!(parser(Partial::new("HeLlO, World!")), Ok((Partial::new(", World!"), "HeLlO")));
+/// assert_eq!(parser(Partial::new("Something")), Err(ErrMode::Backtrack(Error::new(Partial::new("Something"), ErrorKind::Tag))));
+/// assert_eq!(parser(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(5))));
+/// ```
+#[inline(always)]
+#[doc(alias = "literal")]
+#[doc(alias = "bytes")]
+#[doc(alias = "just")]
+pub fn tag_no_case<T, I, Error: ParseError<I>>(
+ tag: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + Compare<T>,
+ T: SliceLen + Clone,
+{
+ trace("tag_no_case", move |i: I| {
+ let t = tag.clone();
+ if <I as StreamIsPartial>::is_partial_supported() {
+ tag_no_case_::<_, _, _, true>(i, t)
+ } else {
+ tag_no_case_::<_, _, _, false>(i, t)
+ }
+ })
+}
+
+fn tag_no_case_<T, I, Error: ParseError<I>, const PARTIAL: bool>(
+ i: I,
+ t: T,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + Compare<T>,
+ T: SliceLen,
+{
+ let tag_len = t.slice_len();
+
+ match (i).compare_no_case(t) {
+ CompareResult::Ok => Ok(i.next_slice(tag_len)),
+ CompareResult::Incomplete if PARTIAL && i.is_partial() => {
+ Err(ErrMode::Incomplete(Needed::new(tag_len - i.eof_offset())))
+ }
+ CompareResult::Incomplete | CompareResult::Error => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(ErrMode::from_error_kind(i, e))
+ }
+ }
+}
+
+/// Recognize a token that matches the [pattern][ContainsToken]
+///
+/// **Note:** [`Parser`][crate::Parser] is implemented as a convenience (complete
+/// only) for
+/// - `u8`
+/// - `char`
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Partial version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error};
+/// # use winnow::token::one_of;
+/// assert_eq!(one_of::<_, _, Error<_>>("abc").parse_next("b"), Ok(("", 'b')));
+/// assert_eq!(one_of::<_, _, Error<_>>("a").parse_next("bc"), Err(ErrMode::Backtrack(Error::new("bc", ErrorKind::Verify))));
+/// assert_eq!(one_of::<_, _, Error<_>>("a").parse_next(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Token))));
+///
+/// fn parser_fn(i: &str) -> IResult<&str, char> {
+/// one_of(|c| c == 'a' || c == 'b').parse_next(i)
+/// }
+/// assert_eq!(parser_fn("abc"), Ok(("bc", 'a')));
+/// assert_eq!(parser_fn("cd"), Err(ErrMode::Backtrack(Error::new("cd", ErrorKind::Verify))));
+/// assert_eq!(parser_fn(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Token))));
+/// ```
+///
+/// ```
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::Partial;
+/// # use winnow::token::one_of;
+/// assert_eq!(one_of::<_, _, Error<_>>("abc").parse_next(Partial::new("b")), Ok((Partial::new(""), 'b')));
+/// assert_eq!(one_of::<_, _, Error<_>>("a").parse_next(Partial::new("bc")), Err(ErrMode::Backtrack(Error::new(Partial::new("bc"), ErrorKind::Verify))));
+/// assert_eq!(one_of::<_, _, Error<_>>("a").parse_next(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+///
+/// fn parser_fn(i: Partial<&str>) -> IResult<Partial<&str>, char> {
+/// one_of(|c| c == 'a' || c == 'b').parse_next(i)
+/// }
+/// assert_eq!(parser_fn(Partial::new("abc")), Ok((Partial::new("bc"), 'a')));
+/// assert_eq!(parser_fn(Partial::new("cd")), Err(ErrMode::Backtrack(Error::new(Partial::new("cd"), ErrorKind::Verify))));
+/// assert_eq!(parser_fn(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+#[doc(alias = "char")]
+#[doc(alias = "token")]
+#[doc(alias = "satisfy")]
+pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, <I as Stream>::Token, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ <I as Stream>::Token: Copy,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ trace(
+ "one_of",
+ any.verify(move |t: &<I as Stream>::Token| list.contains_token(*t)),
+ )
+}
+
+/// Recognize a token that does not match the [pattern][ContainsToken]
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Partial version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error};
+/// # use winnow::prelude::*;
+/// # use winnow::token::none_of;
+/// assert_eq!(none_of::<_, _, Error<_>>("abc").parse_next("z"), Ok(("", 'z')));
+/// assert_eq!(none_of::<_, _, Error<_>>("ab").parse_next("a"), Err(ErrMode::Backtrack(Error::new("a", ErrorKind::Verify))));
+/// assert_eq!(none_of::<_, _, Error<_>>("a").parse_next(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Token))));
+/// ```
+///
+/// ```
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// # use winnow::token::none_of;
+/// assert_eq!(none_of::<_, _, Error<_>>("abc").parse_next(Partial::new("z")), Ok((Partial::new(""), 'z')));
+/// assert_eq!(none_of::<_, _, Error<_>>("ab").parse_next(Partial::new("a")), Err(ErrMode::Backtrack(Error::new(Partial::new("a"), ErrorKind::Verify))));
+/// assert_eq!(none_of::<_, _, Error<_>>("a").parse_next(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, <I as Stream>::Token, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ <I as Stream>::Token: Copy,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ trace(
+ "none_of",
+ any.verify(move |t: &<I as Stream>::Token| !list.contains_token(*t)),
+ )
+}
+
+/// Recognize the longest (m <= len <= n) input slice that matches the [pattern][ContainsToken]
+///
+/// It will return an `ErrMode::Backtrack(Error::new(_, ErrorKind::Slice))` if the pattern wasn't met or is out
+/// of range (m <= len <= n).
+///
+/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short.
+///
+/// To recognize a series of tokens, use [`repeat`][crate::combinator::repeat] to [`Accumulate`][crate::stream::Accumulate] into a `()` and then [`Parser::recognize`][crate::Parser::recognize].
+///
+/// # Example
+///
+/// Zero or more tokens:
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take_while;
+/// use winnow::stream::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while(0.., AsChar::is_alpha).parse_next(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
+/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_while;
+/// use winnow::stream::AsChar;
+///
+/// fn alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+/// take_while(0.., AsChar::is_alpha).parse_next(s)
+/// }
+///
+/// assert_eq!(alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
+/// assert_eq!(alpha(Partial::new(b"12345")), Ok((Partial::new(&b"12345"[..]), &b""[..])));
+/// assert_eq!(alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(alpha(Partial::new(b"")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+///
+/// One or more tokens:
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take_while;
+/// use winnow::stream::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while(1.., AsChar::is_alpha).parse_next(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"12345"), Err(ErrMode::Backtrack(Error::new(&b"12345"[..], ErrorKind::Slice))));
+///
+/// fn hex(s: &str) -> IResult<&str, &str> {
+/// take_while(1.., "1234567890ABCDEF").parse_next(s)
+/// }
+///
+/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
+/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
+/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
+/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
+/// assert_eq!(hex(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice))));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_while;
+/// use winnow::stream::AsChar;
+///
+/// fn alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+/// take_while(1.., AsChar::is_alpha).parse_next(s)
+/// }
+///
+/// assert_eq!(alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
+/// assert_eq!(alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(alpha(Partial::new(b"12345")), Err(ErrMode::Backtrack(Error::new(Partial::new(&b"12345"[..]), ErrorKind::Slice))));
+///
+/// fn hex(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take_while(1.., "1234567890ABCDEF").parse_next(s)
+/// }
+///
+/// assert_eq!(hex(Partial::new("123 and voila")), Ok((Partial::new(" and voila"), "123")));
+/// assert_eq!(hex(Partial::new("DEADBEEF and others")), Ok((Partial::new(" and others"), "DEADBEEF")));
+/// assert_eq!(hex(Partial::new("BADBABEsomething")), Ok((Partial::new("something"), "BADBABE")));
+/// assert_eq!(hex(Partial::new("D15EA5E")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(hex(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+///
+/// Arbitrary amount of tokens:
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take_while;
+/// use winnow::stream::AsChar;
+///
+/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while(3..=6, AsChar::is_alpha).parse_next(s)
+/// }
+///
+/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
+/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(short_alpha(b"ed"), Err(ErrMode::Backtrack(Error::new(&b"ed"[..], ErrorKind::Slice))));
+/// assert_eq!(short_alpha(b"12345"), Err(ErrMode::Backtrack(Error::new(&b"12345"[..], ErrorKind::Slice))));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_while;
+/// use winnow::stream::AsChar;
+///
+/// fn short_alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+/// take_while(3..=6, AsChar::is_alpha).parse_next(s)
+/// }
+///
+/// assert_eq!(short_alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
+/// assert_eq!(short_alpha(Partial::new(b"lengthy")), Ok((Partial::new(&b"y"[..]), &b"length"[..])));
+/// assert_eq!(short_alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(short_alpha(Partial::new(b"ed")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(short_alpha(Partial::new(b"12345")), Err(ErrMode::Backtrack(Error::new(Partial::new(&b"12345"[..]), ErrorKind::Slice))));
+/// ```
+#[inline(always)]
+#[doc(alias = "is_a")]
+#[doc(alias = "take_while0")]
+#[doc(alias = "take_while1")]
+pub fn take_while<T, I, Error: ParseError<I>>(
+ range: impl Into<Range>,
+ list: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ let Range {
+ start_inclusive,
+ end_inclusive,
+ } = range.into();
+ trace("take_while", move |i: I| {
+ match (start_inclusive, end_inclusive) {
+ (0, None) => {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_while0_::<_, _, _, true>(i, &list)
+ } else {
+ take_while0_::<_, _, _, false>(i, &list)
+ }
+ }
+ (1, None) => {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_while1_::<_, _, _, true>(i, &list)
+ } else {
+ take_while1_::<_, _, _, false>(i, &list)
+ }
+ }
+ (start, end) => {
+ let end = end.unwrap_or(usize::MAX);
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_while_m_n_::<_, _, _, true>(i, start, end, &list)
+ } else {
+ take_while_m_n_::<_, _, _, false>(i, start, end, &list)
+ }
+ }
+ }
+ })
+}
+
+/// Deprecated, see [`take_while`]
+#[deprecated(since = "0.4.6", note = "Replaced with `take_while`")]
+#[inline(always)]
+pub fn take_while0<T, I, Error: ParseError<I>>(
+ list: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ take_while(0.., list)
+}
+
+/// Deprecated, see [`take_while`]
+#[deprecated(since = "0.4.6", note = "Replaced with `take_while`")]
+#[inline(always)]
+pub fn take_while1<T, I, Error: ParseError<I>>(
+ list: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ take_while(1.., list)
+}
+
+fn take_while0_<T, I, Error: ParseError<I>, const PARTIAL: bool>(
+ input: I,
+ list: &T,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ if PARTIAL && input.is_partial() {
+ split_at_offset_partial(&input, |c| !list.contains_token(c))
+ } else {
+ split_at_offset_complete(&input, |c| !list.contains_token(c))
+ }
+}
+
+fn take_while1_<T, I, Error: ParseError<I>, const PARTIAL: bool>(
+ input: I,
+ list: &T,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ let e: ErrorKind = ErrorKind::Slice;
+ if PARTIAL && input.is_partial() {
+ split_at_offset1_partial(&input, |c| !list.contains_token(c), e)
+ } else {
+ split_at_offset1_complete(&input, |c| !list.contains_token(c), e)
+ }
+}
+
+fn take_while_m_n_<T, I, Error: ParseError<I>, const PARTIAL: bool>(
+ input: I,
+ m: usize,
+ n: usize,
+ list: &T,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ if n < m {
+ return Err(ErrMode::assert(input, "`m` should be <= `n`"));
+ }
+
+ let mut final_count = 0;
+ for (processed, (offset, token)) in input.iter_offsets().enumerate() {
+ if !list.contains_token(token) {
+ if processed < m {
+ return Err(ErrMode::from_error_kind(input, ErrorKind::Slice));
+ } else {
+ return Ok(input.next_slice(offset));
+ }
+ } else {
+ if processed == n {
+ return Ok(input.next_slice(offset));
+ }
+ final_count = processed + 1;
+ }
+ }
+ if PARTIAL && input.is_partial() {
+ if final_count == n {
+ Ok(input.next_slice(input.eof_offset()))
+ } else {
+ let needed = if m > input.eof_offset() {
+ m - input.eof_offset()
+ } else {
+ 1
+ };
+ Err(ErrMode::Incomplete(Needed::new(needed)))
+ }
+ } else {
+ if m <= final_count {
+ Ok(input.next_slice(input.eof_offset()))
+ } else {
+ Err(ErrMode::from_error_kind(input, ErrorKind::Slice))
+ }
+ }
+}
+
+/// Recognize the longest input slice (if any) till a [pattern][ContainsToken] is met.
+///
+/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the match reaches the
+/// end of input or if there was not match.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take_till0;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till0(|c| c == ':').parse_next(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
+/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
+/// assert_eq!(till_colon(""), Ok(("", "")));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_till0;
+///
+/// fn till_colon(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take_till0(|c| c == ':').parse_next(s)
+/// }
+///
+/// assert_eq!(till_colon(Partial::new("latin:123")), Ok((Partial::new(":123"), "latin")));
+/// assert_eq!(till_colon(Partial::new(":empty matched")), Ok((Partial::new(":empty matched"), ""))); //allowed
+/// assert_eq!(till_colon(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(till_colon(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn take_till0<T, I, Error: ParseError<I>>(
+ list: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ trace("take_till0", move |i: I| {
+ if <I as StreamIsPartial>::is_partial_supported() && i.is_partial() {
+ split_at_offset_partial(&i, |c| list.contains_token(c))
+ } else {
+ split_at_offset_complete(&i, |c| list.contains_token(c))
+ }
+ })
+}
+
+/// Recognize the longest (at least 1) input slice till a [pattern][ContainsToken] is met.
+///
+/// It will return `Err(ErrMode::Backtrack(Error::new(_, ErrorKind::Slice)))` if the input is empty or the
+/// predicate matches the first input.
+///
+/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the match reaches the
+/// end of input or if there was not match.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take_till1;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till1(|c| c == ':').parse_next(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Err(ErrMode::Backtrack(Error::new(":empty matched", ErrorKind::Slice))));
+/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
+/// assert_eq!(till_colon(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice))));
+///
+/// fn not_space(s: &str) -> IResult<&str, &str> {
+/// take_till1(" \t\r\n").parse_next(s)
+/// }
+///
+/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
+/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
+/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace")));
+/// assert_eq!(not_space(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice))));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_till1;
+///
+/// fn till_colon(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take_till1(|c| c == ':').parse_next(s)
+/// }
+///
+/// assert_eq!(till_colon(Partial::new("latin:123")), Ok((Partial::new(":123"), "latin")));
+/// assert_eq!(till_colon(Partial::new(":empty matched")), Err(ErrMode::Backtrack(Error::new(Partial::new(":empty matched"), ErrorKind::Slice))));
+/// assert_eq!(till_colon(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(till_colon(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+///
+/// fn not_space(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take_till1(" \t\r\n").parse_next(s)
+/// }
+///
+/// assert_eq!(not_space(Partial::new("Hello, World!")), Ok((Partial::new(" World!"), "Hello,")));
+/// assert_eq!(not_space(Partial::new("Sometimes\t")), Ok((Partial::new("\t"), "Sometimes")));
+/// assert_eq!(not_space(Partial::new("Nospace")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(not_space(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+#[doc(alias = "is_not")]
+pub fn take_till1<T, I, Error: ParseError<I>>(
+ list: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ trace("take_till1", move |i: I| {
+ let e: ErrorKind = ErrorKind::Slice;
+ if <I as StreamIsPartial>::is_partial_supported() && i.is_partial() {
+ split_at_offset1_partial(&i, |c| list.contains_token(c), e)
+ } else {
+ split_at_offset1_complete(&i, |c| list.contains_token(c), e)
+ }
+ })
+}
+
+/// Recognize an input slice containing the first N input elements (I[..N]).
+///
+/// *Complete version*: It will return `Err(ErrMode::Backtrack(Error::new(_, ErrorKind::Slice)))` if the input is shorter than the argument.
+///
+/// *Partial version*: if the input has less than N elements, `take` will
+/// return a `ErrMode::Incomplete(Needed::new(M))` where M is the number of
+/// additional bytes the parser would need to succeed.
+/// It is well defined for `&[u8]` as the number of elements is the byte size,
+/// but for types like `&str`, we cannot know how many bytes correspond for
+/// the next few chars, so the result will be `ErrMode::Incomplete(Needed::Unknown)`
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take;
+///
+/// fn take6(s: &str) -> IResult<&str, &str> {
+/// take(6usize).parse_next(s)
+/// }
+///
+/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
+/// assert_eq!(take6("things"), Ok(("", "things")));
+/// assert_eq!(take6("short"), Err(ErrMode::Backtrack(Error::new("short", ErrorKind::Slice))));
+/// assert_eq!(take6(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice))));
+/// ```
+///
+/// The units that are taken will depend on the input type. For example, for a
+/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
+/// take that many `u8`'s:
+///
+/// ```rust
+/// # use winnow::prelude::*;
+/// use winnow::error::Error;
+/// use winnow::token::take;
+///
+/// assert_eq!(take::<_, _, Error<_>>(1usize).parse_next("💙"), Ok(("", "💙")));
+/// assert_eq!(take::<_, _, Error<_>>(1usize).parse_next("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
+/// ```
+///
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::Partial;
+/// use winnow::token::take;
+///
+/// fn take6(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take(6usize).parse_next(s)
+/// }
+///
+/// assert_eq!(take6(Partial::new("1234567")), Ok((Partial::new("7"), "123456")));
+/// assert_eq!(take6(Partial::new("things")), Ok((Partial::new(""), "things")));
+/// // `Unknown` as we don't know the number of bytes that `count` corresponds to
+/// assert_eq!(take6(Partial::new("short")), Err(ErrMode::Incomplete(Needed::Unknown)));
+/// ```
+#[inline(always)]
+pub fn take<C, I, Error: ParseError<I>>(count: C) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ C: ToUsize,
+{
+ let c = count.to_usize();
+ trace("take", move |i: I| {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_::<_, _, true>(i, c)
+ } else {
+ take_::<_, _, false>(i, c)
+ }
+ })
+}
+
+fn take_<I, Error: ParseError<I>, const PARTIAL: bool>(
+ i: I,
+ c: usize,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+{
+ match i.offset_at(c) {
+ Ok(offset) => Ok(i.next_slice(offset)),
+ Err(e) if PARTIAL && i.is_partial() => Err(ErrMode::Incomplete(e)),
+ Err(_needed) => Err(ErrMode::from_error_kind(i, ErrorKind::Slice)),
+ }
+}
+
+/// Recognize the input slice up to the first occurrence of the literal.
+///
+/// It doesn't consume the pattern.
+///
+/// *Complete version*: It will return `Err(ErrMode::Backtrack(Error::new(_, ErrorKind::Slice)))`
+/// if the pattern wasn't met.
+///
+/// *Partial version*: will return a `ErrMode::Incomplete(Needed::new(N))` if the input doesn't
+/// contain the pattern or if the input is smaller than the pattern.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take_until0;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until0("eof").parse_next(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(ErrMode::Backtrack(Error::new("hello, world", ErrorKind::Slice))));
+/// assert_eq!(until_eof(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice))));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_until0;
+///
+/// fn until_eof(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take_until0("eof").parse_next(s)
+/// }
+///
+/// assert_eq!(until_eof(Partial::new("hello, worldeof")), Ok((Partial::new("eof"), "hello, world")));
+/// assert_eq!(until_eof(Partial::new("hello, world")), Err(ErrMode::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Partial::new("hello, worldeo")), Err(ErrMode::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Partial::new("1eof2eof")), Ok((Partial::new("eof2eof"), "1")));
+/// ```
+#[inline(always)]
+pub fn take_until0<T, I, Error: ParseError<I>>(
+ tag: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + FindSlice<T>,
+ T: SliceLen + Clone,
+{
+ trace("take_until0", move |i: I| {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_until0_::<_, _, _, true>(i, tag.clone())
+ } else {
+ take_until0_::<_, _, _, false>(i, tag.clone())
+ }
+ })
+}
+
+fn take_until0_<T, I, Error: ParseError<I>, const PARTIAL: bool>(
+ i: I,
+ t: T,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + FindSlice<T>,
+ T: SliceLen,
+{
+ match i.find_slice(t) {
+ Some(offset) => Ok(i.next_slice(offset)),
+ None if PARTIAL && i.is_partial() => Err(ErrMode::Incomplete(Needed::Unknown)),
+ None => Err(ErrMode::from_error_kind(i, ErrorKind::Slice)),
+ }
+}
+
+/// Recognize the non empty input slice up to the first occurrence of the literal.
+///
+/// It doesn't consume the pattern.
+///
+/// *Complete version*: It will return `Err(ErrMode::Backtrack(Error::new(_, ErrorKind::Slice)))`
+/// if the pattern wasn't met.
+///
+/// *Partial version*: will return a `ErrMode::Incomplete(Needed::new(N))` if the input doesn't
+/// contain the pattern or if the input is smaller than the pattern.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::take_until1;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until1("eof").parse_next(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(ErrMode::Backtrack(Error::new("hello, world", ErrorKind::Slice))));
+/// assert_eq!(until_eof(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice))));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// assert_eq!(until_eof("eof"), Err(ErrMode::Backtrack(Error::new("eof", ErrorKind::Slice))));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_until1;
+///
+/// fn until_eof(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take_until1("eof").parse_next(s)
+/// }
+///
+/// assert_eq!(until_eof(Partial::new("hello, worldeof")), Ok((Partial::new("eof"), "hello, world")));
+/// assert_eq!(until_eof(Partial::new("hello, world")), Err(ErrMode::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Partial::new("hello, worldeo")), Err(ErrMode::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Partial::new("1eof2eof")), Ok((Partial::new("eof2eof"), "1")));
+/// assert_eq!(until_eof(Partial::new("eof")), Err(ErrMode::Backtrack(Error::new(Partial::new("eof"), ErrorKind::Slice))));
+/// ```
+#[inline(always)]
+pub fn take_until1<T, I, Error: ParseError<I>>(
+ tag: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + FindSlice<T>,
+ T: SliceLen + Clone,
+{
+ trace("take_until1", move |i: I| {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_until1_::<_, _, _, true>(i, tag.clone())
+ } else {
+ take_until1_::<_, _, _, false>(i, tag.clone())
+ }
+ })
+}
+
+fn take_until1_<T, I, Error: ParseError<I>, const PARTIAL: bool>(
+ i: I,
+ t: T,
+) -> IResult<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream + FindSlice<T>,
+ T: SliceLen,
+{
+ match i.find_slice(t) {
+ None if PARTIAL && i.is_partial() => Err(ErrMode::Incomplete(Needed::Unknown)),
+ None | Some(0) => Err(ErrMode::from_error_kind(i, ErrorKind::Slice)),
+ Some(offset) => Ok(i.next_slice(offset)),
+ }
+}
diff --git a/vendor/winnow-0.4.7/src/token/tests.rs b/vendor/winnow-0.4.7/src/token/tests.rs
new file mode 100644
index 000000000..e1c7999c2
--- /dev/null
+++ b/vendor/winnow-0.4.7/src/token/tests.rs
@@ -0,0 +1,700 @@
+use super::*;
+
+#[cfg(feature = "std")]
+use proptest::prelude::*;
+
+use crate::binary::length_data;
+use crate::combinator::delimited;
+use crate::error::ErrMode;
+use crate::error::Error;
+use crate::error::ErrorKind;
+use crate::error::Needed;
+use crate::stream::AsChar;
+use crate::token::tag;
+use crate::IResult;
+use crate::Parser;
+use crate::Partial;
+
+#[test]
+fn complete_take_while_m_n_utf8_all_matching() {
+ let result: IResult<&str, &str> =
+ take_while(1..=4, |c: char| c.is_alphabetic()).parse_next("øn");
+ assert_eq!(result, Ok(("", "øn")));
+}
+
+#[test]
+fn complete_take_while_m_n_utf8_all_matching_substring() {
+ let result: IResult<&str, &str> = take_while(1, |c: char| c.is_alphabetic()).parse_next("øn");
+ assert_eq!(result, Ok(("n", "ø")));
+}
+
+#[cfg(feature = "std")]
+fn model_complete_take_while_m_n(
+ m: usize,
+ n: usize,
+ valid: usize,
+ input: &str,
+) -> IResult<&str, &str> {
+ if n < m {
+ Err(crate::error::ErrMode::from_error_kind(
+ input,
+ crate::error::ErrorKind::Slice,
+ ))
+ } else if m <= valid {
+ let offset = n.min(valid);
+ Ok((&input[offset..], &input[0..offset]))
+ } else {
+ Err(crate::error::ErrMode::from_error_kind(
+ input,
+ crate::error::ErrorKind::Slice,
+ ))
+ }
+}
+
+#[cfg(feature = "std")]
+proptest! {
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn complete_take_while_m_n_bounds(m in 0..20usize, n in 0..20usize, valid in 0..20usize, invalid in 0..20usize) {
+ let input = format!("{:a<valid$}{:b<invalid$}", "", "", valid=valid, invalid=invalid);
+ let expected = model_complete_take_while_m_n(m, n, valid, &input);
+ if m <= n {
+ let actual = take_while(m..=n, |c: char| c == 'a').parse_next(input.as_str());
+ assert_eq!(expected, actual);
+ }
+ }
+}
+
+#[test]
+fn partial_any_str() {
+ use super::any;
+ assert_eq!(
+ any::<_, Error<Partial<&str>>>(Partial::new("Ó˜")),
+ Ok((Partial::new(""), 'Ó˜'))
+ );
+}
+
+#[test]
+fn partial_one_of_test() {
+ fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, u8> {
+ one_of("ab").parse_next(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(f(Partial::new(a)), Ok((Partial::new(&b"bcd"[..]), b'a')));
+
+ let b = &b"cde"[..];
+ assert_eq!(
+ f(Partial::new(b)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(b),
+ ErrorKind::Verify
+ )))
+ );
+
+ fn utf8(i: Partial<&str>) -> IResult<Partial<&str>, char> {
+ one_of("+\u{FF0B}").parse_next(i)
+ }
+
+ assert!(utf8(Partial::new("+")).is_ok());
+ assert!(utf8(Partial::new("\u{FF0B}")).is_ok());
+}
+
+#[test]
+fn char_byteslice() {
+ fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, u8> {
+ 'c'.parse_next(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(
+ f(Partial::new(a)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(a),
+ ErrorKind::Verify
+ )))
+ );
+
+ let b = &b"cde"[..];
+ assert_eq!(f(Partial::new(b)), Ok((Partial::new(&b"de"[..]), b'c')));
+}
+
+#[test]
+fn char_str() {
+ fn f(i: Partial<&str>) -> IResult<Partial<&str>, char> {
+ 'c'.parse_next(i)
+ }
+
+ let a = "abcd";
+ assert_eq!(
+ f(Partial::new(a)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(a),
+ ErrorKind::Verify
+ )))
+ );
+
+ let b = "cde";
+ assert_eq!(f(Partial::new(b)), Ok((Partial::new("de"), 'c')));
+}
+
+#[test]
+fn partial_none_of_test() {
+ fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, u8> {
+ none_of("ab").parse_next(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(
+ f(Partial::new(a)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(a),
+ ErrorKind::Verify
+ )))
+ );
+
+ let b = &b"cde"[..];
+ assert_eq!(f(Partial::new(b)), Ok((Partial::new(&b"de"[..]), b'c')));
+}
+
+#[test]
+fn partial_is_a() {
+ fn a_or_b(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_while(1.., "ab").parse_next(i)
+ }
+
+ let a = Partial::new(&b"abcd"[..]);
+ assert_eq!(a_or_b(a), Ok((Partial::new(&b"cd"[..]), &b"ab"[..])));
+
+ let b = Partial::new(&b"bcde"[..]);
+ assert_eq!(a_or_b(b), Ok((Partial::new(&b"cde"[..]), &b"b"[..])));
+
+ let c = Partial::new(&b"cdef"[..]);
+ assert_eq!(
+ a_or_b(c),
+ Err(ErrMode::Backtrack(error_position!(c, ErrorKind::Slice)))
+ );
+
+ let d = Partial::new(&b"bacdef"[..]);
+ assert_eq!(a_or_b(d), Ok((Partial::new(&b"cdef"[..]), &b"ba"[..])));
+}
+
+#[test]
+fn partial_is_not() {
+ fn a_or_b(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_till1("ab").parse_next(i)
+ }
+
+ let a = Partial::new(&b"cdab"[..]);
+ assert_eq!(a_or_b(a), Ok((Partial::new(&b"ab"[..]), &b"cd"[..])));
+
+ let b = Partial::new(&b"cbde"[..]);
+ assert_eq!(a_or_b(b), Ok((Partial::new(&b"bde"[..]), &b"c"[..])));
+
+ let c = Partial::new(&b"abab"[..]);
+ assert_eq!(
+ a_or_b(c),
+ Err(ErrMode::Backtrack(error_position!(c, ErrorKind::Slice)))
+ );
+
+ let d = Partial::new(&b"cdefba"[..]);
+ assert_eq!(a_or_b(d), Ok((Partial::new(&b"ba"[..]), &b"cdef"[..])));
+
+ let e = Partial::new(&b"e"[..]);
+ assert_eq!(a_or_b(e), Err(ErrMode::Incomplete(Needed::new(1))));
+}
+
+#[test]
+fn partial_take_until_incomplete() {
+ fn y(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_until0("end").parse_next(i)
+ }
+ assert_eq!(
+ y(Partial::new(&b"nd"[..])),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+ assert_eq!(
+ y(Partial::new(&b"123"[..])),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+ assert_eq!(
+ y(Partial::new(&b"123en"[..])),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+}
+
+#[test]
+fn partial_take_until_incomplete_s() {
+ fn ys(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_until0("end").parse_next(i)
+ }
+ assert_eq!(
+ ys(Partial::new("123en")),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+}
+
+#[test]
+fn partial_recognize() {
+ use crate::ascii::{
+ alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit,
+ multispace1 as multispace, oct_digit1 as oct_digit, space1 as space,
+ };
+
+ fn x(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ delimited("<!--", take(5_usize), "-->")
+ .recognize()
+ .parse_next(i)
+ }
+ let r = x(Partial::new(&b"<!-- abc --> aaa"[..]));
+ assert_eq!(r, Ok((Partial::new(&b" aaa"[..]), &b"<!-- abc -->"[..])));
+
+ let semicolon = &b";"[..];
+
+ fn ya(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ alpha.recognize().parse_next(i)
+ }
+ let ra = ya(Partial::new(&b"abc;"[..]));
+ assert_eq!(ra, Ok((Partial::new(semicolon), &b"abc"[..])));
+
+ fn yd(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ digit.recognize().parse_next(i)
+ }
+ let rd = yd(Partial::new(&b"123;"[..]));
+ assert_eq!(rd, Ok((Partial::new(semicolon), &b"123"[..])));
+
+ fn yhd(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ hex_digit.recognize().parse_next(i)
+ }
+ let rhd = yhd(Partial::new(&b"123abcDEF;"[..]));
+ assert_eq!(rhd, Ok((Partial::new(semicolon), &b"123abcDEF"[..])));
+
+ fn yod(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ oct_digit.recognize().parse_next(i)
+ }
+ let rod = yod(Partial::new(&b"1234567;"[..]));
+ assert_eq!(rod, Ok((Partial::new(semicolon), &b"1234567"[..])));
+
+ fn yan(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ alphanumeric.recognize().parse_next(i)
+ }
+ let ran = yan(Partial::new(&b"123abc;"[..]));
+ assert_eq!(ran, Ok((Partial::new(semicolon), &b"123abc"[..])));
+
+ fn ys(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ space.recognize().parse_next(i)
+ }
+ let rs = ys(Partial::new(&b" \t;"[..]));
+ assert_eq!(rs, Ok((Partial::new(semicolon), &b" \t"[..])));
+
+ fn yms(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ multispace.recognize().parse_next(i)
+ }
+ let rms = yms(Partial::new(&b" \t\r\n;"[..]));
+ assert_eq!(rms, Ok((Partial::new(semicolon), &b" \t\r\n"[..])));
+}
+
+#[test]
+fn partial_take_while0() {
+ fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_while(0.., AsChar::is_alpha).parse_next(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"abcd123"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Partial::new(a)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(f(Partial::new(b)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(f(Partial::new(c)), Ok((Partial::new(d), b)));
+ assert_eq!(f(Partial::new(d)), Ok((Partial::new(d), a)));
+}
+
+#[test]
+fn partial_take_while1() {
+ fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_while(1.., AsChar::is_alpha).parse_next(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"abcd123"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Partial::new(a)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(f(Partial::new(b)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(f(Partial::new(c)), Ok((Partial::new(&b"123"[..]), b)));
+ assert_eq!(
+ f(Partial::new(d)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(d),
+ ErrorKind::Slice
+ )))
+ );
+}
+
+#[test]
+fn partial_take_while_m_n() {
+ fn x(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_while(2..=4, AsChar::is_alpha).parse_next(i)
+ }
+ let a = &b""[..];
+ let b = &b"a"[..];
+ let c = &b"abc"[..];
+ let d = &b"abc123"[..];
+ let e = &b"abcde"[..];
+ let f = &b"123"[..];
+
+ assert_eq!(x(Partial::new(a)), Err(ErrMode::Incomplete(Needed::new(2))));
+ assert_eq!(x(Partial::new(b)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(x(Partial::new(c)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(x(Partial::new(d)), Ok((Partial::new(&b"123"[..]), c)));
+ assert_eq!(
+ x(Partial::new(e)),
+ Ok((Partial::new(&b"e"[..]), &b"abcd"[..]))
+ );
+ assert_eq!(
+ x(Partial::new(f)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(f),
+ ErrorKind::Slice
+ )))
+ );
+}
+
+#[test]
+fn partial_take_till0() {
+ fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_till0(AsChar::is_alpha).parse_next(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"123abcd"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Partial::new(a)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(
+ f(Partial::new(b)),
+ Ok((Partial::new(&b"abcd"[..]), &b""[..]))
+ );
+ assert_eq!(
+ f(Partial::new(c)),
+ Ok((Partial::new(&b"abcd"[..]), &b"123"[..]))
+ );
+ assert_eq!(f(Partial::new(d)), Err(ErrMode::Incomplete(Needed::new(1))));
+}
+
+#[test]
+fn partial_take_till1() {
+ fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_till1(AsChar::is_alpha).parse_next(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"123abcd"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Partial::new(a)), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_eq!(
+ f(Partial::new(b)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(b),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ f(Partial::new(c)),
+ Ok((Partial::new(&b"abcd"[..]), &b"123"[..]))
+ );
+ assert_eq!(f(Partial::new(d)), Err(ErrMode::Incomplete(Needed::new(1))));
+}
+
+#[test]
+fn partial_take_while_utf8() {
+ fn f(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_while(0.., |c| c != '點').parse_next(i)
+ }
+
+ assert_eq!(
+ f(Partial::new("")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ f(Partial::new("abcd")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(f(Partial::new("abcd點")), Ok((Partial::new("點"), "abcd")));
+ assert_eq!(
+ f(Partial::new("abcd點a")),
+ Ok((Partial::new("點a"), "abcd"))
+ );
+
+ fn g(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_while(0.., |c| c == '點').parse_next(i)
+ }
+
+ assert_eq!(
+ g(Partial::new("")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(g(Partial::new("點abcd")), Ok((Partial::new("abcd"), "點")));
+ assert_eq!(
+ g(Partial::new("點點點a")),
+ Ok((Partial::new("a"), "點點點"))
+ );
+}
+
+#[test]
+fn partial_take_till0_utf8() {
+ fn f(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_till0(|c| c == '點').parse_next(i)
+ }
+
+ assert_eq!(
+ f(Partial::new("")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ f(Partial::new("abcd")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(f(Partial::new("abcd點")), Ok((Partial::new("點"), "abcd")));
+ assert_eq!(
+ f(Partial::new("abcd點a")),
+ Ok((Partial::new("點a"), "abcd"))
+ );
+
+ fn g(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_till0(|c| c != '點').parse_next(i)
+ }
+
+ assert_eq!(
+ g(Partial::new("")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(g(Partial::new("點abcd")), Ok((Partial::new("abcd"), "點")));
+ assert_eq!(
+ g(Partial::new("點點點a")),
+ Ok((Partial::new("a"), "點點點"))
+ );
+}
+
+#[test]
+fn partial_take_utf8() {
+ fn f(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take(3_usize).parse_next(i)
+ }
+
+ assert_eq!(
+ f(Partial::new("")),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+ assert_eq!(
+ f(Partial::new("ab")),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+ assert_eq!(
+ f(Partial::new("點")),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+ assert_eq!(f(Partial::new("ab點cd")), Ok((Partial::new("cd"), "ab點")));
+ assert_eq!(f(Partial::new("a點bcd")), Ok((Partial::new("cd"), "a點b")));
+ assert_eq!(f(Partial::new("a點b")), Ok((Partial::new(""), "a點b")));
+
+ fn g(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_while(0.., |c| c == '點').parse_next(i)
+ }
+
+ assert_eq!(
+ g(Partial::new("")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(g(Partial::new("點abcd")), Ok((Partial::new("abcd"), "點")));
+ assert_eq!(
+ g(Partial::new("點點點a")),
+ Ok((Partial::new("a"), "點點點"))
+ );
+}
+
+#[test]
+fn partial_take_while_m_n_utf8_fixed() {
+ fn parser(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_while(1, |c| c == 'A' || c == '😃').parse_next(i)
+ }
+ assert_eq!(parser(Partial::new("A!")), Ok((Partial::new("!"), "A")));
+ assert_eq!(parser(Partial::new("😃!")), Ok((Partial::new("!"), "😃")));
+}
+
+#[test]
+fn partial_take_while_m_n_utf8_range() {
+ fn parser(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_while(1..=2, |c| c == 'A' || c == '😃').parse_next(i)
+ }
+ assert_eq!(parser(Partial::new("A!")), Ok((Partial::new("!"), "A")));
+ assert_eq!(parser(Partial::new("😃!")), Ok((Partial::new("!"), "😃")));
+}
+
+#[test]
+fn partial_take_while_m_n_utf8_full_match_fixed() {
+ fn parser(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_while(1, |c: char| c.is_alphabetic()).parse_next(i)
+ }
+ assert_eq!(parser(Partial::new("øn")), Ok((Partial::new("n"), "ø")));
+}
+
+#[test]
+fn partial_take_while_m_n_utf8_full_match_range() {
+ fn parser(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ take_while(1..=2, |c: char| c.is_alphabetic()).parse_next(i)
+ }
+ assert_eq!(parser(Partial::new("øn")), Ok((Partial::new(""), "øn")));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn partial_recognize_take_while0() {
+ fn x(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ take_while(0.., AsChar::is_alphanum).parse_next(i)
+ }
+ fn y(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ x.recognize().parse_next(i)
+ }
+ assert_eq!(
+ x(Partial::new(&b"ab."[..])),
+ Ok((Partial::new(&b"."[..]), &b"ab"[..]))
+ );
+ assert_eq!(
+ y(Partial::new(&b"ab."[..])),
+ Ok((Partial::new(&b"."[..]), &b"ab"[..]))
+ );
+}
+
+#[test]
+fn partial_length_bytes() {
+ use crate::binary::le_u8;
+
+ fn x(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ length_data(le_u8).parse_next(i)
+ }
+ assert_eq!(
+ x(Partial::new(b"\x02..>>")),
+ Ok((Partial::new(&b">>"[..]), &b".."[..]))
+ );
+ assert_eq!(
+ x(Partial::new(b"\x02..")),
+ Ok((Partial::new(&[][..]), &b".."[..]))
+ );
+ assert_eq!(
+ x(Partial::new(b"\x02.")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ x(Partial::new(b"\x02")),
+ Err(ErrMode::Incomplete(Needed::new(2)))
+ );
+
+ fn y(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ let (i, _) = "magic".parse_next(i)?;
+ length_data(le_u8).parse_next(i)
+ }
+ assert_eq!(
+ y(Partial::new(b"magic\x02..>>")),
+ Ok((Partial::new(&b">>"[..]), &b".."[..]))
+ );
+ assert_eq!(
+ y(Partial::new(b"magic\x02..")),
+ Ok((Partial::new(&[][..]), &b".."[..]))
+ );
+ assert_eq!(
+ y(Partial::new(b"magic\x02.")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ y(Partial::new(b"magic\x02")),
+ Err(ErrMode::Incomplete(Needed::new(2)))
+ );
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn partial_case_insensitive() {
+ fn test(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ tag_no_case("ABcd").parse_next(i)
+ }
+ assert_eq!(
+ test(Partial::new(&b"aBCdefgh"[..])),
+ Ok((Partial::new(&b"efgh"[..]), &b"aBCd"[..]))
+ );
+ assert_eq!(
+ test(Partial::new(&b"abcdefgh"[..])),
+ Ok((Partial::new(&b"efgh"[..]), &b"abcd"[..]))
+ );
+ assert_eq!(
+ test(Partial::new(&b"ABCDefgh"[..])),
+ Ok((Partial::new(&b"efgh"[..]), &b"ABCD"[..]))
+ );
+ assert_eq!(
+ test(Partial::new(&b"ab"[..])),
+ Err(ErrMode::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ test(Partial::new(&b"Hello"[..])),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"Hello"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ test(Partial::new(&b"Hel"[..])),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"Hel"[..]),
+ ErrorKind::Tag
+ )))
+ );
+
+ fn test2(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
+ tag_no_case("ABcd").parse_next(i)
+ }
+ assert_eq!(
+ test2(Partial::new("aBCdefgh")),
+ Ok((Partial::new("efgh"), "aBCd"))
+ );
+ assert_eq!(
+ test2(Partial::new("abcdefgh")),
+ Ok((Partial::new("efgh"), "abcd"))
+ );
+ assert_eq!(
+ test2(Partial::new("ABCDefgh")),
+ Ok((Partial::new("efgh"), "ABCD"))
+ );
+ assert_eq!(
+ test2(Partial::new("ab")),
+ Err(ErrMode::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ test2(Partial::new("Hello")),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new("Hello"),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ test2(Partial::new("Hel")),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new("Hel"),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn partial_tag_fixed_size_array() {
+ fn test(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ tag([0x42]).parse_next(i)
+ }
+ fn test2(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
+ tag(&[0x42]).parse_next(i)
+ }
+ let input = Partial::new(&[0x42, 0x00][..]);
+ assert_eq!(test(input), Ok((Partial::new(&b"\x00"[..]), &b"\x42"[..])));
+ assert_eq!(test2(input), Ok((Partial::new(&b"\x00"[..]), &b"\x42"[..])));
+}