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