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/stream/mod.rs
Line
Count
Source
1
//! Stream capability for combinators to parse
2
//!
3
//! Stream types include:
4
//! - `&[u8]` and [`Bytes`] for binary data
5
//! - `&str` (aliased as [`Str`]) and [`BStr`] for UTF-8 data
6
//! - [`LocatingSlice`] can track the location within the original buffer to report
7
//!   [spans][crate::Parser::with_span]
8
//! - [`Stateful`] to thread global state through your parsers
9
//! - [`Partial`] can mark an input as partial buffer that is being streamed into
10
//! - [Custom stream types][crate::_topic::stream]
11
12
use core::hash::BuildHasher;
13
use core::iter::{Cloned, Enumerate};
14
use core::num::NonZeroUsize;
15
use core::slice::Iter;
16
use core::str::from_utf8;
17
use core::str::CharIndices;
18
use core::str::FromStr;
19
20
#[allow(unused_imports)]
21
#[cfg(any(feature = "unstable-doc", feature = "unstable-recover"))]
22
use crate::error::ErrMode;
23
24
#[cfg(feature = "alloc")]
25
use alloc::borrow::Cow;
26
#[cfg(feature = "alloc")]
27
use alloc::collections::BTreeMap;
28
#[cfg(feature = "alloc")]
29
use alloc::collections::BTreeSet;
30
#[cfg(feature = "alloc")]
31
use alloc::collections::VecDeque;
32
#[cfg(feature = "alloc")]
33
use alloc::string::String;
34
#[cfg(feature = "alloc")]
35
use alloc::vec::Vec;
36
#[cfg(feature = "std")]
37
use std::collections::HashMap;
38
#[cfg(feature = "std")]
39
use std::collections::HashSet;
40
41
mod bstr;
42
mod bytes;
43
mod locating;
44
mod partial;
45
mod range;
46
#[cfg(feature = "unstable-recover")]
47
#[cfg(feature = "std")]
48
mod recoverable;
49
mod stateful;
50
#[cfg(test)]
51
mod tests;
52
mod token;
53
54
pub use bstr::BStr;
55
pub use bytes::Bytes;
56
pub use locating::LocatingSlice;
57
pub use partial::Partial;
58
pub use range::Range;
59
#[cfg(feature = "unstable-recover")]
60
#[cfg(feature = "std")]
61
pub use recoverable::Recoverable;
62
pub use stateful::Stateful;
63
pub use token::TokenSlice;
64
65
/// UTF-8 Stream
66
pub type Str<'i> = &'i str;
67
68
/// Abstract method to calculate the input length
69
pub trait SliceLen {
70
    /// Calculates the input length, as indicated by its name,
71
    /// and the name of the trait itself
72
    fn slice_len(&self) -> usize;
73
}
74
75
impl<T> SliceLen for &[T] {
76
    #[inline(always)]
77
0
    fn slice_len(&self) -> usize {
78
0
        self.len()
79
0
    }
80
}
81
82
impl<T, const LEN: usize> SliceLen for [T; LEN] {
83
    #[inline(always)]
84
0
    fn slice_len(&self) -> usize {
85
0
        self.len()
86
0
    }
87
}
88
89
impl<T, const LEN: usize> SliceLen for &[T; LEN] {
90
    #[inline(always)]
91
0
    fn slice_len(&self) -> usize {
92
0
        self.len()
93
0
    }
94
}
95
96
impl SliceLen for &str {
97
    #[inline(always)]
98
0
    fn slice_len(&self) -> usize {
99
0
        self.len()
100
0
    }
101
}
102
103
impl SliceLen for u8 {
104
    #[inline(always)]
105
0
    fn slice_len(&self) -> usize {
106
0
        1
107
0
    }
108
}
109
110
impl SliceLen for char {
111
    #[inline(always)]
112
0
    fn slice_len(&self) -> usize {
113
0
        self.len_utf8()
114
0
    }
115
}
116
117
impl<I> SliceLen for (I, usize, usize)
118
where
119
    I: SliceLen,
120
{
121
    #[inline(always)]
122
0
    fn slice_len(&self) -> usize {
123
0
        self.0.slice_len() * 8 + self.2 - self.1
124
0
    }
125
}
126
127
/// Core definition for parser input state
128
pub trait Stream: Offset<<Self as Stream>::Checkpoint> + core::fmt::Debug {
129
    /// The smallest unit being parsed
130
    ///
131
    /// Example: `u8` for `&[u8]` or `char` for `&str`
132
    type Token: core::fmt::Debug;
133
    /// Sequence of `Token`s
134
    ///
135
    /// Example: `&[u8]` for `LocatingSlice<&[u8]>` or `&str` for `LocatingSlice<&str>`
136
    type Slice: core::fmt::Debug;
137
138
    /// Iterate with the offset from the current location
139
    type IterOffsets: Iterator<Item = (usize, Self::Token)>;
140
141
    /// A parse location within the stream
142
    type Checkpoint: Offset + Clone + core::fmt::Debug;
143
144
    /// Iterate with the offset from the current location
145
    fn iter_offsets(&self) -> Self::IterOffsets;
146
147
    /// Returns the offset to the end of the input
148
    fn eof_offset(&self) -> usize;
149
150
    /// Split off the next token from the input
151
    fn next_token(&mut self) -> Option<Self::Token>;
152
    /// Split off the next token from the input
153
    fn peek_token(&self) -> Option<Self::Token>;
154
155
    /// Finds the offset of the next matching token
156
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
157
    where
158
        P: Fn(Self::Token) -> bool;
159
    /// Get the offset for the number of `tokens` into the stream
160
    ///
161
    /// This means "0 tokens" will return `0` offset
162
    fn offset_at(&self, tokens: usize) -> Result<usize, Needed>;
163
    /// Split off a slice of tokens from the input
164
    ///
165
    /// <div class="warning">
166
    ///
167
    /// **Note:** For inputs with variable width tokens, like `&str`'s `char`, `offset` might not correspond
168
    /// with the number of tokens. To get a valid offset, use:
169
    /// - [`Stream::eof_offset`]
170
    /// - [`Stream::iter_offsets`]
171
    /// - [`Stream::offset_for`]
172
    /// - [`Stream::offset_at`]
173
    ///
174
    /// </div>
175
    ///
176
    /// # Panic
177
    ///
178
    /// This will panic if
179
    ///
180
    /// * Indexes must be within bounds of the original input;
181
    /// * Indexes must uphold invariants of the stream, like for `str` they must lie on UTF-8
182
    ///   sequence boundaries.
183
    ///
184
    fn next_slice(&mut self, offset: usize) -> Self::Slice;
185
    /// Split off a slice of tokens from the input
186
    ///
187
    /// <div class="warning">
188
    ///
189
    /// **Note:** For inputs with variable width tokens, like `&str`'s `char`, `offset` might not correspond
190
    /// with the number of tokens. To get a valid offset, use:
191
    /// - [`Stream::eof_offset`]
192
    /// - [`Stream::iter_offsets`]
193
    /// - [`Stream::offset_for`]
194
    /// - [`Stream::offset_at`]
195
    ///
196
    /// </div>
197
    ///
198
    /// # Safety
199
    ///
200
    /// Callers of this function are responsible that these preconditions are satisfied:
201
    ///
202
    /// * Indexes must be within bounds of the original input;
203
    /// * Indexes must uphold invariants of the stream, like for `str` they must lie on UTF-8
204
    ///   sequence boundaries.
205
    ///
206
0
    unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
207
        // Inherent impl to allow callers to have `unsafe`-free code
208
0
        self.next_slice(offset)
209
0
    }
210
    /// Split off a slice of tokens from the input
211
    fn peek_slice(&self, offset: usize) -> Self::Slice;
212
    /// Split off a slice of tokens from the input
213
    ///
214
    /// # Safety
215
    ///
216
    /// Callers of this function are responsible that these preconditions are satisfied:
217
    ///
218
    /// * Indexes must be within bounds of the original input;
219
    /// * Indexes must uphold invariants of the stream, like for `str` they must lie on UTF-8
220
    ///   sequence boundaries.
221
0
    unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
222
        // Inherent impl to allow callers to have `unsafe`-free code
223
0
        self.peek_slice(offset)
224
0
    }
225
226
    /// Advance to the end of the stream
227
    #[inline(always)]
228
1.77k
    fn finish(&mut self) -> Self::Slice {
229
1.77k
        self.next_slice(self.eof_offset())
230
1.77k
    }
<winnow::stream::locating::LocatingSlice<&str> as winnow::stream::Stream>::finish
Line
Count
Source
228
1.77k
    fn finish(&mut self) -> Self::Slice {
229
1.77k
        self.next_slice(self.eof_offset())
230
1.77k
    }
Unexecuted instantiation: <winnow::stream::token::TokenSlice<toml_parser::lexer::token::Token> as winnow::stream::Stream>::finish
Unexecuted instantiation: <_ as winnow::stream::Stream>::finish
231
    /// Advance to the end of the stream
232
    #[inline(always)]
233
0
    fn peek_finish(&self) -> Self::Slice
234
0
    where
235
0
        Self: Clone,
236
    {
237
0
        self.peek_slice(self.eof_offset())
238
0
    }
239
240
    /// Save the current parse location within the stream
241
    fn checkpoint(&self) -> Self::Checkpoint;
242
    /// Revert the stream to a prior [`Self::Checkpoint`]
243
    ///
244
    /// # Panic
245
    ///
246
    /// May panic if an invalid [`Self::Checkpoint`] is provided
247
    fn reset(&mut self, checkpoint: &Self::Checkpoint);
248
249
    /// Write out a single-line summary of the current parse location
250
    fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
251
}
252
253
/// Contains information on needed data if a parser returned `Incomplete`
254
///
255
/// <div class="warning">
256
///
257
/// **Note:** This is only possible for `Stream` that are [partial][`crate::stream::StreamIsPartial`],
258
/// like [`Partial`].
259
///
260
/// </div>
261
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
262
pub enum Needed {
263
    /// Needs more data, but we do not know how much
264
    Unknown,
265
    /// Contains a lower bound on the buffer offset needed to finish parsing
266
    ///
267
    /// For byte/`&str` streams, this translates to bytes
268
    Size(NonZeroUsize),
269
}
270
271
impl Needed {
272
    /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
273
0
    pub fn new(s: usize) -> Self {
274
0
        match NonZeroUsize::new(s) {
275
0
            Some(sz) => Needed::Size(sz),
276
0
            None => Needed::Unknown,
277
        }
278
0
    }
279
280
    /// Indicates if we know how many bytes we need
281
0
    pub fn is_known(&self) -> bool {
282
0
        *self != Needed::Unknown
283
0
    }
284
285
    /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
286
    #[inline]
287
0
    pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
288
0
        match self {
289
0
            Needed::Unknown => Needed::Unknown,
290
0
            Needed::Size(n) => Needed::new(f(n)),
291
        }
292
0
    }
293
}
294
295
impl<'i, T> Stream for &'i [T]
296
where
297
    T: Clone + core::fmt::Debug,
298
{
299
    type Token = T;
300
    type Slice = &'i [T];
301
302
    type IterOffsets = Enumerate<Cloned<Iter<'i, T>>>;
303
304
    type Checkpoint = Checkpoint<Self, Self>;
305
306
    #[inline(always)]
307
0
    fn iter_offsets(&self) -> Self::IterOffsets {
308
0
        self.iter().cloned().enumerate()
309
0
    }
310
    #[inline(always)]
311
112k
    fn eof_offset(&self) -> usize {
312
112k
        self.len()
313
112k
    }
<&[toml_parser::lexer::token::Token] as winnow::stream::Stream>::eof_offset
Line
Count
Source
311
112k
    fn eof_offset(&self) -> usize {
312
112k
        self.len()
313
112k
    }
Unexecuted instantiation: <&[_] as winnow::stream::Stream>::eof_offset
314
315
    #[inline(always)]
316
0
    fn next_token(&mut self) -> Option<Self::Token> {
317
0
        let (token, next) = self.split_first()?;
318
0
        *self = next;
319
0
        Some(token.clone())
320
0
    }
321
322
    #[inline(always)]
323
771k
    fn peek_token(&self) -> Option<Self::Token> {
324
771k
        if self.is_empty() {
325
1.40k
            None
326
        } else {
327
770k
            Some(self[0].clone())
328
        }
329
771k
    }
<&[u8] as winnow::stream::Stream>::peek_token
Line
Count
Source
323
771k
    fn peek_token(&self) -> Option<Self::Token> {
324
771k
        if self.is_empty() {
325
1.40k
            None
326
        } else {
327
770k
            Some(self[0].clone())
328
        }
329
771k
    }
Unexecuted instantiation: <&[_] as winnow::stream::Stream>::peek_token
330
331
    #[inline(always)]
332
7.38M
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
7.38M
    where
334
7.38M
        P: Fn(Self::Token) -> bool,
335
    {
336
88.9M
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::lexer::lex_whitespace::{closure#0}>::{closure#0}
Line
Count
Source
336
9.10M
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::lexer::lex_atom::{closure#0}>::{closure#0}
Line
Count
Source
336
31.3M
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::scalar::decode_datetime_or_float_or_integer::{closure#0}>::{closure#0}
Line
Count
Source
336
991k
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_invalid::{closure#0}>::{closure#0}
Line
Count
Source
336
4.38M
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::basic_invalid::{closure#0}>::{closure#0}
Line
Count
Source
336
7.02M
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_unescaped::{closure#0}>::{closure#0}
Line
Count
Source
336
19.0M
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_escaped_nl::{closure#0}>::{closure#0}
Line
Count
Source
336
480k
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_escaped_nl::{closure#1}>::{closure#0}
Line
Count
Source
336
469k
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::basic_unescaped::{closure#0}>::{closure#0}
Line
Count
Source
336
15.7M
        self.iter().position(|b| predicate(b.clone()))
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::hexescape::{closure#0}>::{closure#0}
Line
Count
Source
336
396k
        self.iter().position(|b| predicate(b.clone()))
Unexecuted instantiation: <&[_] as winnow::stream::Stream>::offset_for::<_>::{closure#0}
337
7.38M
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::lexer::lex_whitespace::{closure#0}>
Line
Count
Source
332
994k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
994k
    where
334
994k
        P: Fn(Self::Token) -> bool,
335
    {
336
994k
        self.iter().position(|b| predicate(b.clone()))
337
994k
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::lexer::lex_atom::{closure#0}>
Line
Count
Source
332
2.21M
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
2.21M
    where
334
2.21M
        P: Fn(Self::Token) -> bool,
335
    {
336
2.21M
        self.iter().position(|b| predicate(b.clone()))
337
2.21M
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_invalid::{closure#0}>
Line
Count
Source
332
790k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
790k
    where
334
790k
        P: Fn(Self::Token) -> bool,
335
    {
336
790k
        self.iter().position(|b| predicate(b.clone()))
337
790k
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::basic_invalid::{closure#0}>
Line
Count
Source
332
200k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
200k
    where
334
200k
        P: Fn(Self::Token) -> bool,
335
    {
336
200k
        self.iter().position(|b| predicate(b.clone()))
337
200k
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_unescaped::{closure#0}>
Line
Count
Source
332
1.79M
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
1.79M
    where
334
1.79M
        P: Fn(Self::Token) -> bool,
335
    {
336
1.79M
        self.iter().position(|b| predicate(b.clone()))
337
1.79M
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_escaped_nl::{closure#0}>
Line
Count
Source
332
356k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
356k
    where
334
356k
        P: Fn(Self::Token) -> bool,
335
    {
336
356k
        self.iter().position(|b| predicate(b.clone()))
337
356k
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::mlb_escaped_nl::{closure#1}>
Line
Count
Source
332
449k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
449k
    where
334
449k
        P: Fn(Self::Token) -> bool,
335
    {
336
449k
        self.iter().position(|b| predicate(b.clone()))
337
449k
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::basic_unescaped::{closure#0}>
Line
Count
Source
332
450k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
450k
    where
334
450k
        P: Fn(Self::Token) -> bool,
335
    {
336
450k
        self.iter().position(|b| predicate(b.clone()))
337
450k
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::string::hexescape::{closure#0}>
Line
Count
Source
332
20.8k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
20.8k
    where
334
20.8k
        P: Fn(Self::Token) -> bool,
335
    {
336
20.8k
        self.iter().position(|b| predicate(b.clone()))
337
20.8k
    }
<&[u8] as winnow::stream::Stream>::offset_for::<toml_parser::decoder::scalar::decode_datetime_or_float_or_integer::{closure#0}>
Line
Count
Source
332
112k
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
333
112k
    where
334
112k
        P: Fn(Self::Token) -> bool,
335
    {
336
112k
        self.iter().position(|b| predicate(b.clone()))
337
112k
    }
Unexecuted instantiation: <&[_] as winnow::stream::Stream>::offset_for::<_>
338
    #[inline(always)]
339
0
    fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
340
0
        if let Some(needed) = tokens.checked_sub(self.len()).and_then(NonZeroUsize::new) {
341
0
            Err(Needed::Size(needed))
342
        } else {
343
0
            Ok(tokens)
344
        }
345
0
    }
346
    #[inline(always)]
347
196k
    fn next_slice(&mut self, offset: usize) -> Self::Slice {
348
196k
        let (slice, next) = self.split_at(offset);
349
196k
        *self = next;
350
196k
        slice
351
196k
    }
<&[toml_parser::lexer::token::Token] as winnow::stream::Stream>::next_slice
Line
Count
Source
347
196k
    fn next_slice(&mut self, offset: usize) -> Self::Slice {
348
196k
        let (slice, next) = self.split_at(offset);
349
196k
        *self = next;
350
196k
        slice
351
196k
    }
Unexecuted instantiation: <&[_] as winnow::stream::Stream>::next_slice
352
    #[inline(always)]
353
0
    unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
354
        #[cfg(debug_assertions)]
355
        self.peek_slice(offset);
356
357
        // SAFETY: `Stream::next_slice_unchecked` requires `offset` to be in bounds
358
0
        let slice = unsafe { self.get_unchecked(..offset) };
359
        // SAFETY: `Stream::next_slice_unchecked` requires `offset` to be in bounds
360
0
        let next = unsafe { self.get_unchecked(offset..) };
361
0
        *self = next;
362
0
        slice
363
0
    }
364
    #[inline(always)]
365
0
    fn peek_slice(&self, offset: usize) -> Self::Slice {
366
0
        &self[..offset]
367
0
    }
368
    #[inline(always)]
369
0
    unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
370
        #[cfg(debug_assertions)]
371
        self.peek_slice(offset);
372
373
        // SAFETY: `Stream::next_slice_unchecked` requires `offset` to be in bounds
374
0
        let slice = unsafe { self.get_unchecked(..offset) };
375
0
        slice
376
0
    }
377
378
    #[inline(always)]
379
112k
    fn checkpoint(&self) -> Self::Checkpoint {
380
112k
        Checkpoint::<_, Self>::new(*self)
381
112k
    }
<&[toml_parser::lexer::token::Token] as winnow::stream::Stream>::checkpoint
Line
Count
Source
379
112k
    fn checkpoint(&self) -> Self::Checkpoint {
380
112k
        Checkpoint::<_, Self>::new(*self)
381
112k
    }
Unexecuted instantiation: <&[_] as winnow::stream::Stream>::checkpoint
382
    #[inline(always)]
383
112k
    fn reset(&mut self, checkpoint: &Self::Checkpoint) {
384
112k
        *self = checkpoint.inner;
385
112k
    }
<&[toml_parser::lexer::token::Token] as winnow::stream::Stream>::reset
Line
Count
Source
383
112k
    fn reset(&mut self, checkpoint: &Self::Checkpoint) {
384
112k
        *self = checkpoint.inner;
385
112k
    }
Unexecuted instantiation: <&[_] as winnow::stream::Stream>::reset
386
387
0
    fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
388
0
        write!(f, "{self:?}")
389
0
    }
390
}
391
392
impl<'i> Stream for &'i str {
393
    type Token = char;
394
    type Slice = &'i str;
395
396
    type IterOffsets = CharIndices<'i>;
397
398
    type Checkpoint = Checkpoint<Self, Self>;
399
400
    #[inline(always)]
401
0
    fn iter_offsets(&self) -> Self::IterOffsets {
402
0
        self.char_indices()
403
0
    }
404
    #[inline(always)]
405
1.00M
    fn eof_offset(&self) -> usize {
406
1.00M
        self.len()
407
1.00M
    }
408
409
    #[inline(always)]
410
1.54M
    fn next_token(&mut self) -> Option<Self::Token> {
411
1.54M
        let mut iter = self.chars();
412
1.54M
        let c = iter.next()?;
413
1.54M
        *self = iter.as_str();
414
1.54M
        Some(c)
415
1.54M
    }
416
417
    #[inline(always)]
418
0
    fn peek_token(&self) -> Option<Self::Token> {
419
0
        self.chars().next()
420
0
    }
421
422
    #[inline(always)]
423
0
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
424
0
    where
425
0
        P: Fn(Self::Token) -> bool,
426
    {
427
0
        for (o, c) in self.iter_offsets() {
428
0
            if predicate(c) {
429
0
                return Some(o);
430
0
            }
431
        }
432
0
        None
433
0
    }
434
    #[inline]
435
0
    fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
436
0
        let mut cnt = 0;
437
0
        for (offset, _) in self.iter_offsets() {
438
0
            if cnt == tokens {
439
0
                return Ok(offset);
440
0
            }
441
0
            cnt += 1;
442
        }
443
444
0
        if cnt == tokens {
445
0
            Ok(self.eof_offset())
446
        } else {
447
0
            Err(Needed::Unknown)
448
        }
449
0
    }
450
    #[inline(always)]
451
21.5M
    fn next_slice(&mut self, offset: usize) -> Self::Slice {
452
21.5M
        let (slice, next) = self.split_at(offset);
453
21.5M
        *self = next;
454
21.5M
        slice
455
21.5M
    }
456
    #[inline(always)]
457
0
    unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
458
        #[cfg(debug_assertions)]
459
        self.peek_slice(offset);
460
461
        // SAFETY: `Stream::next_slice_unchecked` requires `offset` to be in bounds and on a UTF-8
462
        // sequence boundary
463
0
        let slice = unsafe { self.get_unchecked(..offset) };
464
        // SAFETY: `Stream::next_slice_unchecked` requires `offset` to be in bounds and on a UTF-8
465
        // sequence boundary
466
0
        let next = unsafe { self.get_unchecked(offset..) };
467
0
        *self = next;
468
0
        slice
469
0
    }
470
    #[inline(always)]
471
0
    fn peek_slice(&self, offset: usize) -> Self::Slice {
472
0
        &self[..offset]
473
0
    }
474
    #[inline(always)]
475
0
    unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
476
        #[cfg(debug_assertions)]
477
        self.peek_slice(offset);
478
479
        // SAFETY: `Stream::next_slice_unchecked` requires `offset` to be in bounds
480
0
        let slice = unsafe { self.get_unchecked(..offset) };
481
0
        slice
482
0
    }
483
484
    #[inline(always)]
485
584k
    fn checkpoint(&self) -> Self::Checkpoint {
486
584k
        Checkpoint::<_, Self>::new(*self)
487
584k
    }
488
    #[inline(always)]
489
94.4k
    fn reset(&mut self, checkpoint: &Self::Checkpoint) {
490
94.4k
        *self = checkpoint.inner;
491
94.4k
    }
492
493
0
    fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
494
0
        write!(f, "{self:#?}")
495
0
    }
496
}
497
498
/// Current parse locations offset
499
///
500
/// See [`LocatingSlice`] for adding location tracking to your [`Stream`]
501
pub trait Location {
502
    /// Previous token's end offset
503
    fn previous_token_end(&self) -> usize;
504
    /// Current token's start offset
505
    fn current_token_start(&self) -> usize;
506
}
507
508
/// Capture top-level errors in the middle of parsing so parsing can resume
509
///
510
/// See [`Recoverable`] for adding error recovery tracking to your [`Stream`]
511
#[cfg(feature = "unstable-recover")]
512
#[cfg(feature = "std")]
513
pub trait Recover<E>: Stream {
514
    /// Capture a top-level error
515
    ///
516
    /// May return `Err(err)` if recovery is not possible (e.g. if [`Recover::is_recovery_supported`]
517
    /// returns `false`).
518
    fn record_err(
519
        &mut self,
520
        token_start: &Self::Checkpoint,
521
        err_start: &Self::Checkpoint,
522
        err: E,
523
    ) -> Result<(), E>;
524
525
    /// Report whether the [`Stream`] can save off errors for recovery
526
    fn is_recovery_supported() -> bool;
527
}
528
529
#[cfg(feature = "unstable-recover")]
530
#[cfg(feature = "std")]
531
impl<'a, T, E> Recover<E> for &'a [T]
532
where
533
    &'a [T]: Stream,
534
{
535
    #[inline(always)]
536
    fn record_err(
537
        &mut self,
538
        _token_start: &Self::Checkpoint,
539
        _err_start: &Self::Checkpoint,
540
        err: E,
541
    ) -> Result<(), E> {
542
        Err(err)
543
    }
544
545
    /// Report whether the [`Stream`] can save off errors for recovery
546
    #[inline(always)]
547
    fn is_recovery_supported() -> bool {
548
        false
549
    }
550
}
551
552
#[cfg(feature = "unstable-recover")]
553
#[cfg(feature = "std")]
554
impl<E> Recover<E> for &str {
555
    #[inline(always)]
556
    fn record_err(
557
        &mut self,
558
        _token_start: &Self::Checkpoint,
559
        _err_start: &Self::Checkpoint,
560
        err: E,
561
    ) -> Result<(), E> {
562
        Err(err)
563
    }
564
565
    /// Report whether the [`Stream`] can save off errors for recovery
566
    #[inline(always)]
567
    fn is_recovery_supported() -> bool {
568
        false
569
    }
570
}
571
572
/// Marks the input as being the complete buffer or a partial buffer for streaming input
573
///
574
/// See [`Partial`] for marking a presumed complete buffer type as a streaming buffer.
575
pub trait StreamIsPartial: Sized {
576
    /// Whether the stream is currently partial or complete
577
    type PartialState;
578
579
    /// Mark the stream is complete
580
    #[must_use]
581
    fn complete(&mut self) -> Self::PartialState;
582
583
    /// Restore the stream back to its previous state
584
    fn restore_partial(&mut self, state: Self::PartialState);
585
586
    /// Report whether the [`Stream`] is can ever be incomplete
587
    fn is_partial_supported() -> bool;
588
589
    /// Report whether the [`Stream`] is currently incomplete
590
    #[inline(always)]
591
0
    fn is_partial(&self) -> bool {
592
0
        Self::is_partial_supported()
593
0
    }
594
}
595
596
impl<T> StreamIsPartial for &[T] {
597
    type PartialState = ();
598
599
    #[inline]
600
0
    fn complete(&mut self) -> Self::PartialState {}
601
602
    #[inline]
603
0
    fn restore_partial(&mut self, _state: Self::PartialState) {}
604
605
    #[inline(always)]
606
0
    fn is_partial_supported() -> bool {
607
0
        false
608
0
    }
609
}
610
611
impl StreamIsPartial for &str {
612
    type PartialState = ();
613
614
    #[inline]
615
0
    fn complete(&mut self) -> Self::PartialState {
616
        // Already complete
617
0
    }
618
619
    #[inline]
620
0
    fn restore_partial(&mut self, _state: Self::PartialState) {}
621
622
    #[inline(always)]
623
0
    fn is_partial_supported() -> bool {
624
0
        false
625
0
    }
626
}
627
628
/// Useful functions to calculate the offset between slices and show a hexdump of a slice
629
pub trait Offset<Start = Self> {
630
    /// Offset between the first byte of `start` and the first byte of `self`a
631
    ///
632
    /// <div class="warning">
633
    ///
634
    /// **Note:** This is an offset, not an index, and may point to the end of input
635
    /// (`start.len()`) when `self` is exhausted.
636
    ///
637
    /// </div>
638
    fn offset_from(&self, start: &Start) -> usize;
639
}
640
641
impl<T> Offset for &[T] {
642
    #[inline]
643
33.7M
    fn offset_from(&self, start: &Self) -> usize {
644
33.7M
        let fst = (*start).as_ptr();
645
33.7M
        let snd = (*self).as_ptr();
646
647
33.7M
        debug_assert!(
648
0
            fst <= snd,
649
            "`Offset::offset_from({snd:?}, {fst:?})` only accepts slices of `self`"
650
        );
651
33.7M
        (snd as usize - fst as usize) / core::mem::size_of::<T>()
652
33.7M
    }
<&[toml_parser::lexer::token::Token] as winnow::stream::Offset>::offset_from
Line
Count
Source
643
212k
    fn offset_from(&self, start: &Self) -> usize {
644
212k
        let fst = (*start).as_ptr();
645
212k
        let snd = (*self).as_ptr();
646
647
212k
        debug_assert!(
648
0
            fst <= snd,
649
            "`Offset::offset_from({snd:?}, {fst:?})` only accepts slices of `self`"
650
        );
651
212k
        (snd as usize - fst as usize) / core::mem::size_of::<T>()
652
212k
    }
<&[u8] as winnow::stream::Offset>::offset_from
Line
Count
Source
643
33.5M
    fn offset_from(&self, start: &Self) -> usize {
644
33.5M
        let fst = (*start).as_ptr();
645
33.5M
        let snd = (*self).as_ptr();
646
647
33.5M
        debug_assert!(
648
0
            fst <= snd,
649
            "`Offset::offset_from({snd:?}, {fst:?})` only accepts slices of `self`"
650
        );
651
33.5M
        (snd as usize - fst as usize) / core::mem::size_of::<T>()
652
33.5M
    }
Unexecuted instantiation: <&[_] as winnow::stream::Offset>::offset_from
653
}
654
655
impl<'a, T> Offset<<&'a [T] as Stream>::Checkpoint> for &'a [T]
656
where
657
    T: Clone + core::fmt::Debug,
658
{
659
    #[inline(always)]
660
0
    fn offset_from(&self, other: &<&'a [T] as Stream>::Checkpoint) -> usize {
661
0
        self.checkpoint().offset_from(other)
662
0
    }
663
}
664
665
impl Offset for &str {
666
    #[inline(always)]
667
33.2M
    fn offset_from(&self, start: &Self) -> usize {
668
33.2M
        self.as_bytes().offset_from(&start.as_bytes())
669
33.2M
    }
670
}
671
672
impl<'a> Offset<<&'a str as Stream>::Checkpoint> for &'a str {
673
    #[inline(always)]
674
0
    fn offset_from(&self, other: &<&'a str as Stream>::Checkpoint) -> usize {
675
0
        self.checkpoint().offset_from(other)
676
0
    }
677
}
678
679
impl<I, S> Offset for Checkpoint<I, S>
680
where
681
    I: Offset,
682
{
683
    #[inline(always)]
684
112k
    fn offset_from(&self, start: &Self) -> usize {
685
112k
        self.inner.offset_from(&start.inner)
686
112k
    }
<winnow::stream::Checkpoint<&[toml_parser::lexer::token::Token], winnow::stream::token::TokenSlice<toml_parser::lexer::token::Token>> as winnow::stream::Offset>::offset_from
Line
Count
Source
684
112k
    fn offset_from(&self, start: &Self) -> usize {
685
112k
        self.inner.offset_from(&start.inner)
686
112k
    }
Unexecuted instantiation: <winnow::stream::Checkpoint<_, _> as winnow::stream::Offset>::offset_from
687
}
688
689
/// Helper trait for types that can be viewed as a byte slice
690
pub trait AsBytes {
691
    /// Casts the input type to a byte slice
692
    fn as_bytes(&self) -> &[u8];
693
}
694
695
impl AsBytes for &[u8] {
696
    #[inline(always)]
697
0
    fn as_bytes(&self) -> &[u8] {
698
0
        self
699
0
    }
700
}
701
702
/// Helper trait for types that can be viewed as a byte slice
703
pub trait AsBStr {
704
    /// Casts the input type to a byte slice
705
    fn as_bstr(&self) -> &[u8];
706
}
707
708
impl AsBStr for &[u8] {
709
    #[inline(always)]
710
0
    fn as_bstr(&self) -> &[u8] {
711
0
        self
712
0
    }
713
}
714
715
impl AsBStr for &str {
716
    #[inline(always)]
717
23.1M
    fn as_bstr(&self) -> &[u8] {
718
23.1M
        (*self).as_bytes()
719
23.1M
    }
720
}
721
722
/// Result of [`Compare::compare`]
723
#[derive(Debug, Eq, PartialEq)]
724
pub enum CompareResult {
725
    /// Comparison was successful
726
    ///
727
    /// `usize` is the end of the successful match within the buffer.
728
    /// This is most relevant for caseless UTF-8 where `Compare::compare`'s parameter might be a different
729
    /// length than the match within the buffer.
730
    Ok(usize),
731
    /// We need more data to be sure
732
    Incomplete,
733
    /// Comparison failed
734
    Error,
735
}
736
737
/// Abstracts comparison operations
738
pub trait Compare<T> {
739
    /// Compares self to another value for equality
740
    fn compare(&self, t: T) -> CompareResult;
741
}
742
743
impl<'b> Compare<&'b [u8]> for &[u8] {
744
    #[inline]
745
0
    fn compare(&self, t: &'b [u8]) -> CompareResult {
746
0
        if t.iter().zip(*self).any(|(a, b)| a != b) {
747
0
            CompareResult::Error
748
0
        } else if self.len() < t.slice_len() {
749
0
            CompareResult::Incomplete
750
        } else {
751
0
            CompareResult::Ok(t.slice_len())
752
        }
753
0
    }
754
}
755
756
impl<const LEN: usize> Compare<[u8; LEN]> for &[u8] {
757
    #[inline(always)]
758
0
    fn compare(&self, t: [u8; LEN]) -> CompareResult {
759
0
        self.compare(&t[..])
760
0
    }
761
}
762
763
impl<'b, const LEN: usize> Compare<&'b [u8; LEN]> for &[u8] {
764
    #[inline(always)]
765
0
    fn compare(&self, t: &'b [u8; LEN]) -> CompareResult {
766
0
        self.compare(&t[..])
767
0
    }
768
}
769
770
impl<'b> Compare<&'b str> for &[u8] {
771
    #[inline(always)]
772
0
    fn compare(&self, t: &'b str) -> CompareResult {
773
0
        self.compare(t.as_bytes())
774
0
    }
775
}
776
777
impl Compare<u8> for &[u8] {
778
    #[inline]
779
0
    fn compare(&self, t: u8) -> CompareResult {
780
0
        match self.first().copied() {
781
0
            Some(c) if t == c => CompareResult::Ok(t.slice_len()),
782
0
            Some(_) => CompareResult::Error,
783
0
            None => CompareResult::Incomplete,
784
        }
785
0
    }
786
}
787
788
impl Compare<char> for &[u8] {
789
    #[inline(always)]
790
0
    fn compare(&self, t: char) -> CompareResult {
791
0
        self.compare(t.encode_utf8(&mut [0; 4]).as_bytes())
792
0
    }
793
}
794
795
impl<'b> Compare<&'b str> for &str {
796
    #[inline(always)]
797
0
    fn compare(&self, t: &'b str) -> CompareResult {
798
0
        self.as_bytes().compare(t.as_bytes())
799
0
    }
800
}
801
802
impl Compare<char> for &str {
803
    #[inline(always)]
804
0
    fn compare(&self, t: char) -> CompareResult {
805
0
        self.as_bytes().compare(t)
806
0
    }
807
}
808
809
/// Look for a slice in self
810
pub trait FindSlice<T> {
811
    /// Returns the offset of the slice if it is found
812
    fn find_slice(&self, substr: T) -> Option<core::ops::Range<usize>>;
813
}
814
815
impl<'s> FindSlice<&'s [u8]> for &[u8] {
816
    #[inline(always)]
817
271k
    fn find_slice(&self, substr: &'s [u8]) -> Option<core::ops::Range<usize>> {
818
271k
        memmem(self, substr)
819
271k
    }
820
}
821
822
impl<'s> FindSlice<(&'s [u8],)> for &[u8] {
823
    #[inline(always)]
824
0
    fn find_slice(&self, substr: (&'s [u8],)) -> Option<core::ops::Range<usize>> {
825
0
        memmem(self, substr.0)
826
0
    }
827
}
828
829
impl<'s> FindSlice<(&'s [u8], &'s [u8])> for &[u8] {
830
    #[inline(always)]
831
0
    fn find_slice(&self, substr: (&'s [u8], &'s [u8])) -> Option<core::ops::Range<usize>> {
832
0
        memmem2(self, substr)
833
0
    }
834
}
835
836
impl<'s> FindSlice<(&'s [u8], &'s [u8], &'s [u8])> for &[u8] {
837
    #[inline(always)]
838
0
    fn find_slice(
839
0
        &self,
840
0
        substr: (&'s [u8], &'s [u8], &'s [u8]),
841
0
    ) -> Option<core::ops::Range<usize>> {
842
0
        memmem3(self, substr)
843
0
    }
844
}
845
846
impl FindSlice<char> for &[u8] {
847
    #[inline(always)]
848
0
    fn find_slice(&self, substr: char) -> Option<core::ops::Range<usize>> {
849
0
        let mut b = [0; 4];
850
0
        let substr = substr.encode_utf8(&mut b);
851
0
        self.find_slice(&*substr)
852
0
    }
853
}
854
855
impl FindSlice<(char,)> for &[u8] {
856
    #[inline(always)]
857
0
    fn find_slice(&self, substr: (char,)) -> Option<core::ops::Range<usize>> {
858
0
        let mut b = [0; 4];
859
0
        let substr0 = substr.0.encode_utf8(&mut b);
860
0
        self.find_slice((&*substr0,))
861
0
    }
862
}
863
864
impl FindSlice<(char, char)> for &[u8] {
865
    #[inline(always)]
866
0
    fn find_slice(&self, substr: (char, char)) -> Option<core::ops::Range<usize>> {
867
0
        let mut b = [0; 4];
868
0
        let substr0 = substr.0.encode_utf8(&mut b);
869
0
        let mut b = [0; 4];
870
0
        let substr1 = substr.1.encode_utf8(&mut b);
871
0
        self.find_slice((&*substr0, &*substr1))
872
0
    }
873
}
874
875
impl FindSlice<(char, char, char)> for &[u8] {
876
    #[inline(always)]
877
0
    fn find_slice(&self, substr: (char, char, char)) -> Option<core::ops::Range<usize>> {
878
0
        let mut b = [0; 4];
879
0
        let substr0 = substr.0.encode_utf8(&mut b);
880
0
        let mut b = [0; 4];
881
0
        let substr1 = substr.1.encode_utf8(&mut b);
882
0
        let mut b = [0; 4];
883
0
        let substr2 = substr.2.encode_utf8(&mut b);
884
0
        self.find_slice((&*substr0, &*substr1, &*substr2))
885
0
    }
886
}
887
888
impl FindSlice<u8> for &[u8] {
889
    #[inline(always)]
890
0
    fn find_slice(&self, substr: u8) -> Option<core::ops::Range<usize>> {
891
0
        memchr(substr, self).map(|i| i..i + 1)
892
0
    }
893
}
894
895
impl FindSlice<(u8,)> for &[u8] {
896
    #[inline(always)]
897
0
    fn find_slice(&self, substr: (u8,)) -> Option<core::ops::Range<usize>> {
898
0
        memchr(substr.0, self).map(|i| i..i + 1)
899
0
    }
900
}
901
902
impl FindSlice<(u8, u8)> for &[u8] {
903
    #[inline(always)]
904
74.1k
    fn find_slice(&self, substr: (u8, u8)) -> Option<core::ops::Range<usize>> {
905
74.1k
        memchr2(substr, self).map(|i| i..i + 1)
<&[u8] as winnow::stream::FindSlice<(u8, u8)>>::find_slice::{closure#0}
Line
Count
Source
905
73.6k
        memchr2(substr, self).map(|i| i..i + 1)
Unexecuted instantiation: <&[u8] as winnow::stream::FindSlice<(u8, u8)>>::find_slice::{closure#0}
906
74.1k
    }
907
}
908
909
impl FindSlice<(u8, u8, u8)> for &[u8] {
910
    #[inline(always)]
911
534k
    fn find_slice(&self, substr: (u8, u8, u8)) -> Option<core::ops::Range<usize>> {
912
534k
        memchr3(substr, self).map(|i| i..i + 1)
<&[u8] as winnow::stream::FindSlice<(u8, u8, u8)>>::find_slice::{closure#0}
Line
Count
Source
912
501k
        memchr3(substr, self).map(|i| i..i + 1)
Unexecuted instantiation: <&[u8] as winnow::stream::FindSlice<(u8, u8, u8)>>::find_slice::{closure#0}
913
534k
    }
914
}
915
916
impl<'s> FindSlice<&'s str> for &[u8] {
917
    #[inline(always)]
918
271k
    fn find_slice(&self, substr: &'s str) -> Option<core::ops::Range<usize>> {
919
271k
        self.find_slice(substr.as_bytes())
920
271k
    }
921
}
922
923
impl<'s> FindSlice<(&'s str,)> for &[u8] {
924
    #[inline(always)]
925
0
    fn find_slice(&self, substr: (&'s str,)) -> Option<core::ops::Range<usize>> {
926
0
        memmem(self, substr.0.as_bytes())
927
0
    }
928
}
929
930
impl<'s> FindSlice<(&'s str, &'s str)> for &[u8] {
931
    #[inline(always)]
932
578k
    fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<core::ops::Range<usize>> {
933
578k
        memmem2(self, (substr.0.as_bytes(), substr.1.as_bytes()))
934
578k
    }
935
}
936
937
impl<'s> FindSlice<(&'s str, &'s str, &'s str)> for &[u8] {
938
    #[inline(always)]
939
0
    fn find_slice(&self, substr: (&'s str, &'s str, &'s str)) -> Option<core::ops::Range<usize>> {
940
0
        memmem3(
941
0
            self,
942
0
            (
943
0
                substr.0.as_bytes(),
944
0
                substr.1.as_bytes(),
945
0
                substr.2.as_bytes(),
946
0
            ),
947
        )
948
0
    }
949
}
950
951
impl<'s> FindSlice<&'s str> for &str {
952
    #[inline(always)]
953
241k
    fn find_slice(&self, substr: &'s str) -> Option<core::ops::Range<usize>> {
954
241k
        self.as_bytes().find_slice(substr)
955
241k
    }
956
}
957
958
impl<'s> FindSlice<(&'s str,)> for &str {
959
    #[inline(always)]
960
0
    fn find_slice(&self, substr: (&'s str,)) -> Option<core::ops::Range<usize>> {
961
0
        self.as_bytes().find_slice(substr)
962
0
    }
963
}
964
965
impl<'s> FindSlice<(&'s str, &'s str)> for &str {
966
    #[inline(always)]
967
0
    fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<core::ops::Range<usize>> {
968
0
        self.as_bytes().find_slice(substr)
969
0
    }
970
}
971
972
impl<'s> FindSlice<(&'s str, &'s str, &'s str)> for &str {
973
    #[inline(always)]
974
0
    fn find_slice(&self, substr: (&'s str, &'s str, &'s str)) -> Option<core::ops::Range<usize>> {
975
0
        self.as_bytes().find_slice(substr)
976
0
    }
977
}
978
979
impl FindSlice<char> for &str {
980
    #[inline(always)]
981
0
    fn find_slice(&self, substr: char) -> Option<core::ops::Range<usize>> {
982
0
        self.as_bytes().find_slice(substr)
983
0
    }
984
}
985
986
impl FindSlice<(char,)> for &str {
987
    #[inline(always)]
988
0
    fn find_slice(&self, substr: (char,)) -> Option<core::ops::Range<usize>> {
989
0
        self.as_bytes().find_slice(substr)
990
0
    }
991
}
992
993
impl FindSlice<(char, char)> for &str {
994
    #[inline(always)]
995
0
    fn find_slice(&self, substr: (char, char)) -> Option<core::ops::Range<usize>> {
996
0
        self.as_bytes().find_slice(substr)
997
0
    }
998
}
999
1000
impl FindSlice<(char, char, char)> for &str {
1001
    #[inline(always)]
1002
0
    fn find_slice(&self, substr: (char, char, char)) -> Option<core::ops::Range<usize>> {
1003
0
        self.as_bytes().find_slice(substr)
1004
0
    }
1005
}
1006
1007
/// Used to integrate `str`'s `parse()` method
1008
pub trait ParseSlice<R> {
1009
    /// Succeeds if `parse()` succeeded
1010
    ///
1011
    /// The byte slice implementation will first convert it to a `&str`, then apply the `parse()`
1012
    /// function
1013
    fn parse_slice(&self) -> Option<R>;
1014
}
1015
1016
impl<R: FromStr> ParseSlice<R> for &[u8] {
1017
    #[inline(always)]
1018
0
    fn parse_slice(&self) -> Option<R> {
1019
0
        from_utf8(self).ok().and_then(|s| s.parse().ok())
1020
0
    }
1021
}
1022
1023
impl<R: FromStr> ParseSlice<R> for &str {
1024
    #[inline(always)]
1025
0
    fn parse_slice(&self) -> Option<R> {
1026
0
        self.parse().ok()
1027
0
    }
1028
}
1029
1030
/// Convert a `Stream` into an appropriate `Output` type
1031
pub trait UpdateSlice: Stream {
1032
    /// Convert an `Output` type to be used as `Stream`
1033
    fn update_slice(self, inner: Self::Slice) -> Self;
1034
}
1035
1036
impl<T> UpdateSlice for &[T]
1037
where
1038
    T: Clone + core::fmt::Debug,
1039
{
1040
    #[inline(always)]
1041
0
    fn update_slice(self, inner: Self::Slice) -> Self {
1042
0
        inner
1043
0
    }
1044
}
1045
1046
impl UpdateSlice for &str {
1047
    #[inline(always)]
1048
0
    fn update_slice(self, inner: Self::Slice) -> Self {
1049
0
        inner
1050
0
    }
1051
}
1052
1053
/// Ensure checkpoint details are kept private
1054
pub struct Checkpoint<T, S> {
1055
    pub(crate) inner: T,
1056
    stream: core::marker::PhantomData<S>,
1057
}
1058
1059
impl<T, S> Checkpoint<T, S> {
1060
921k
    pub(crate) fn new(inner: T) -> Self {
1061
921k
        Self {
1062
921k
            inner,
1063
921k
            stream: Default::default(),
1064
921k
        }
1065
921k
    }
<winnow::stream::Checkpoint<&[toml_parser::lexer::token::Token], &[toml_parser::lexer::token::Token]>>::new
Line
Count
Source
1060
112k
    pub(crate) fn new(inner: T) -> Self {
1061
112k
        Self {
1062
112k
            inner,
1063
112k
            stream: Default::default(),
1064
112k
        }
1065
112k
    }
<winnow::stream::Checkpoint<&[toml_parser::lexer::token::Token], winnow::stream::token::TokenSlice<toml_parser::lexer::token::Token>>>::new
Line
Count
Source
1060
224k
    pub(crate) fn new(inner: T) -> Self {
1061
224k
        Self {
1062
224k
            inner,
1063
224k
            stream: Default::default(),
1064
224k
        }
1065
224k
    }
<winnow::stream::Checkpoint<&str, &str>>::new
Line
Count
Source
1060
584k
    pub(crate) fn new(inner: T) -> Self {
1061
584k
        Self {
1062
584k
            inner,
1063
584k
            stream: Default::default(),
1064
584k
        }
1065
584k
    }
Unexecuted instantiation: <winnow::stream::Checkpoint<_, _>>::new
1066
}
1067
1068
impl<T: Copy, S> Copy for Checkpoint<T, S> {}
1069
1070
impl<T: Clone, S> Clone for Checkpoint<T, S> {
1071
    #[inline(always)]
1072
0
    fn clone(&self) -> Self {
1073
0
        Self {
1074
0
            inner: self.inner.clone(),
1075
0
            stream: Default::default(),
1076
0
        }
1077
0
    }
1078
}
1079
1080
impl<T: PartialOrd, S> PartialOrd for Checkpoint<T, S> {
1081
    #[inline(always)]
1082
0
    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
1083
0
        self.inner.partial_cmp(&other.inner)
1084
0
    }
1085
}
1086
1087
impl<T: Ord, S> Ord for Checkpoint<T, S> {
1088
    #[inline(always)]
1089
0
    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1090
0
        self.inner.cmp(&other.inner)
1091
0
    }
1092
}
1093
1094
impl<T: PartialEq, S> PartialEq for Checkpoint<T, S> {
1095
    #[inline(always)]
1096
0
    fn eq(&self, other: &Self) -> bool {
1097
0
        self.inner.eq(&other.inner)
1098
0
    }
1099
}
1100
1101
impl<T: Eq, S> Eq for Checkpoint<T, S> {}
1102
1103
impl<T: core::fmt::Debug, S> core::fmt::Debug for Checkpoint<T, S> {
1104
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1105
0
        self.inner.fmt(f)
1106
0
    }
1107
}
1108
1109
/// Abstracts something which can extend an `Extend`.
1110
///
1111
/// Used to build modified input slices in [`escaped`][crate::ascii::escaped].
1112
pub trait Accumulate<T>: Sized {
1113
    /// Create a new `Extend` of the correct type
1114
    fn initial(capacity: Option<usize>) -> Self;
1115
    /// Accumulate the input into an accumulator
1116
    fn accumulate(&mut self, acc: T);
1117
}
1118
1119
impl<T> Accumulate<T> for () {
1120
    #[inline(always)]
1121
0
    fn initial(_capacity: Option<usize>) -> Self {}
1122
    #[inline(always)]
1123
0
    fn accumulate(&mut self, _acc: T) {}
1124
}
1125
1126
impl<T> Accumulate<T> for usize {
1127
    #[inline(always)]
1128
0
    fn initial(_capacity: Option<usize>) -> Self {
1129
0
        0
1130
0
    }
1131
    #[inline(always)]
1132
0
    fn accumulate(&mut self, _acc: T) {
1133
0
        *self += 1;
1134
0
    }
1135
}
1136
1137
#[cfg(feature = "alloc")]
1138
impl<T> Accumulate<T> for Vec<T> {
1139
    #[inline(always)]
1140
0
    fn initial(capacity: Option<usize>) -> Self {
1141
0
        match capacity {
1142
0
            Some(capacity) => Vec::with_capacity(clamp_capacity::<T>(capacity)),
1143
0
            None => Vec::new(),
1144
        }
1145
0
    }
1146
    #[inline(always)]
1147
0
    fn accumulate(&mut self, acc: T) {
1148
0
        self.push(acc);
1149
0
    }
1150
}
1151
1152
#[cfg(feature = "alloc")]
1153
impl<'i, T: Clone> Accumulate<&'i [T]> for Vec<T> {
1154
    #[inline(always)]
1155
0
    fn initial(capacity: Option<usize>) -> Self {
1156
0
        match capacity {
1157
0
            Some(capacity) => Vec::with_capacity(clamp_capacity::<T>(capacity)),
1158
0
            None => Vec::new(),
1159
        }
1160
0
    }
1161
    #[inline(always)]
1162
0
    fn accumulate(&mut self, acc: &'i [T]) {
1163
0
        self.extend(acc.iter().cloned());
1164
0
    }
1165
}
1166
1167
#[cfg(feature = "alloc")]
1168
impl Accumulate<char> for String {
1169
    #[inline(always)]
1170
0
    fn initial(capacity: Option<usize>) -> Self {
1171
0
        match capacity {
1172
0
            Some(capacity) => String::with_capacity(clamp_capacity::<char>(capacity)),
1173
0
            None => String::new(),
1174
        }
1175
0
    }
1176
    #[inline(always)]
1177
0
    fn accumulate(&mut self, acc: char) {
1178
0
        self.push(acc);
1179
0
    }
1180
}
1181
1182
#[cfg(feature = "alloc")]
1183
impl<'i> Accumulate<&'i str> for String {
1184
    #[inline(always)]
1185
0
    fn initial(capacity: Option<usize>) -> Self {
1186
0
        match capacity {
1187
0
            Some(capacity) => String::with_capacity(clamp_capacity::<char>(capacity)),
1188
0
            None => String::new(),
1189
        }
1190
0
    }
1191
    #[inline(always)]
1192
0
    fn accumulate(&mut self, acc: &'i str) {
1193
0
        self.push_str(acc);
1194
0
    }
1195
}
1196
1197
#[cfg(feature = "alloc")]
1198
impl<'i> Accumulate<Cow<'i, str>> for String {
1199
    #[inline(always)]
1200
0
    fn initial(capacity: Option<usize>) -> Self {
1201
0
        match capacity {
1202
0
            Some(capacity) => String::with_capacity(clamp_capacity::<char>(capacity)),
1203
0
            None => String::new(),
1204
        }
1205
0
    }
1206
    #[inline(always)]
1207
0
    fn accumulate(&mut self, acc: Cow<'i, str>) {
1208
0
        self.push_str(&acc);
1209
0
    }
1210
}
1211
1212
#[cfg(feature = "alloc")]
1213
impl Accumulate<String> for String {
1214
    #[inline(always)]
1215
0
    fn initial(capacity: Option<usize>) -> Self {
1216
0
        match capacity {
1217
0
            Some(capacity) => String::with_capacity(clamp_capacity::<char>(capacity)),
1218
0
            None => String::new(),
1219
        }
1220
0
    }
1221
    #[inline(always)]
1222
0
    fn accumulate(&mut self, acc: String) {
1223
0
        self.push_str(&acc);
1224
0
    }
1225
}
1226
1227
#[cfg(feature = "alloc")]
1228
impl Accumulate<char> for Cow<'_, str> {
1229
    #[inline(always)]
1230
0
    fn initial(_capacity: Option<usize>) -> Self {
1231
0
        Cow::Borrowed("")
1232
0
    }
1233
    #[inline(always)]
1234
0
    fn accumulate(&mut self, acc: char) {
1235
0
        self.to_mut().accumulate(acc);
1236
0
    }
1237
}
1238
1239
#[cfg(feature = "alloc")]
1240
impl<'i> Accumulate<&'i str> for Cow<'i, str> {
1241
    #[inline(always)]
1242
0
    fn initial(_capacity: Option<usize>) -> Self {
1243
0
        Cow::Borrowed("")
1244
0
    }
1245
    #[inline(always)]
1246
0
    fn accumulate(&mut self, acc: &'i str) {
1247
0
        if self.as_ref().is_empty() {
1248
0
            *self = Cow::Borrowed(acc);
1249
0
        } else {
1250
0
            self.to_mut().accumulate(acc);
1251
0
        }
1252
0
    }
1253
}
1254
1255
#[cfg(feature = "alloc")]
1256
impl<'i> Accumulate<Cow<'i, str>> for Cow<'i, str> {
1257
    #[inline(always)]
1258
0
    fn initial(_capacity: Option<usize>) -> Self {
1259
0
        Cow::Borrowed("")
1260
0
    }
1261
    #[inline(always)]
1262
0
    fn accumulate(&mut self, acc: Cow<'i, str>) {
1263
0
        if self.as_ref().is_empty() {
1264
0
            *self = acc;
1265
0
        } else {
1266
0
            self.to_mut().accumulate(acc);
1267
0
        }
1268
0
    }
1269
}
1270
1271
#[cfg(feature = "alloc")]
1272
impl Accumulate<String> for Cow<'_, str> {
1273
    #[inline(always)]
1274
0
    fn initial(_capacity: Option<usize>) -> Self {
1275
0
        Cow::Borrowed("")
1276
0
    }
1277
    #[inline(always)]
1278
0
    fn accumulate(&mut self, acc: String) {
1279
0
        self.to_mut().accumulate(acc);
1280
0
    }
1281
}
1282
1283
#[cfg(feature = "alloc")]
1284
impl<K, V> Accumulate<(K, V)> for BTreeMap<K, V>
1285
where
1286
    K: core::cmp::Ord,
1287
{
1288
    #[inline(always)]
1289
0
    fn initial(_capacity: Option<usize>) -> Self {
1290
0
        BTreeMap::new()
1291
0
    }
1292
    #[inline(always)]
1293
0
    fn accumulate(&mut self, (key, value): (K, V)) {
1294
0
        self.insert(key, value);
1295
0
    }
1296
}
1297
1298
#[cfg(feature = "std")]
1299
impl<K, V, S> Accumulate<(K, V)> for HashMap<K, V, S>
1300
where
1301
    K: core::cmp::Eq + core::hash::Hash,
1302
    S: BuildHasher + Default,
1303
{
1304
    #[inline(always)]
1305
0
    fn initial(capacity: Option<usize>) -> Self {
1306
0
        let h = S::default();
1307
0
        match capacity {
1308
0
            Some(capacity) => {
1309
0
                HashMap::with_capacity_and_hasher(clamp_capacity::<(K, V)>(capacity), h)
1310
            }
1311
0
            None => HashMap::with_hasher(h),
1312
        }
1313
0
    }
1314
    #[inline(always)]
1315
0
    fn accumulate(&mut self, (key, value): (K, V)) {
1316
0
        self.insert(key, value);
1317
0
    }
1318
}
1319
1320
#[cfg(feature = "alloc")]
1321
impl<K> Accumulate<K> for BTreeSet<K>
1322
where
1323
    K: core::cmp::Ord,
1324
{
1325
    #[inline(always)]
1326
0
    fn initial(_capacity: Option<usize>) -> Self {
1327
0
        BTreeSet::new()
1328
0
    }
1329
    #[inline(always)]
1330
0
    fn accumulate(&mut self, key: K) {
1331
0
        self.insert(key);
1332
0
    }
1333
}
1334
1335
#[cfg(feature = "std")]
1336
impl<K, S> Accumulate<K> for HashSet<K, S>
1337
where
1338
    K: core::cmp::Eq + core::hash::Hash,
1339
    S: BuildHasher + Default,
1340
{
1341
    #[inline(always)]
1342
0
    fn initial(capacity: Option<usize>) -> Self {
1343
0
        let h = S::default();
1344
0
        match capacity {
1345
0
            Some(capacity) => HashSet::with_capacity_and_hasher(clamp_capacity::<K>(capacity), h),
1346
0
            None => HashSet::with_hasher(h),
1347
        }
1348
0
    }
1349
    #[inline(always)]
1350
0
    fn accumulate(&mut self, key: K) {
1351
0
        self.insert(key);
1352
0
    }
1353
}
1354
1355
#[cfg(feature = "alloc")]
1356
impl<'i, T: Clone> Accumulate<&'i [T]> for VecDeque<T> {
1357
    #[inline(always)]
1358
0
    fn initial(capacity: Option<usize>) -> Self {
1359
0
        match capacity {
1360
0
            Some(capacity) => VecDeque::with_capacity(clamp_capacity::<T>(capacity)),
1361
0
            None => VecDeque::new(),
1362
        }
1363
0
    }
1364
    #[inline(always)]
1365
0
    fn accumulate(&mut self, acc: &'i [T]) {
1366
0
        self.extend(acc.iter().cloned());
1367
0
    }
1368
}
1369
1370
#[cfg(feature = "alloc")]
1371
#[inline]
1372
0
pub(crate) fn clamp_capacity<T>(capacity: usize) -> usize {
1373
    /// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`.
1374
    ///
1375
    /// Pre-allocating memory is a nice optimization but count fields can't
1376
    /// always be trusted. We should clamp initial capacities to some reasonable
1377
    /// amount. This reduces the risk of a bogus count value triggering a panic
1378
    /// due to an OOM error.
1379
    ///
1380
    /// This does not affect correctness. `winnow` will always read the full number
1381
    /// of elements regardless of the capacity cap.
1382
    const MAX_INITIAL_CAPACITY_BYTES: usize = 65536;
1383
1384
0
    let max_initial_capacity = MAX_INITIAL_CAPACITY_BYTES / core::mem::size_of::<T>().max(1);
1385
0
    capacity.min(max_initial_capacity)
1386
0
}
1387
1388
/// Helper trait to convert numbers to usize.
1389
///
1390
/// By default, usize implements `From<u8>` and `From<u16>` but not
1391
/// `From<u32>` and `From<u64>` because that would be invalid on some
1392
/// platforms. This trait implements the conversion for platforms
1393
/// with 32 and 64 bits pointer platforms
1394
pub trait ToUsize {
1395
    /// converts self to usize
1396
    fn to_usize(&self) -> usize;
1397
}
1398
1399
impl ToUsize for u8 {
1400
    #[inline(always)]
1401
0
    fn to_usize(&self) -> usize {
1402
0
        *self as usize
1403
0
    }
1404
}
1405
1406
impl ToUsize for u16 {
1407
    #[inline(always)]
1408
0
    fn to_usize(&self) -> usize {
1409
0
        *self as usize
1410
0
    }
1411
}
1412
1413
impl ToUsize for usize {
1414
    #[inline(always)]
1415
0
    fn to_usize(&self) -> usize {
1416
0
        *self
1417
0
    }
1418
}
1419
1420
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
1421
impl ToUsize for u32 {
1422
    #[inline(always)]
1423
0
    fn to_usize(&self) -> usize {
1424
0
        *self as usize
1425
0
    }
1426
}
1427
1428
#[cfg(target_pointer_width = "64")]
1429
impl ToUsize for u64 {
1430
    #[inline(always)]
1431
0
    fn to_usize(&self) -> usize {
1432
0
        *self as usize
1433
0
    }
1434
}
1435
1436
/// Transforms a token into a char for basic string parsing
1437
#[allow(clippy::len_without_is_empty)]
1438
#[allow(clippy::wrong_self_convention)]
1439
pub trait AsChar {
1440
    /// Makes a char from self
1441
    ///
1442
    /// # Example
1443
    ///
1444
    /// ```
1445
    /// use winnow::prelude::*;
1446
    ///
1447
    /// assert_eq!('a'.as_char(), 'a');
1448
    /// assert_eq!(u8::MAX.as_char(), std::char::from_u32(u8::MAX as u32).unwrap());
1449
    /// ```
1450
    fn as_char(self) -> char;
1451
1452
    /// Tests that self is an ASCII alphabetic character
1453
    fn is_alpha(self) -> bool;
1454
1455
    /// Tests that self is an alphabetic character
1456
    /// or a decimal digit
1457
    fn is_alphanum(self) -> bool;
1458
    /// Tests that self is a decimal digit
1459
    fn is_dec_digit(self) -> bool;
1460
    /// Tests that self is an hex digit
1461
    fn is_hex_digit(self) -> bool;
1462
    /// Tests that self is an octal digit
1463
    fn is_oct_digit(self) -> bool;
1464
    /// Gets the len in bytes for self
1465
    fn len(self) -> usize;
1466
    /// Tests that self is ASCII space or tab
1467
    fn is_space(self) -> bool;
1468
    /// Tests if byte is ASCII newline: \n
1469
    fn is_newline(self) -> bool;
1470
}
1471
1472
impl AsChar for u8 {
1473
    #[inline(always)]
1474
677M
    fn as_char(self) -> char {
1475
677M
        self as char
1476
677M
    }
1477
    #[inline]
1478
0
    fn is_alpha(self) -> bool {
1479
0
        matches!(self, 0x41..=0x5A | 0x61..=0x7A)
1480
0
    }
1481
    #[inline]
1482
0
    fn is_alphanum(self) -> bool {
1483
0
        self.is_alpha() || self.is_dec_digit()
1484
0
    }
1485
    #[inline]
1486
0
    fn is_dec_digit(self) -> bool {
1487
0
        matches!(self, 0x30..=0x39)
1488
0
    }
1489
    #[inline]
1490
0
    fn is_hex_digit(self) -> bool {
1491
0
        matches!(self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66)
1492
0
    }
1493
    #[inline]
1494
0
    fn is_oct_digit(self) -> bool {
1495
0
        matches!(self, 0x30..=0x37)
1496
0
    }
1497
    #[inline]
1498
0
    fn len(self) -> usize {
1499
0
        1
1500
0
    }
1501
    #[inline]
1502
0
    fn is_space(self) -> bool {
1503
0
        self == b' ' || self == b'\t'
1504
0
    }
1505
    #[inline]
1506
0
    fn is_newline(self) -> bool {
1507
0
        self == b'\n'
1508
0
    }
1509
}
1510
1511
impl AsChar for &u8 {
1512
    #[inline(always)]
1513
379M
    fn as_char(self) -> char {
1514
379M
        (*self).as_char()
1515
379M
    }
1516
    #[inline(always)]
1517
0
    fn is_alpha(self) -> bool {
1518
0
        (*self).is_alpha()
1519
0
    }
1520
    #[inline(always)]
1521
0
    fn is_alphanum(self) -> bool {
1522
0
        (*self).is_alphanum()
1523
0
    }
1524
    #[inline(always)]
1525
0
    fn is_dec_digit(self) -> bool {
1526
0
        (*self).is_dec_digit()
1527
0
    }
1528
    #[inline(always)]
1529
0
    fn is_hex_digit(self) -> bool {
1530
0
        (*self).is_hex_digit()
1531
0
    }
1532
    #[inline(always)]
1533
0
    fn is_oct_digit(self) -> bool {
1534
0
        (*self).is_oct_digit()
1535
0
    }
1536
    #[inline(always)]
1537
0
    fn len(self) -> usize {
1538
0
        (*self).len()
1539
0
    }
1540
    #[inline(always)]
1541
0
    fn is_space(self) -> bool {
1542
0
        (*self).is_space()
1543
0
    }
1544
    #[inline(always)]
1545
0
    fn is_newline(self) -> bool {
1546
0
        (*self).is_newline()
1547
0
    }
1548
}
1549
1550
impl AsChar for char {
1551
    #[inline(always)]
1552
0
    fn as_char(self) -> char {
1553
0
        self
1554
0
    }
1555
    #[inline]
1556
0
    fn is_alpha(self) -> bool {
1557
0
        self.is_ascii_alphabetic()
1558
0
    }
1559
    #[inline]
1560
0
    fn is_alphanum(self) -> bool {
1561
0
        self.is_alpha() || self.is_dec_digit()
1562
0
    }
1563
    #[inline]
1564
0
    fn is_dec_digit(self) -> bool {
1565
0
        self.is_ascii_digit()
1566
0
    }
1567
    #[inline]
1568
0
    fn is_hex_digit(self) -> bool {
1569
0
        self.is_ascii_hexdigit()
1570
0
    }
1571
    #[inline]
1572
0
    fn is_oct_digit(self) -> bool {
1573
0
        self.is_digit(8)
1574
0
    }
1575
    #[inline]
1576
0
    fn len(self) -> usize {
1577
0
        self.len_utf8()
1578
0
    }
1579
    #[inline]
1580
0
    fn is_space(self) -> bool {
1581
0
        self == ' ' || self == '\t'
1582
0
    }
1583
    #[inline]
1584
0
    fn is_newline(self) -> bool {
1585
0
        self == '\n'
1586
0
    }
1587
}
1588
1589
impl AsChar for &char {
1590
    #[inline(always)]
1591
0
    fn as_char(self) -> char {
1592
0
        (*self).as_char()
1593
0
    }
1594
    #[inline(always)]
1595
0
    fn is_alpha(self) -> bool {
1596
0
        (*self).is_alpha()
1597
0
    }
1598
    #[inline(always)]
1599
0
    fn is_alphanum(self) -> bool {
1600
0
        (*self).is_alphanum()
1601
0
    }
1602
    #[inline(always)]
1603
0
    fn is_dec_digit(self) -> bool {
1604
0
        (*self).is_dec_digit()
1605
0
    }
1606
    #[inline(always)]
1607
0
    fn is_hex_digit(self) -> bool {
1608
0
        (*self).is_hex_digit()
1609
0
    }
1610
    #[inline(always)]
1611
0
    fn is_oct_digit(self) -> bool {
1612
0
        (*self).is_oct_digit()
1613
0
    }
1614
    #[inline(always)]
1615
0
    fn len(self) -> usize {
1616
0
        (*self).len()
1617
0
    }
1618
    #[inline(always)]
1619
0
    fn is_space(self) -> bool {
1620
0
        (*self).is_space()
1621
0
    }
1622
    #[inline(always)]
1623
0
    fn is_newline(self) -> bool {
1624
0
        (*self).is_newline()
1625
0
    }
1626
}
1627
1628
/// Check if a token is in a set of possible tokens
1629
///
1630
/// While this can be implemented manually, you can also build up sets using:
1631
/// - `b'c'` and `'c'`
1632
/// - `b""`
1633
/// - `|c| true`
1634
/// - `b'a'..=b'z'`, `'a'..='z'` (etc for each [range type][std::ops])
1635
/// - `(set1, set2, ...)`
1636
///
1637
/// # Example
1638
///
1639
/// For example, you could implement `hex_digit0` as:
1640
/// ```
1641
/// # #[cfg(feature = "parser")] {
1642
/// # use winnow::prelude::*;
1643
/// # use winnow::{error::ErrMode, error::ContextError};
1644
/// # use winnow::token::take_while;
1645
/// fn hex_digit1<'s>(input: &mut &'s str) -> ModalResult<&'s str, ContextError> {
1646
///     take_while(1.., ('a'..='f', 'A'..='F', '0'..='9')).parse_next(input)
1647
/// }
1648
///
1649
/// assert_eq!(hex_digit1.parse_peek("21cZ"), Ok(("Z", "21c")));
1650
/// assert!(hex_digit1.parse_peek("H2").is_err());
1651
/// assert!(hex_digit1.parse_peek("").is_err());
1652
/// # }
1653
/// ```
1654
pub trait ContainsToken<T> {
1655
    /// Returns true if self contains the token
1656
    fn contains_token(&self, token: T) -> bool;
1657
}
1658
1659
impl ContainsToken<u8> for u8 {
1660
    #[inline(always)]
1661
170M
    fn contains_token(&self, token: u8) -> bool {
1662
170M
        *self == token
1663
170M
    }
1664
}
1665
1666
impl ContainsToken<&u8> for u8 {
1667
    #[inline(always)]
1668
7.20M
    fn contains_token(&self, token: &u8) -> bool {
1669
7.20M
        self.contains_token(*token)
1670
7.20M
    }
1671
}
1672
1673
impl ContainsToken<char> for u8 {
1674
    #[inline(always)]
1675
0
    fn contains_token(&self, token: char) -> bool {
1676
0
        self.as_char() == token
1677
0
    }
1678
}
1679
1680
impl ContainsToken<&char> for u8 {
1681
    #[inline(always)]
1682
0
    fn contains_token(&self, token: &char) -> bool {
1683
0
        self.contains_token(*token)
1684
0
    }
1685
}
1686
1687
impl<C: AsChar> ContainsToken<C> for char {
1688
    #[inline(always)]
1689
3.92M
    fn contains_token(&self, token: C) -> bool {
1690
3.92M
        *self == token.as_char()
1691
3.92M
    }
<char as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1689
3.92M
    fn contains_token(&self, token: C) -> bool {
1690
3.92M
        *self == token.as_char()
1691
3.92M
    }
Unexecuted instantiation: <char as winnow::stream::ContainsToken<_>>::contains_token
1692
}
1693
1694
impl<C, F: Fn(C) -> bool> ContainsToken<C> for F {
1695
    #[inline(always)]
1696
0
    fn contains_token(&self, token: C) -> bool {
1697
0
        self(token)
1698
0
    }
1699
}
1700
1701
impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for core::ops::Range<C2> {
1702
    #[inline(always)]
1703
0
    fn contains_token(&self, token: C1) -> bool {
1704
0
        let start = self.start.clone().as_char();
1705
0
        let end = self.end.clone().as_char();
1706
0
        (start..end).contains(&token.as_char())
1707
0
    }
1708
}
1709
1710
impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for core::ops::RangeInclusive<C2> {
1711
    #[inline(always)]
1712
93.0M
    fn contains_token(&self, token: C1) -> bool {
1713
93.0M
        let start = self.start().clone().as_char();
1714
93.0M
        let end = self.end().clone().as_char();
1715
93.0M
        (start..=end).contains(&token.as_char())
1716
93.0M
    }
<core::ops::range::RangeInclusive<u8> as winnow::stream::ContainsToken<&u8>>::contains_token
Line
Count
Source
1712
16.5M
    fn contains_token(&self, token: C1) -> bool {
1713
16.5M
        let start = self.start().clone().as_char();
1714
16.5M
        let end = self.end().clone().as_char();
1715
16.5M
        (start..=end).contains(&token.as_char())
1716
16.5M
    }
<core::ops::range::RangeInclusive<u8> as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1712
76.5M
    fn contains_token(&self, token: C1) -> bool {
1713
76.5M
        let start = self.start().clone().as_char();
1714
76.5M
        let end = self.end().clone().as_char();
1715
76.5M
        (start..=end).contains(&token.as_char())
1716
76.5M
    }
Unexecuted instantiation: <core::ops::range::RangeInclusive<_> as winnow::stream::ContainsToken<_>>::contains_token
1717
}
1718
1719
impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for core::ops::RangeFrom<C2> {
1720
    #[inline(always)]
1721
0
    fn contains_token(&self, token: C1) -> bool {
1722
0
        let start = self.start.clone().as_char();
1723
0
        (start..).contains(&token.as_char())
1724
0
    }
1725
}
1726
1727
impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for core::ops::RangeTo<C2> {
1728
    #[inline(always)]
1729
0
    fn contains_token(&self, token: C1) -> bool {
1730
0
        let end = self.end.clone().as_char();
1731
0
        (..end).contains(&token.as_char())
1732
0
    }
1733
}
1734
1735
impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for core::ops::RangeToInclusive<C2> {
1736
    #[inline(always)]
1737
0
    fn contains_token(&self, token: C1) -> bool {
1738
0
        let end = self.end.clone().as_char();
1739
0
        (..=end).contains(&token.as_char())
1740
0
    }
1741
}
1742
1743
impl<C1: AsChar> ContainsToken<C1> for core::ops::RangeFull {
1744
    #[inline(always)]
1745
0
    fn contains_token(&self, _token: C1) -> bool {
1746
0
        true
1747
0
    }
1748
}
1749
1750
impl<C: AsChar> ContainsToken<C> for &'_ [u8] {
1751
    #[inline]
1752
31.3M
    fn contains_token(&self, token: C) -> bool {
1753
31.3M
        let token = token.as_char();
1754
363M
        self.iter().any(|t| t.as_char() == token)
<&[u8] as winnow::stream::ContainsToken<u8>>::contains_token::{closure#0}
Line
Count
Source
1754
363M
        self.iter().any(|t| t.as_char() == token)
Unexecuted instantiation: <&[u8] as winnow::stream::ContainsToken<_>>::contains_token::{closure#0}
1755
31.3M
    }
<&[u8] as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1752
31.3M
    fn contains_token(&self, token: C) -> bool {
1753
31.3M
        let token = token.as_char();
1754
31.3M
        self.iter().any(|t| t.as_char() == token)
1755
31.3M
    }
Unexecuted instantiation: <&[u8] as winnow::stream::ContainsToken<_>>::contains_token
1756
}
1757
1758
impl<C: AsChar> ContainsToken<C> for &'_ [char] {
1759
    #[inline]
1760
0
    fn contains_token(&self, token: C) -> bool {
1761
0
        let token = token.as_char();
1762
0
        self.contains(&token)
1763
0
    }
1764
}
1765
1766
impl<const LEN: usize, C: AsChar> ContainsToken<C> for &'_ [u8; LEN] {
1767
    #[inline]
1768
0
    fn contains_token(&self, token: C) -> bool {
1769
0
        let token = token.as_char();
1770
0
        self.iter().any(|t| t.as_char() == token)
1771
0
    }
1772
}
1773
1774
impl<const LEN: usize, C: AsChar> ContainsToken<C> for &'_ [char; LEN] {
1775
    #[inline]
1776
0
    fn contains_token(&self, token: C) -> bool {
1777
0
        let token = token.as_char();
1778
0
        self.contains(&token)
1779
0
    }
1780
}
1781
1782
impl<const LEN: usize, C: AsChar> ContainsToken<C> for [u8; LEN] {
1783
    #[inline]
1784
0
    fn contains_token(&self, token: C) -> bool {
1785
0
        let token = token.as_char();
1786
0
        self.iter().any(|t| t.as_char() == token)
1787
0
    }
1788
}
1789
1790
impl<const LEN: usize, C: AsChar> ContainsToken<C> for [char; LEN] {
1791
    #[inline]
1792
0
    fn contains_token(&self, token: C) -> bool {
1793
0
        let token = token.as_char();
1794
0
        self.contains(&token)
1795
0
    }
1796
}
1797
1798
impl<T> ContainsToken<T> for () {
1799
    #[inline(always)]
1800
0
    fn contains_token(&self, _token: T) -> bool {
1801
0
        false
1802
0
    }
1803
}
1804
1805
macro_rules! impl_contains_token_for_tuple {
1806
    ($($haystack:ident),+) => (
1807
        #[allow(non_snake_case)]
1808
        impl<T, $($haystack),+> ContainsToken<T> for ($($haystack),+,)
1809
        where
1810
            T: Clone,
1811
            $($haystack: ContainsToken<T>),+
1812
        {
1813
            #[inline]
1814
144M
            fn contains_token(&self, token: T) -> bool {
1815
144M
                let ($(ref $haystack),+,) = *self;
1816
72.9M
                $($haystack.contains_token(token.clone()) || )+ false
1817
144M
            }
<(((u8, u8), u8, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>), u8) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
7.02M
            fn contains_token(&self, token: T) -> bool {
1815
7.02M
                let ($(ref $haystack),+,) = *self;
1816
6.83M
                $($haystack.contains_token(token.clone()) || )+ false
1817
7.02M
            }
<(core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
626k
            fn contains_token(&self, token: T) -> bool {
1815
626k
                let ($(ref $haystack),+,) = *self;
1816
246k
                $($haystack.contains_token(token.clone()) || )+ false
1817
626k
            }
<(((u8, u8), u8, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>), u8, u8) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
19.0M
            fn contains_token(&self, token: T) -> bool {
1815
19.0M
                let ($(ref $haystack),+,) = *self;
1816
2.13M
                $($haystack.contains_token(token.clone()) || )+ false
1817
19.0M
            }
<(u8, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
2.60M
            fn contains_token(&self, token: T) -> bool {
1815
2.60M
                let ($(ref $haystack),+,) = *self;
1816
857k
                $($haystack.contains_token(token.clone()) || )+ false
1817
2.60M
            }
<(u8, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>) as winnow::stream::ContainsToken<&u8>>::contains_token
Line
Count
Source
1814
1.14M
            fn contains_token(&self, token: T) -> bool {
1815
1.14M
                let ($(ref $haystack),+,) = *self;
1816
273k
                $($haystack.contains_token(token.clone()) || )+ false
1817
1.14M
            }
<(core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, u8, u8) as winnow::stream::ContainsToken<&u8>>::contains_token
Line
Count
Source
1814
5.24M
            fn contains_token(&self, token: T) -> bool {
1815
5.24M
                let ($(ref $haystack),+,) = *self;
1816
2.00M
                $($haystack.contains_token(token.clone()) || )+ false
1817
5.24M
            }
<(((u8, u8), u8, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>), u8, u8, u8, char) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
4.38M
            fn contains_token(&self, token: T) -> bool {
1815
4.38M
                let ($(ref $haystack),+,) = *self;
1816
3.92M
                $($haystack.contains_token(token.clone()) || )+ false
1817
4.38M
            }
<((u8, u8), u8, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>, core::ops::range::RangeInclusive<u8>) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
46.2M
            fn contains_token(&self, token: T) -> bool {
1815
46.2M
                let ($(ref $haystack),+,) = *self;
1816
13.6M
                $($haystack.contains_token(token.clone()) || )+ false
1817
46.2M
            }
<((u8, u8), u8) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
469k
            fn contains_token(&self, token: T) -> bool {
1815
469k
                let ($(ref $haystack),+,) = *self;
1816
454k
                $($haystack.contains_token(token.clone()) || )+ false
1817
469k
            }
<(u8, u8) as winnow::stream::ContainsToken<&u8>>::contains_token
Line
Count
Source
1814
524k
            fn contains_token(&self, token: T) -> bool {
1815
524k
                let ($(ref $haystack),+,) = *self;
1816
523k
                $($haystack.contains_token(token.clone()) || )+ false
1817
524k
            }
<(u8, u8) as winnow::stream::ContainsToken<u8>>::contains_token
Line
Count
Source
1814
56.2M
            fn contains_token(&self, token: T) -> bool {
1815
56.2M
                let ($(ref $haystack),+,) = *self;
1816
41.5M
                $($haystack.contains_token(token.clone()) || )+ false
1817
56.2M
            }
<((u8, u8), u8, u8) as winnow::stream::ContainsToken<&u8>>::contains_token
Line
Count
Source
1814
524k
            fn contains_token(&self, token: T) -> bool {
1815
524k
                let ($(ref $haystack),+,) = *self;
1816
479k
                $($haystack.contains_token(token.clone()) || )+ false
1817
524k
            }
Unexecuted instantiation: <(_,) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _, _, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _, _, _, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _, _, _, _, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as winnow::stream::ContainsToken<_>>::contains_token
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as winnow::stream::ContainsToken<_>>::contains_token
1818
        }
1819
    )
1820
}
1821
1822
macro_rules! impl_contains_token_for_tuples {
1823
    ($haystack1:ident, $($haystack:ident),+) => {
1824
        impl_contains_token_for_tuples!(__impl $haystack1; $($haystack),+);
1825
    };
1826
    (__impl $($haystack:ident),+; $haystack1:ident $(,$haystack2:ident)*) => {
1827
        impl_contains_token_for_tuple!($($haystack),+);
1828
        impl_contains_token_for_tuples!(__impl $($haystack),+, $haystack1; $($haystack2),*);
1829
    };
1830
    (__impl $($haystack:ident),+;) => {
1831
        impl_contains_token_for_tuple!($($haystack),+);
1832
    }
1833
}
1834
1835
impl_contains_token_for_tuples!(F1, F2, F3, F4, F5, F6, F7, F8, F9, F10);
1836
1837
#[cfg(feature = "simd")]
1838
#[inline(always)]
1839
fn memchr(token: u8, slice: &[u8]) -> Option<usize> {
1840
    memchr::memchr(token, slice)
1841
}
1842
1843
#[cfg(feature = "simd")]
1844
#[inline(always)]
1845
fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> {
1846
    memchr::memchr2(token.0, token.1, slice)
1847
}
1848
1849
#[cfg(feature = "simd")]
1850
#[inline(always)]
1851
fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> {
1852
    memchr::memchr3(token.0, token.1, token.2, slice)
1853
}
1854
1855
#[cfg(not(feature = "simd"))]
1856
#[inline(always)]
1857
241k
fn memchr(token: u8, slice: &[u8]) -> Option<usize> {
1858
586k
    slice.iter().position(|t| *t == token)
winnow::stream::memchr::{closure#0}
Line
Count
Source
1858
586k
    slice.iter().position(|t| *t == token)
Unexecuted instantiation: winnow::stream::memchr::{closure#0}
1859
241k
}
1860
1861
#[cfg(not(feature = "simd"))]
1862
#[inline(always)]
1863
74.1k
fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> {
1864
3.88M
    slice.iter().position(|t| *t == token.0 || *t == token.1)
winnow::stream::memchr2::{closure#0}
Line
Count
Source
1864
3.88M
    slice.iter().position(|t| *t == token.0 || *t == token.1)
Unexecuted instantiation: winnow::stream::memchr2::{closure#0}
1865
74.1k
}
1866
1867
#[cfg(not(feature = "simd"))]
1868
#[inline(always)]
1869
534k
fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> {
1870
534k
    slice
1871
534k
        .iter()
1872
30.2M
        .position(|t| *t == token.0 || *t == token.1 || *t == token.2)
winnow::stream::memchr3::{closure#0}
Line
Count
Source
1872
30.2M
        .position(|t| *t == token.0 || *t == token.1 || *t == token.2)
Unexecuted instantiation: winnow::stream::memchr3::{closure#0}
1873
534k
}
1874
1875
#[inline(always)]
1876
271k
fn memmem(slice: &[u8], literal: &[u8]) -> Option<core::ops::Range<usize>> {
1877
271k
    match literal.len() {
1878
0
        0 => Some(0..0),
1879
241k
        1 => memchr(literal[0], slice).map(|i| i..i + 1),
winnow::stream::memmem::{closure#0}
Line
Count
Source
1879
222k
        1 => memchr(literal[0], slice).map(|i| i..i + 1),
Unexecuted instantiation: winnow::stream::memmem::{closure#0}
1880
29.5k
        _ => memmem_(slice, literal),
1881
    }
1882
271k
}
1883
1884
#[inline(always)]
1885
578k
fn memmem2(slice: &[u8], literal: (&[u8], &[u8])) -> Option<core::ops::Range<usize>> {
1886
578k
    match (literal.0.len(), literal.1.len()) {
1887
0
        (0, _) | (_, 0) => Some(0..0),
1888
0
        (1, 1) => memchr2((literal.0[0], literal.1[0]), slice).map(|i| i..i + 1),
Unexecuted instantiation: winnow::stream::memmem2::{closure#0}
Unexecuted instantiation: winnow::stream::memmem2::{closure#0}
1889
578k
        _ => memmem2_(slice, literal),
1890
    }
1891
578k
}
1892
1893
#[inline(always)]
1894
0
fn memmem3(slice: &[u8], literal: (&[u8], &[u8], &[u8])) -> Option<core::ops::Range<usize>> {
1895
0
    match (literal.0.len(), literal.1.len(), literal.2.len()) {
1896
0
        (0, _, _) | (_, 0, _) | (_, _, 0) => Some(0..0),
1897
0
        (1, 1, 1) => memchr3((literal.0[0], literal.1[0], literal.2[0]), slice).map(|i| i..i + 1),
1898
0
        _ => memmem3_(slice, literal),
1899
    }
1900
0
}
1901
1902
#[cfg(feature = "simd")]
1903
#[inline(always)]
1904
fn memmem_(slice: &[u8], literal: &[u8]) -> Option<core::ops::Range<usize>> {
1905
    let &prefix = match literal.first() {
1906
        Some(x) => x,
1907
        None => return Some(0..0),
1908
    };
1909
    #[allow(clippy::manual_find)] // faster this way
1910
    for i in memchr::memchr_iter(prefix, slice) {
1911
        if slice[i..].starts_with(literal) {
1912
            let i_end = i + literal.len();
1913
            return Some(i..i_end);
1914
        }
1915
    }
1916
    None
1917
}
1918
1919
#[cfg(feature = "simd")]
1920
fn memmem2_(slice: &[u8], literal: (&[u8], &[u8])) -> Option<core::ops::Range<usize>> {
1921
    let prefix = match (literal.0.first(), literal.1.first()) {
1922
        (Some(&a), Some(&b)) => (a, b),
1923
        _ => return Some(0..0),
1924
    };
1925
    #[allow(clippy::manual_find)] // faster this way
1926
    for i in memchr::memchr2_iter(prefix.0, prefix.1, slice) {
1927
        let subslice = &slice[i..];
1928
        if subslice.starts_with(literal.0) {
1929
            let i_end = i + literal.0.len();
1930
            return Some(i..i_end);
1931
        }
1932
        if subslice.starts_with(literal.1) {
1933
            let i_end = i + literal.1.len();
1934
            return Some(i..i_end);
1935
        }
1936
    }
1937
    None
1938
}
1939
1940
#[cfg(feature = "simd")]
1941
fn memmem3_(slice: &[u8], literal: (&[u8], &[u8], &[u8])) -> Option<core::ops::Range<usize>> {
1942
    let prefix = match (literal.0.first(), literal.1.first(), literal.2.first()) {
1943
        (Some(&a), Some(&b), Some(&c)) => (a, b, c),
1944
        _ => return Some(0..0),
1945
    };
1946
    #[allow(clippy::manual_find)] // faster this way
1947
    for i in memchr::memchr3_iter(prefix.0, prefix.1, prefix.2, slice) {
1948
        let subslice = &slice[i..];
1949
        if subslice.starts_with(literal.0) {
1950
            let i_end = i + literal.0.len();
1951
            return Some(i..i_end);
1952
        }
1953
        if subslice.starts_with(literal.1) {
1954
            let i_end = i + literal.1.len();
1955
            return Some(i..i_end);
1956
        }
1957
        if subslice.starts_with(literal.2) {
1958
            let i_end = i + literal.2.len();
1959
            return Some(i..i_end);
1960
        }
1961
    }
1962
    None
1963
}
1964
1965
#[cfg(not(feature = "simd"))]
1966
29.5k
fn memmem_(slice: &[u8], literal: &[u8]) -> Option<core::ops::Range<usize>> {
1967
1.25M
    for i in 0..slice.len() {
1968
1.25M
        let subslice = &slice[i..];
1969
1.25M
        if subslice.starts_with(literal) {
1970
29.2k
            let i_end = i + literal.len();
1971
29.2k
            return Some(i..i_end);
1972
1.22M
        }
1973
    }
1974
316
    None
1975
29.5k
}
1976
1977
#[cfg(not(feature = "simd"))]
1978
578k
fn memmem2_(slice: &[u8], literal: (&[u8], &[u8])) -> Option<core::ops::Range<usize>> {
1979
24.0M
    for i in 0..slice.len() {
1980
24.0M
        let subslice = &slice[i..];
1981
24.0M
        if subslice.starts_with(literal.0) {
1982
32.5k
            let i_end = i + literal.0.len();
1983
32.5k
            return Some(i..i_end);
1984
23.9M
        }
1985
23.9M
        if subslice.starts_with(literal.1) {
1986
545k
            let i_end = i + literal.1.len();
1987
545k
            return Some(i..i_end);
1988
23.4M
        }
1989
    }
1990
1.00k
    None
1991
578k
}
1992
1993
#[cfg(not(feature = "simd"))]
1994
0
fn memmem3_(slice: &[u8], literal: (&[u8], &[u8], &[u8])) -> Option<core::ops::Range<usize>> {
1995
0
    for i in 0..slice.len() {
1996
0
        let subslice = &slice[i..];
1997
0
        if subslice.starts_with(literal.0) {
1998
0
            let i_end = i + literal.0.len();
1999
0
            return Some(i..i_end);
2000
0
        }
2001
0
        if subslice.starts_with(literal.1) {
2002
0
            let i_end = i + literal.1.len();
2003
0
            return Some(i..i_end);
2004
0
        }
2005
0
        if subslice.starts_with(literal.2) {
2006
0
            let i_end = i + literal.2.len();
2007
0
            return Some(i..i_end);
2008
0
        }
2009
    }
2010
0
    None
2011
0
}