Coverage Report

Created: 2026-10-28 07:08

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