/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 | } |