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