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