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