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