winnow/token/
mod.rs

1//! Parsers extracting tokens from the stream
2
3#[cfg(test)]
4mod tests;
5
6use crate::combinator::trace;
7use crate::error::ErrMode;
8use crate::error::ErrorKind;
9use crate::error::Needed;
10use crate::error::ParserError;
11use crate::lib::std::result::Result::Ok;
12use crate::stream::Range;
13use crate::stream::{Compare, CompareResult, ContainsToken, FindSlice, SliceLen, Stream};
14use crate::stream::{StreamIsPartial, ToUsize};
15use crate::PResult;
16use crate::Parser;
17
18/// Matches one token
19///
20/// *Complete version*: Will return an error if there's not enough input data.
21///
22/// *Partial version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
23///
24/// # Example
25///
26/// ```rust
27/// # use winnow::{token::any, error::ErrMode, error::{InputError, ErrorKind}};
28/// # use winnow::prelude::*;
29/// fn parser(input: &str) -> IResult<&str, char> {
30///     any.parse_peek(input)
31/// }
32///
33/// assert_eq!(parser("abc"), Ok(("bc",'a')));
34/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Token))));
35/// ```
36///
37/// ```rust
38/// # use winnow::{token::any, error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
39/// # use winnow::prelude::*;
40/// # use winnow::Partial;
41/// assert_eq!(any::<_, InputError<_>>.parse_peek(Partial::new("abc")), Ok((Partial::new("bc"),'a')));
42/// assert_eq!(any::<_, InputError<_>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
43/// ```
44#[inline(always)]
45#[doc(alias = "token")]
46pub fn any<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Token, E>
47where
48    I: StreamIsPartial,
49    I: Stream,
50{
51    trace("any", move |input: &mut I| {
52        if <I as StreamIsPartial>::is_partial_supported() {
53            any_::<_, _, true>(input)
54        } else {
55            any_::<_, _, false>(input)
56        }
57    })
58    .parse_next(input)
59}
60
61fn any_<I, E: ParserError<I>, const PARTIAL: bool>(
62    input: &mut I,
63) -> PResult<<I as Stream>::Token, E>
64where
65    I: StreamIsPartial,
66    I: Stream,
67{
68    input.next_token().ok_or_else(|| {
69        if PARTIAL && input.is_partial() {
70            ErrMode::Incomplete(Needed::new(1))
71        } else {
72            ErrMode::from_error_kind(input, ErrorKind::Token)
73        }
74    })
75}
76
77/// Recognizes a literal
78///
79/// The input data will be compared to the tag combinator's argument and will return the part of
80/// the input that matches the argument
81///
82/// It will return `Err(ErrMode::Backtrack(InputError::new(_, ErrorKind::Tag)))` if the input doesn't match the pattern
83///
84/// **Note:** [`Parser`] is implemented for strings and byte strings as a convenience (complete
85/// only)
86///
87/// # Example
88/// ```rust
89/// # use winnow::prelude::*;
90/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
91/// use winnow::token::tag;
92///
93/// fn parser(s: &str) -> IResult<&str, &str> {
94///   "Hello".parse_peek(s)
95/// }
96///
97/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
98/// assert_eq!(parser("Something"), Err(ErrMode::Backtrack(InputError::new("Something", ErrorKind::Tag))));
99/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
100/// ```
101///
102/// ```rust
103/// # use winnow::prelude::*;
104/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
105/// # use winnow::Partial;
106/// use winnow::token::tag;
107///
108/// fn parser(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
109///   "Hello".parse_peek(s)
110/// }
111///
112/// assert_eq!(parser(Partial::new("Hello, World!")), Ok((Partial::new(", World!"), "Hello")));
113/// assert_eq!(parser(Partial::new("Something")), Err(ErrMode::Backtrack(InputError::new(Partial::new("Something"), ErrorKind::Tag))));
114/// assert_eq!(parser(Partial::new("S")), Err(ErrMode::Backtrack(InputError::new(Partial::new("S"), ErrorKind::Tag))));
115/// assert_eq!(parser(Partial::new("H")), Err(ErrMode::Incomplete(Needed::new(4))));
116/// ```
117///
118/// ```rust
119/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
120/// # use winnow::prelude::*;
121/// use winnow::token::tag;
122/// use winnow::ascii::Caseless;
123///
124/// fn parser(s: &str) -> IResult<&str, &str> {
125///   tag(Caseless("hello")).parse_peek(s)
126/// }
127///
128/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
129/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
130/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
131/// assert_eq!(parser("Something"), Err(ErrMode::Backtrack(InputError::new("Something", ErrorKind::Tag))));
132/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
133/// ```
134#[inline(always)]
135#[doc(alias = "tag")]
136#[doc(alias = "bytes")]
137#[doc(alias = "just")]
138pub fn literal<T, I, Error: ParserError<I>>(tag: T) -> impl Parser<I, <I as Stream>::Slice, Error>
139where
140    I: StreamIsPartial,
141    I: Stream + Compare<T>,
142    T: SliceLen + Clone,
143{
144    trace("tag", move |i: &mut I| {
145        let t = tag.clone();
146        if <I as StreamIsPartial>::is_partial_supported() {
147            literal_::<_, _, _, true>(i, t)
148        } else {
149            literal_::<_, _, _, false>(i, t)
150        }
151    })
152}
153
154/// Deprecated, replaced with [`literal`]
155#[deprecated(since = "0.5.38", note = "Replaced with `literal`")]
156pub fn tag<T, I, Error: ParserError<I>>(tag: T) -> impl Parser<I, <I as Stream>::Slice, Error>
157where
158    I: StreamIsPartial,
159    I: Stream + Compare<T>,
160    T: SliceLen + Clone,
161{
162    literal(tag)
163}
164
165fn literal_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
166    i: &mut I,
167    t: T,
168) -> PResult<<I as Stream>::Slice, Error>
169where
170    I: StreamIsPartial,
171    I: Stream + Compare<T>,
172    T: SliceLen,
173{
174    let tag_len = t.slice_len();
175    match i.compare(t) {
176        CompareResult::Ok => Ok(i.next_slice(tag_len)),
177        CompareResult::Incomplete if PARTIAL && i.is_partial() => {
178            Err(ErrMode::Incomplete(Needed::new(tag_len - i.eof_offset())))
179        }
180        CompareResult::Incomplete | CompareResult::Error => {
181            let e: ErrorKind = ErrorKind::Tag;
182            Err(ErrMode::from_error_kind(i, e))
183        }
184    }
185}
186
187/// Recognizes a case insensitive literal.
188///
189/// The input data will be compared to the tag combinator's argument and will return the part of
190/// the input that matches the argument with no regard to case.
191///
192/// It will return `Err(ErrMode::Backtrack(InputError::new(_, ErrorKind::Tag)))` if the input doesn't match the pattern.
193///
194/// # Example
195///
196/// ```rust
197/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
198/// # use winnow::prelude::*;
199/// use winnow::token::tag_no_case;
200///
201/// fn parser(s: &str) -> IResult<&str, &str> {
202///   tag_no_case("hello").parse_peek(s)
203/// }
204///
205/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
206/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
207/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
208/// assert_eq!(parser("Something"), Err(ErrMode::Backtrack(InputError::new("Something", ErrorKind::Tag))));
209/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
210/// ```
211///
212/// ```rust
213/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
214/// # use winnow::prelude::*;
215/// # use winnow::Partial;
216/// use winnow::token::tag_no_case;
217///
218/// fn parser(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
219///   tag_no_case("hello").parse_peek(s)
220/// }
221///
222/// assert_eq!(parser(Partial::new("Hello, World!")), Ok((Partial::new(", World!"), "Hello")));
223/// assert_eq!(parser(Partial::new("hello, World!")), Ok((Partial::new(", World!"), "hello")));
224/// assert_eq!(parser(Partial::new("HeLlO, World!")), Ok((Partial::new(", World!"), "HeLlO")));
225/// assert_eq!(parser(Partial::new("Something")), Err(ErrMode::Backtrack(InputError::new(Partial::new("Something"), ErrorKind::Tag))));
226/// assert_eq!(parser(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(5))));
227/// ```
228#[inline(always)]
229#[doc(alias = "literal")]
230#[doc(alias = "bytes")]
231#[doc(alias = "just")]
232#[deprecated(since = "0.5.20", note = "Replaced with `tag(ascii::Caseless(_))`")]
233pub fn tag_no_case<T, I, Error: ParserError<I>>(
234    tag: T,
235) -> impl Parser<I, <I as Stream>::Slice, Error>
236where
237    I: StreamIsPartial,
238    I: Stream + Compare<T>,
239    T: SliceLen + Clone,
240{
241    trace("tag_no_case", move |i: &mut I| {
242        let t = tag.clone();
243        if <I as StreamIsPartial>::is_partial_supported() {
244            tag_no_case_::<_, _, _, true>(i, t)
245        } else {
246            tag_no_case_::<_, _, _, false>(i, t)
247        }
248    })
249}
250
251#[allow(deprecated)]
252fn tag_no_case_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
253    i: &mut I,
254    t: T,
255) -> PResult<<I as Stream>::Slice, Error>
256where
257    I: StreamIsPartial,
258    I: Stream + Compare<T>,
259    T: SliceLen,
260{
261    let tag_len = t.slice_len();
262
263    match i.compare_no_case(t) {
264        CompareResult::Ok => Ok(i.next_slice(tag_len)),
265        CompareResult::Incomplete if PARTIAL && i.is_partial() => {
266            Err(ErrMode::Incomplete(Needed::new(tag_len - i.eof_offset())))
267        }
268        CompareResult::Incomplete | CompareResult::Error => {
269            let e: ErrorKind = ErrorKind::Tag;
270            Err(ErrMode::from_error_kind(i, e))
271        }
272    }
273}
274
275/// Recognize a token that matches the [pattern][ContainsToken]
276///
277/// **Note:** [`Parser`] is implemented as a convenience (complete
278/// only) for
279/// - `u8`
280/// - `char`
281///
282/// *Complete version*: Will return an error if there's not enough input data.
283///
284/// *Partial version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
285///
286/// # Example
287///
288/// ```rust
289/// # use winnow::prelude::*;
290/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError};
291/// # use winnow::token::one_of;
292/// assert_eq!(one_of::<_, _, InputError<_>>(['a', 'b', 'c']).parse_peek("b"), Ok(("", 'b')));
293/// assert_eq!(one_of::<_, _, InputError<_>>('a').parse_peek("bc"), Err(ErrMode::Backtrack(InputError::new("bc", ErrorKind::Verify))));
294/// assert_eq!(one_of::<_, _, InputError<_>>('a').parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Token))));
295///
296/// fn parser_fn(i: &str) -> IResult<&str, char> {
297///     one_of(|c| c == 'a' || c == 'b').parse_peek(i)
298/// }
299/// assert_eq!(parser_fn("abc"), Ok(("bc", 'a')));
300/// assert_eq!(parser_fn("cd"), Err(ErrMode::Backtrack(InputError::new("cd", ErrorKind::Verify))));
301/// assert_eq!(parser_fn(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Token))));
302/// ```
303///
304/// ```
305/// # use winnow::prelude::*;
306/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
307/// # use winnow::Partial;
308/// # use winnow::token::one_of;
309/// assert_eq!(one_of::<_, _, InputError<_>>(['a', 'b', 'c']).parse_peek(Partial::new("b")), Ok((Partial::new(""), 'b')));
310/// assert_eq!(one_of::<_, _, InputError<_>>('a').parse_peek(Partial::new("bc")), Err(ErrMode::Backtrack(InputError::new(Partial::new("bc"), ErrorKind::Verify))));
311/// assert_eq!(one_of::<_, _, InputError<_>>('a').parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
312///
313/// fn parser_fn(i: Partial<&str>) -> IResult<Partial<&str>, char> {
314///     one_of(|c| c == 'a' || c == 'b').parse_peek(i)
315/// }
316/// assert_eq!(parser_fn(Partial::new("abc")), Ok((Partial::new("bc"), 'a')));
317/// assert_eq!(parser_fn(Partial::new("cd")), Err(ErrMode::Backtrack(InputError::new(Partial::new("cd"), ErrorKind::Verify))));
318/// assert_eq!(parser_fn(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
319/// ```
320#[inline(always)]
321#[doc(alias = "char")]
322#[doc(alias = "token")]
323#[doc(alias = "satisfy")]
324pub fn one_of<I, T, Error: ParserError<I>>(list: T) -> impl Parser<I, <I as Stream>::Token, Error>
325where
326    I: StreamIsPartial,
327    I: Stream,
328    <I as Stream>::Token: Clone,
329    T: ContainsToken<<I as Stream>::Token>,
330{
331    trace(
332        "one_of",
333        any.verify(move |t: &<I as Stream>::Token| list.contains_token(t.clone())),
334    )
335}
336
337/// Recognize a token that does not match the [pattern][ContainsToken]
338///
339/// *Complete version*: Will return an error if there's not enough input data.
340///
341/// *Partial version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data.
342///
343/// # Example
344///
345/// ```rust
346/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError};
347/// # use winnow::prelude::*;
348/// # use winnow::token::none_of;
349/// assert_eq!(none_of::<_, _, InputError<_>>(['a', 'b', 'c']).parse_peek("z"), Ok(("", 'z')));
350/// assert_eq!(none_of::<_, _, InputError<_>>(['a', 'b']).parse_peek("a"), Err(ErrMode::Backtrack(InputError::new("a", ErrorKind::Verify))));
351/// assert_eq!(none_of::<_, _, InputError<_>>('a').parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Token))));
352/// ```
353///
354/// ```
355/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
356/// # use winnow::prelude::*;
357/// # use winnow::Partial;
358/// # use winnow::token::none_of;
359/// assert_eq!(none_of::<_, _, InputError<_>>(['a', 'b', 'c']).parse_peek(Partial::new("z")), Ok((Partial::new(""), 'z')));
360/// assert_eq!(none_of::<_, _, InputError<_>>(['a', 'b']).parse_peek(Partial::new("a")), Err(ErrMode::Backtrack(InputError::new(Partial::new("a"), ErrorKind::Verify))));
361/// assert_eq!(none_of::<_, _, InputError<_>>('a').parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
362/// ```
363#[inline(always)]
364pub fn none_of<I, T, Error: ParserError<I>>(list: T) -> impl Parser<I, <I as Stream>::Token, Error>
365where
366    I: StreamIsPartial,
367    I: Stream,
368    <I as Stream>::Token: Clone,
369    T: ContainsToken<<I as Stream>::Token>,
370{
371    trace(
372        "none_of",
373        any.verify(move |t: &<I as Stream>::Token| !list.contains_token(t.clone())),
374    )
375}
376
377/// Recognize the longest (m <= len <= n) input slice that matches the [pattern][ContainsToken]
378///
379/// It will return an `ErrMode::Backtrack(InputError::new(_, ErrorKind::Slice))` if the pattern wasn't met or is out
380/// of range (m <= len <= n).
381///
382/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short.
383///
384/// To recognize a series of tokens, use [`repeat`][crate::combinator::repeat] to [`Accumulate`][crate::stream::Accumulate] into a `()` and then [`Parser::recognize`].
385///
386/// # Example
387///
388/// Zero or more tokens:
389/// ```rust
390/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
391/// # use winnow::prelude::*;
392/// use winnow::token::take_while;
393/// use winnow::stream::AsChar;
394///
395/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
396///   take_while(0.., AsChar::is_alpha).parse_peek(s)
397/// }
398///
399/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
400/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
401/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
402/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
403/// ```
404///
405/// ```rust
406/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
407/// # use winnow::prelude::*;
408/// # use winnow::Partial;
409/// use winnow::token::take_while;
410/// use winnow::stream::AsChar;
411///
412/// fn alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
413///   take_while(0.., AsChar::is_alpha).parse_peek(s)
414/// }
415///
416/// assert_eq!(alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
417/// assert_eq!(alpha(Partial::new(b"12345")), Ok((Partial::new(&b"12345"[..]), &b""[..])));
418/// assert_eq!(alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
419/// assert_eq!(alpha(Partial::new(b"")), Err(ErrMode::Incomplete(Needed::new(1))));
420/// ```
421///
422/// One or more tokens:
423/// ```rust
424/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
425/// # use winnow::prelude::*;
426/// use winnow::token::take_while;
427/// use winnow::stream::AsChar;
428///
429/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
430///   take_while(1.., AsChar::is_alpha).parse_peek(s)
431/// }
432///
433/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
434/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
435/// assert_eq!(alpha(b"12345"), Err(ErrMode::Backtrack(InputError::new(&b"12345"[..], ErrorKind::Slice))));
436///
437/// fn hex(s: &str) -> IResult<&str, &str> {
438///   take_while(1.., ('0'..='9', 'A'..='F')).parse_peek(s)
439/// }
440///
441/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
442/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
443/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
444/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
445/// assert_eq!(hex(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
446/// ```
447///
448/// ```rust
449/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
450/// # use winnow::prelude::*;
451/// # use winnow::Partial;
452/// use winnow::token::take_while;
453/// use winnow::stream::AsChar;
454///
455/// fn alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
456///   take_while(1.., AsChar::is_alpha).parse_peek(s)
457/// }
458///
459/// assert_eq!(alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
460/// assert_eq!(alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
461/// assert_eq!(alpha(Partial::new(b"12345")), Err(ErrMode::Backtrack(InputError::new(Partial::new(&b"12345"[..]), ErrorKind::Slice))));
462///
463/// fn hex(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
464///   take_while(1.., ('0'..='9', 'A'..='F')).parse_peek(s)
465/// }
466///
467/// assert_eq!(hex(Partial::new("123 and voila")), Ok((Partial::new(" and voila"), "123")));
468/// assert_eq!(hex(Partial::new("DEADBEEF and others")), Ok((Partial::new(" and others"), "DEADBEEF")));
469/// assert_eq!(hex(Partial::new("BADBABEsomething")), Ok((Partial::new("something"), "BADBABE")));
470/// assert_eq!(hex(Partial::new("D15EA5E")), Err(ErrMode::Incomplete(Needed::new(1))));
471/// assert_eq!(hex(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
472/// ```
473///
474/// Arbitrary amount of tokens:
475/// ```rust
476/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
477/// # use winnow::prelude::*;
478/// use winnow::token::take_while;
479/// use winnow::stream::AsChar;
480///
481/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
482///   take_while(3..=6, AsChar::is_alpha).parse_peek(s)
483/// }
484///
485/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
486/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
487/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
488/// assert_eq!(short_alpha(b"ed"), Err(ErrMode::Backtrack(InputError::new(&b"ed"[..], ErrorKind::Slice))));
489/// assert_eq!(short_alpha(b"12345"), Err(ErrMode::Backtrack(InputError::new(&b"12345"[..], ErrorKind::Slice))));
490/// ```
491///
492/// ```rust
493/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
494/// # use winnow::prelude::*;
495/// # use winnow::Partial;
496/// use winnow::token::take_while;
497/// use winnow::stream::AsChar;
498///
499/// fn short_alpha(s: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
500///   take_while(3..=6, AsChar::is_alpha).parse_peek(s)
501/// }
502///
503/// assert_eq!(short_alpha(Partial::new(b"latin123")), Ok((Partial::new(&b"123"[..]), &b"latin"[..])));
504/// assert_eq!(short_alpha(Partial::new(b"lengthy")), Ok((Partial::new(&b"y"[..]), &b"length"[..])));
505/// assert_eq!(short_alpha(Partial::new(b"latin")), Err(ErrMode::Incomplete(Needed::new(1))));
506/// assert_eq!(short_alpha(Partial::new(b"ed")), Err(ErrMode::Incomplete(Needed::new(1))));
507/// assert_eq!(short_alpha(Partial::new(b"12345")), Err(ErrMode::Backtrack(InputError::new(Partial::new(&b"12345"[..]), ErrorKind::Slice))));
508/// ```
509#[inline(always)]
510#[doc(alias = "is_a")]
511#[doc(alias = "take_while0")]
512#[doc(alias = "take_while1")]
513pub fn take_while<T, I, Error: ParserError<I>>(
514    range: impl Into<Range>,
515    list: T,
516) -> impl Parser<I, <I as Stream>::Slice, Error>
517where
518    I: StreamIsPartial,
519    I: Stream,
520    T: ContainsToken<<I as Stream>::Token>,
521{
522    let Range {
523        start_inclusive,
524        end_inclusive,
525    } = range.into();
526    trace("take_while", move |i: &mut I| {
527        match (start_inclusive, end_inclusive) {
528            (0, None) => {
529                if <I as StreamIsPartial>::is_partial_supported() {
530                    take_while0_::<_, _, _, true>(i, &list)
531                } else {
532                    take_while0_::<_, _, _, false>(i, &list)
533                }
534            }
535            (1, None) => {
536                if <I as StreamIsPartial>::is_partial_supported() {
537                    take_while1_::<_, _, _, true>(i, &list)
538                } else {
539                    take_while1_::<_, _, _, false>(i, &list)
540                }
541            }
542            (start, end) => {
543                let end = end.unwrap_or(usize::MAX);
544                if <I as StreamIsPartial>::is_partial_supported() {
545                    take_while_m_n_::<_, _, _, true>(i, start, end, &list)
546                } else {
547                    take_while_m_n_::<_, _, _, false>(i, start, end, &list)
548                }
549            }
550        }
551    })
552}
553
554fn take_while0_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
555    input: &mut I,
556    list: &T,
557) -> PResult<<I as Stream>::Slice, Error>
558where
559    I: StreamIsPartial,
560    I: Stream,
561    T: ContainsToken<<I as Stream>::Token>,
562{
563    if PARTIAL && input.is_partial() {
564        take_till0_partial(input, |c| !list.contains_token(c))
565    } else {
566        take_till0_complete(input, |c| !list.contains_token(c))
567    }
568}
569
570fn take_while1_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
571    input: &mut I,
572    list: &T,
573) -> PResult<<I as Stream>::Slice, Error>
574where
575    I: StreamIsPartial,
576    I: Stream,
577    T: ContainsToken<<I as Stream>::Token>,
578{
579    if PARTIAL && input.is_partial() {
580        take_till1_partial(input, |c| !list.contains_token(c))
581    } else {
582        take_till1_complete(input, |c| !list.contains_token(c))
583    }
584}
585
586fn take_while_m_n_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
587    input: &mut I,
588    m: usize,
589    n: usize,
590    list: &T,
591) -> PResult<<I as Stream>::Slice, Error>
592where
593    I: StreamIsPartial,
594    I: Stream,
595    T: ContainsToken<<I as Stream>::Token>,
596{
597    take_till_m_n::<_, _, _, PARTIAL>(input, m, n, |c| !list.contains_token(c))
598}
599
600/// Looks for the first element of the input type for which the condition returns true,
601/// and returns the input up to this position.
602///
603/// *Partial version*: If no element is found matching the condition, this will return `Incomplete`
604fn take_till0_partial<P, I: Stream, E: ParserError<I>>(
605    input: &mut I,
606    predicate: P,
607) -> PResult<<I as Stream>::Slice, E>
608where
609    P: Fn(I::Token) -> bool,
610{
611    let offset = input
612        .offset_for(predicate)
613        .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?;
614    Ok(input.next_slice(offset))
615}
616
617/// Looks for the first element of the input type for which the condition returns true
618/// and returns the input up to this position.
619///
620/// Fails if the produced slice is empty.
621///
622/// *Partial version*: If no element is found matching the condition, this will return `Incomplete`
623fn take_till1_partial<P, I: Stream, E: ParserError<I>>(
624    input: &mut I,
625    predicate: P,
626) -> PResult<<I as Stream>::Slice, E>
627where
628    P: Fn(I::Token) -> bool,
629{
630    let e: ErrorKind = ErrorKind::Slice;
631    let offset = input
632        .offset_for(predicate)
633        .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?;
634    if offset == 0 {
635        Err(ErrMode::from_error_kind(input, e))
636    } else {
637        Ok(input.next_slice(offset))
638    }
639}
640
641/// Looks for the first element of the input type for which the condition returns true,
642/// and returns the input up to this position.
643///
644/// *Complete version*: If no element is found matching the condition, this will return the whole input
645fn take_till0_complete<P, I: Stream, E: ParserError<I>>(
646    input: &mut I,
647    predicate: P,
648) -> PResult<<I as Stream>::Slice, E>
649where
650    P: Fn(I::Token) -> bool,
651{
652    let offset = input
653        .offset_for(predicate)
654        .unwrap_or_else(|| input.eof_offset());
655    Ok(input.next_slice(offset))
656}
657
658/// Looks for the first element of the input type for which the condition returns true
659/// and returns the input up to this position.
660///
661/// Fails if the produced slice is empty.
662///
663/// *Complete version*: If no element is found matching the condition, this will return the whole input
664fn take_till1_complete<P, I: Stream, E: ParserError<I>>(
665    input: &mut I,
666    predicate: P,
667) -> PResult<<I as Stream>::Slice, E>
668where
669    P: Fn(I::Token) -> bool,
670{
671    let e: ErrorKind = ErrorKind::Slice;
672    let offset = input
673        .offset_for(predicate)
674        .unwrap_or_else(|| input.eof_offset());
675    if offset == 0 {
676        Err(ErrMode::from_error_kind(input, e))
677    } else {
678        Ok(input.next_slice(offset))
679    }
680}
681
682fn take_till_m_n<P, I, Error: ParserError<I>, const PARTIAL: bool>(
683    input: &mut I,
684    m: usize,
685    n: usize,
686    predicate: P,
687) -> PResult<<I as Stream>::Slice, Error>
688where
689    I: StreamIsPartial,
690    I: Stream,
691    P: Fn(I::Token) -> bool,
692{
693    if n < m {
694        return Err(ErrMode::assert(input, "`m` should be <= `n`"));
695    }
696
697    let mut final_count = 0;
698    for (processed, (offset, token)) in input.iter_offsets().enumerate() {
699        if predicate(token) {
700            if processed < m {
701                return Err(ErrMode::from_error_kind(input, ErrorKind::Slice));
702            } else {
703                return Ok(input.next_slice(offset));
704            }
705        } else {
706            if processed == n {
707                return Ok(input.next_slice(offset));
708            }
709            final_count = processed + 1;
710        }
711    }
712    if PARTIAL && input.is_partial() {
713        if final_count == n {
714            Ok(input.finish())
715        } else {
716            let needed = if m > input.eof_offset() {
717                m - input.eof_offset()
718            } else {
719                1
720            };
721            Err(ErrMode::Incomplete(Needed::new(needed)))
722        }
723    } else {
724        if m <= final_count {
725            Ok(input.finish())
726        } else {
727            Err(ErrMode::from_error_kind(input, ErrorKind::Slice))
728        }
729    }
730}
731
732/// Recognize the longest input slice (if any) till a [pattern][ContainsToken] is met.
733///
734/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the match reaches the
735/// end of input or if there was not match.
736///
737/// # Example
738///
739/// ```rust
740/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
741/// # use winnow::prelude::*;
742/// use winnow::token::take_till;
743///
744/// fn till_colon(s: &str) -> IResult<&str, &str> {
745///   take_till(0.., |c| c == ':').parse_peek(s)
746/// }
747///
748/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
749/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
750/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
751/// assert_eq!(till_colon(""), Ok(("", "")));
752/// ```
753///
754/// ```rust
755/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
756/// # use winnow::prelude::*;
757/// # use winnow::Partial;
758/// use winnow::token::take_till;
759///
760/// fn till_colon(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
761///   take_till(0.., |c| c == ':').parse_peek(s)
762/// }
763///
764/// assert_eq!(till_colon(Partial::new("latin:123")), Ok((Partial::new(":123"), "latin")));
765/// assert_eq!(till_colon(Partial::new(":empty matched")), Ok((Partial::new(":empty matched"), ""))); //allowed
766/// assert_eq!(till_colon(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
767/// assert_eq!(till_colon(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
768/// ```
769#[inline(always)]
770#[doc(alias = "is_not")]
771pub fn take_till<T, I, Error: ParserError<I>>(
772    range: impl Into<Range>,
773    list: T,
774) -> impl Parser<I, <I as Stream>::Slice, Error>
775where
776    I: StreamIsPartial,
777    I: Stream,
778    T: ContainsToken<<I as Stream>::Token>,
779{
780    let Range {
781        start_inclusive,
782        end_inclusive,
783    } = range.into();
784    trace("take_till", move |i: &mut I| {
785        match (start_inclusive, end_inclusive) {
786            (0, None) => {
787                if <I as StreamIsPartial>::is_partial_supported() {
788                    take_till0_partial(i, |c| list.contains_token(c))
789                } else {
790                    take_till0_complete(i, |c| list.contains_token(c))
791                }
792            }
793            (1, None) => {
794                if <I as StreamIsPartial>::is_partial_supported() {
795                    take_till1_partial(i, |c| list.contains_token(c))
796                } else {
797                    take_till1_complete(i, |c| list.contains_token(c))
798                }
799            }
800            (start, end) => {
801                let end = end.unwrap_or(usize::MAX);
802                if <I as StreamIsPartial>::is_partial_supported() {
803                    take_till_m_n::<_, _, _, true>(i, start, end, |c| list.contains_token(c))
804                } else {
805                    take_till_m_n::<_, _, _, false>(i, start, end, |c| list.contains_token(c))
806                }
807            }
808        }
809    })
810}
811
812/// Recognize the longest input slice (if any) till a [pattern][ContainsToken] is met.
813///
814/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the match reaches the
815/// end of input or if there was not match.
816///
817/// # Example
818///
819/// ```rust
820/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
821/// # use winnow::prelude::*;
822/// use winnow::token::take_till0;
823///
824/// fn till_colon(s: &str) -> IResult<&str, &str> {
825///   take_till0(|c| c == ':').parse_peek(s)
826/// }
827///
828/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
829/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
830/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
831/// assert_eq!(till_colon(""), Ok(("", "")));
832/// ```
833///
834/// ```rust
835/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
836/// # use winnow::prelude::*;
837/// # use winnow::Partial;
838/// use winnow::token::take_till0;
839///
840/// fn till_colon(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
841///   take_till0(|c| c == ':').parse_peek(s)
842/// }
843///
844/// assert_eq!(till_colon(Partial::new("latin:123")), Ok((Partial::new(":123"), "latin")));
845/// assert_eq!(till_colon(Partial::new(":empty matched")), Ok((Partial::new(":empty matched"), ""))); //allowed
846/// assert_eq!(till_colon(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
847/// assert_eq!(till_colon(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
848/// ```
849#[deprecated(since = "0.5.21", note = "Replaced with `take_till(0.., ...)`")]
850#[inline(always)]
851pub fn take_till0<T, I, Error: ParserError<I>>(
852    list: T,
853) -> impl Parser<I, <I as Stream>::Slice, Error>
854where
855    I: StreamIsPartial,
856    I: Stream,
857    T: ContainsToken<<I as Stream>::Token>,
858{
859    trace("take_till0", move |i: &mut I| {
860        if <I as StreamIsPartial>::is_partial_supported() && i.is_partial() {
861            take_till0_partial(i, |c| list.contains_token(c))
862        } else {
863            take_till0_complete(i, |c| list.contains_token(c))
864        }
865    })
866}
867
868/// Recognize the longest (at least 1) input slice till a [pattern][ContainsToken] is met.
869///
870/// It will return `Err(ErrMode::Backtrack(InputError::new(_, ErrorKind::Slice)))` if the input is empty or the
871/// predicate matches the first input.
872///
873/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the match reaches the
874/// end of input or if there was not match.
875///
876/// # Example
877///
878/// ```rust
879/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
880/// # use winnow::prelude::*;
881/// use winnow::token::take_till1;
882///
883/// fn till_colon(s: &str) -> IResult<&str, &str> {
884///   take_till1(|c| c == ':').parse_peek(s)
885/// }
886///
887/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
888/// assert_eq!(till_colon(":empty matched"), Err(ErrMode::Backtrack(InputError::new(":empty matched", ErrorKind::Slice))));
889/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
890/// assert_eq!(till_colon(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
891///
892/// fn not_space(s: &str) -> IResult<&str, &str> {
893///   take_till1([' ', '\t', '\r', '\n']).parse_peek(s)
894/// }
895///
896/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
897/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
898/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace")));
899/// assert_eq!(not_space(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
900/// ```
901///
902/// ```rust
903/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
904/// # use winnow::prelude::*;
905/// # use winnow::Partial;
906/// use winnow::token::take_till1;
907///
908/// fn till_colon(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
909///   take_till1(|c| c == ':').parse_peek(s)
910/// }
911///
912/// assert_eq!(till_colon(Partial::new("latin:123")), Ok((Partial::new(":123"), "latin")));
913/// assert_eq!(till_colon(Partial::new(":empty matched")), Err(ErrMode::Backtrack(InputError::new(Partial::new(":empty matched"), ErrorKind::Slice))));
914/// assert_eq!(till_colon(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
915/// assert_eq!(till_colon(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
916///
917/// fn not_space(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
918///   take_till1([' ', '\t', '\r', '\n']).parse_peek(s)
919/// }
920///
921/// assert_eq!(not_space(Partial::new("Hello, World!")), Ok((Partial::new(" World!"), "Hello,")));
922/// assert_eq!(not_space(Partial::new("Sometimes\t")), Ok((Partial::new("\t"), "Sometimes")));
923/// assert_eq!(not_space(Partial::new("Nospace")), Err(ErrMode::Incomplete(Needed::new(1))));
924/// assert_eq!(not_space(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
925/// ```
926#[inline(always)]
927#[deprecated(since = "0.5.21", note = "Replaced with `take_till(1.., ...)`")]
928pub fn take_till1<T, I, Error: ParserError<I>>(
929    list: T,
930) -> impl Parser<I, <I as Stream>::Slice, Error>
931where
932    I: StreamIsPartial,
933    I: Stream,
934    T: ContainsToken<<I as Stream>::Token>,
935{
936    trace("take_till1", move |i: &mut I| {
937        if <I as StreamIsPartial>::is_partial_supported() && i.is_partial() {
938            take_till1_partial(i, |c| list.contains_token(c))
939        } else {
940            take_till1_complete(i, |c| list.contains_token(c))
941        }
942    })
943}
944
945/// Recognize an input slice containing the first N input elements (I[..N]).
946///
947/// *Complete version*: It will return `Err(ErrMode::Backtrack(InputError::new(_, ErrorKind::Slice)))` if the input is shorter than the argument.
948///
949/// *Partial version*: if the input has less than N elements, `take` will
950/// return a `ErrMode::Incomplete(Needed::new(M))` where M is the number of
951/// additional bytes the parser would need to succeed.
952/// It is well defined for `&[u8]` as the number of elements is the byte size,
953/// but for types like `&str`, we cannot know how many bytes correspond for
954/// the next few chars, so the result will be `ErrMode::Incomplete(Needed::Unknown)`
955///
956/// # Example
957///
958/// ```rust
959/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
960/// # use winnow::prelude::*;
961/// use winnow::token::take;
962///
963/// fn take6(s: &str) -> IResult<&str, &str> {
964///   take(6usize).parse_peek(s)
965/// }
966///
967/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
968/// assert_eq!(take6("things"), Ok(("", "things")));
969/// assert_eq!(take6("short"), Err(ErrMode::Backtrack(InputError::new("short", ErrorKind::Slice))));
970/// assert_eq!(take6(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
971/// ```
972///
973/// The units that are taken will depend on the input type. For example, for a
974/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
975/// take that many `u8`'s:
976///
977/// ```rust
978/// # use winnow::prelude::*;
979/// use winnow::error::InputError;
980/// use winnow::token::take;
981///
982/// assert_eq!(take::<_, _, InputError<_>>(1usize).parse_peek("💙"), Ok(("", "💙")));
983/// assert_eq!(take::<_, _, InputError<_>>(1usize).parse_peek("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
984/// ```
985///
986/// ```rust
987/// # use winnow::prelude::*;
988/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
989/// # use winnow::Partial;
990/// use winnow::token::take;
991///
992/// fn take6(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
993///   take(6usize).parse_peek(s)
994/// }
995///
996/// assert_eq!(take6(Partial::new("1234567")), Ok((Partial::new("7"), "123456")));
997/// assert_eq!(take6(Partial::new("things")), Ok((Partial::new(""), "things")));
998/// // `Unknown` as we don't know the number of bytes that `count` corresponds to
999/// assert_eq!(take6(Partial::new("short")), Err(ErrMode::Incomplete(Needed::Unknown)));
1000/// ```
1001#[inline(always)]
1002pub fn take<C, I, Error: ParserError<I>>(count: C) -> impl Parser<I, <I as Stream>::Slice, Error>
1003where
1004    I: StreamIsPartial,
1005    I: Stream,
1006    C: ToUsize,
1007{
1008    let c = count.to_usize();
1009    trace("take", move |i: &mut I| {
1010        if <I as StreamIsPartial>::is_partial_supported() {
1011            take_::<_, _, true>(i, c)
1012        } else {
1013            take_::<_, _, false>(i, c)
1014        }
1015    })
1016}
1017
1018fn take_<I, Error: ParserError<I>, const PARTIAL: bool>(
1019    i: &mut I,
1020    c: usize,
1021) -> PResult<<I as Stream>::Slice, Error>
1022where
1023    I: StreamIsPartial,
1024    I: Stream,
1025{
1026    match i.offset_at(c) {
1027        Ok(offset) => Ok(i.next_slice(offset)),
1028        Err(e) if PARTIAL && i.is_partial() => Err(ErrMode::Incomplete(e)),
1029        Err(_needed) => Err(ErrMode::from_error_kind(i, ErrorKind::Slice)),
1030    }
1031}
1032
1033/// Recognize the input slice up to the first occurrence of the literal.
1034///
1035/// It doesn't consume the pattern.
1036///
1037/// *Complete version*: It will return `Err(ErrMode::Backtrack(InputError::new(_, ErrorKind::Slice)))`
1038/// if the pattern wasn't met.
1039///
1040/// *Partial version*: will return a `ErrMode::Incomplete(Needed::new(N))` if the input doesn't
1041/// contain the pattern or if the input is smaller than the pattern.
1042///
1043/// # Example
1044///
1045/// ```rust
1046/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
1047/// # use winnow::prelude::*;
1048/// use winnow::token::take_until;
1049///
1050/// fn until_eof(s: &str) -> IResult<&str, &str> {
1051///   take_until(0.., "eof").parse_peek(s)
1052/// }
1053///
1054/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
1055/// assert_eq!(until_eof("hello, world"), Err(ErrMode::Backtrack(InputError::new("hello, world", ErrorKind::Slice))));
1056/// assert_eq!(until_eof(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
1057/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
1058/// ```
1059///
1060/// ```rust
1061/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
1062/// # use winnow::prelude::*;
1063/// # use winnow::Partial;
1064/// use winnow::token::take_until;
1065///
1066/// fn until_eof(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
1067///   take_until(0.., "eof").parse_peek(s)
1068/// }
1069///
1070/// assert_eq!(until_eof(Partial::new("hello, worldeof")), Ok((Partial::new("eof"), "hello, world")));
1071/// assert_eq!(until_eof(Partial::new("hello, world")), Err(ErrMode::Incomplete(Needed::Unknown)));
1072/// assert_eq!(until_eof(Partial::new("hello, worldeo")), Err(ErrMode::Incomplete(Needed::Unknown)));
1073/// assert_eq!(until_eof(Partial::new("1eof2eof")), Ok((Partial::new("eof2eof"), "1")));
1074/// ```
1075///
1076/// ```rust
1077/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
1078/// # use winnow::prelude::*;
1079/// use winnow::token::take_until;
1080///
1081/// fn until_eof(s: &str) -> IResult<&str, &str> {
1082///   take_until(1.., "eof").parse_peek(s)
1083/// }
1084///
1085/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
1086/// assert_eq!(until_eof("hello, world"), Err(ErrMode::Backtrack(InputError::new("hello, world", ErrorKind::Slice))));
1087/// assert_eq!(until_eof(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
1088/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
1089/// assert_eq!(until_eof("eof"), Err(ErrMode::Backtrack(InputError::new("eof", ErrorKind::Slice))));
1090/// ```
1091///
1092/// ```rust
1093/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
1094/// # use winnow::prelude::*;
1095/// # use winnow::Partial;
1096/// use winnow::token::take_until;
1097///
1098/// fn until_eof(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
1099///   take_until(1.., "eof").parse_peek(s)
1100/// }
1101///
1102/// assert_eq!(until_eof(Partial::new("hello, worldeof")), Ok((Partial::new("eof"), "hello, world")));
1103/// assert_eq!(until_eof(Partial::new("hello, world")), Err(ErrMode::Incomplete(Needed::Unknown)));
1104/// assert_eq!(until_eof(Partial::new("hello, worldeo")), Err(ErrMode::Incomplete(Needed::Unknown)));
1105/// assert_eq!(until_eof(Partial::new("1eof2eof")), Ok((Partial::new("eof2eof"), "1")));
1106/// assert_eq!(until_eof(Partial::new("eof")), Err(ErrMode::Backtrack(InputError::new(Partial::new("eof"), ErrorKind::Slice))));
1107/// ```
1108#[inline(always)]
1109pub fn take_until<T, I, Error: ParserError<I>>(
1110    range: impl Into<Range>,
1111    tag: T,
1112) -> impl Parser<I, <I as Stream>::Slice, Error>
1113where
1114    I: StreamIsPartial,
1115    I: Stream + FindSlice<T>,
1116    T: SliceLen + Clone,
1117{
1118    let Range {
1119        start_inclusive,
1120        end_inclusive,
1121    } = range.into();
1122    trace("take_until", move |i: &mut I| {
1123        match (start_inclusive, end_inclusive) {
1124            (0, None) => {
1125                if <I as StreamIsPartial>::is_partial_supported() {
1126                    take_until0_::<_, _, _, true>(i, tag.clone())
1127                } else {
1128                    take_until0_::<_, _, _, false>(i, tag.clone())
1129                }
1130            }
1131            (1, None) => {
1132                if <I as StreamIsPartial>::is_partial_supported() {
1133                    take_until1_::<_, _, _, true>(i, tag.clone())
1134                } else {
1135                    take_until1_::<_, _, _, false>(i, tag.clone())
1136                }
1137            }
1138            (start, end) => {
1139                let end = end.unwrap_or(usize::MAX);
1140                if <I as StreamIsPartial>::is_partial_supported() {
1141                    take_until_m_n_::<_, _, _, true>(i, start, end, tag.clone())
1142                } else {
1143                    take_until_m_n_::<_, _, _, false>(i, start, end, tag.clone())
1144                }
1145            }
1146        }
1147    })
1148}
1149
1150/// Deprecated, see [`take_until`]
1151#[deprecated(since = "0.5.35", note = "Replaced with `take_until`")]
1152pub fn take_until0<T, I, Error: ParserError<I>>(
1153    tag: T,
1154) -> impl Parser<I, <I as Stream>::Slice, Error>
1155where
1156    I: StreamIsPartial,
1157    I: Stream + FindSlice<T>,
1158    T: SliceLen + Clone,
1159{
1160    take_until(0.., tag)
1161}
1162
1163fn take_until0_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
1164    i: &mut I,
1165    t: T,
1166) -> PResult<<I as Stream>::Slice, Error>
1167where
1168    I: StreamIsPartial,
1169    I: Stream + FindSlice<T>,
1170    T: SliceLen,
1171{
1172    match i.find_slice(t) {
1173        Some(offset) => Ok(i.next_slice(offset)),
1174        None if PARTIAL && i.is_partial() => Err(ErrMode::Incomplete(Needed::Unknown)),
1175        None => Err(ErrMode::from_error_kind(i, ErrorKind::Slice)),
1176    }
1177}
1178
1179/// Deprecated, see [`take_until`]
1180#[deprecated(since = "0.5.35", note = "Replaced with `take_until`")]
1181#[inline(always)]
1182pub fn take_until1<T, I, Error: ParserError<I>>(
1183    tag: T,
1184) -> impl Parser<I, <I as Stream>::Slice, Error>
1185where
1186    I: StreamIsPartial,
1187    I: Stream + FindSlice<T>,
1188    T: SliceLen + Clone,
1189{
1190    take_until(1.., tag)
1191}
1192
1193fn take_until1_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
1194    i: &mut I,
1195    t: T,
1196) -> PResult<<I as Stream>::Slice, Error>
1197where
1198    I: StreamIsPartial,
1199    I: Stream + FindSlice<T>,
1200    T: SliceLen,
1201{
1202    match i.find_slice(t) {
1203        None if PARTIAL && i.is_partial() => Err(ErrMode::Incomplete(Needed::Unknown)),
1204        None | Some(0) => Err(ErrMode::from_error_kind(i, ErrorKind::Slice)),
1205        Some(offset) => Ok(i.next_slice(offset)),
1206    }
1207}
1208
1209fn take_until_m_n_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
1210    i: &mut I,
1211    start: usize,
1212    end: usize,
1213    t: T,
1214) -> PResult<<I as Stream>::Slice, Error>
1215where
1216    I: StreamIsPartial,
1217    I: Stream + FindSlice<T>,
1218    T: SliceLen,
1219{
1220    if end < start {
1221        return Err(ErrMode::assert(i, "`start` should be <= `end`"));
1222    }
1223
1224    match i.find_slice(t) {
1225        Some(offset) => {
1226            let start_offset = i.offset_at(start);
1227            let end_offset = i.offset_at(end).unwrap_or_else(|_err| i.eof_offset());
1228            if start_offset.map(|s| offset < s).unwrap_or(true) {
1229                if PARTIAL && i.is_partial() {
1230                    return Err(ErrMode::Incomplete(Needed::Unknown));
1231                } else {
1232                    return Err(ErrMode::from_error_kind(i, ErrorKind::Slice));
1233                }
1234            }
1235            if end_offset < offset {
1236                return Err(ErrMode::from_error_kind(i, ErrorKind::Slice));
1237            }
1238            Ok(i.next_slice(offset))
1239        }
1240        None if PARTIAL && i.is_partial() => Err(ErrMode::Incomplete(Needed::Unknown)),
1241        None => Err(ErrMode::from_error_kind(i, ErrorKind::Slice)),
1242    }
1243}