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 | //! - [`Located`] 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::num::NonZeroUsize; |
14 | |
15 | use crate::ascii::Caseless as AsciiCaseless; |
16 | #[cfg (feature = "unstable-recover" )] |
17 | use crate::error::FromRecoverableError; |
18 | use crate::error::Needed; |
19 | use crate::lib::std::iter::{Cloned, Enumerate}; |
20 | use crate::lib::std::slice::Iter; |
21 | use crate::lib::std::str::from_utf8; |
22 | use crate::lib::std::str::CharIndices; |
23 | use crate::lib::std::str::FromStr; |
24 | |
25 | #[allow (unused_imports)] |
26 | #[cfg (any(feature = "unstable-doc" , feature = "unstable-recover" ))] |
27 | use crate::error::ErrMode; |
28 | |
29 | #[cfg (feature = "alloc" )] |
30 | use crate::lib::std::collections::BTreeMap; |
31 | #[cfg (feature = "alloc" )] |
32 | use crate::lib::std::collections::BTreeSet; |
33 | #[cfg (feature = "std" )] |
34 | use crate::lib::std::collections::HashMap; |
35 | #[cfg (feature = "std" )] |
36 | use crate::lib::std::collections::HashSet; |
37 | #[cfg (feature = "alloc" )] |
38 | use crate::lib::std::string::String; |
39 | #[cfg (feature = "alloc" )] |
40 | use crate::lib::std::vec::Vec; |
41 | |
42 | mod impls; |
43 | #[cfg (test)] |
44 | mod tests; |
45 | |
46 | /// UTF-8 Stream |
47 | pub type Str<'i> = &'i str; |
48 | |
49 | /// Improved `Debug` experience for `&[u8]` byte streams |
50 | #[allow (clippy::derive_hash_xor_eq)] |
51 | #[derive (Hash)] |
52 | #[repr (transparent)] |
53 | pub struct Bytes([u8]); |
54 | |
55 | impl Bytes { |
56 | /// Make a stream out of a byte slice-like. |
57 | #[inline ] |
58 | pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self { |
59 | Self::from_bytes(slice:bytes.as_ref()) |
60 | } |
61 | |
62 | #[inline ] |
63 | fn from_bytes(slice: &[u8]) -> &Self { |
64 | unsafe { crate::lib::std::mem::transmute(src:slice) } |
65 | } |
66 | |
67 | #[inline ] |
68 | fn as_bytes(&self) -> &[u8] { |
69 | &self.0 |
70 | } |
71 | } |
72 | |
73 | /// Improved `Debug` experience for `&[u8]` UTF-8-ish streams |
74 | #[allow (clippy::derive_hash_xor_eq)] |
75 | #[derive (Hash)] |
76 | #[repr (transparent)] |
77 | pub struct BStr([u8]); |
78 | |
79 | impl BStr { |
80 | /// Make a stream out of a byte slice-like. |
81 | #[inline ] |
82 | pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self { |
83 | Self::from_bytes(slice:bytes.as_ref()) |
84 | } |
85 | |
86 | #[inline ] |
87 | fn from_bytes(slice: &[u8]) -> &Self { |
88 | unsafe { crate::lib::std::mem::transmute(src:slice) } |
89 | } |
90 | |
91 | #[inline ] |
92 | fn as_bytes(&self) -> &[u8] { |
93 | &self.0 |
94 | } |
95 | } |
96 | |
97 | /// Allow collecting the span of a parsed token |
98 | /// |
99 | /// Spans are tracked as a [`Range<usize>`] of byte offsets. |
100 | /// |
101 | /// Converting byte offsets to line or column numbers is left up to the user, as computing column |
102 | /// numbers requires domain knowledge (are columns byte-based, codepoint-based, or grapheme-based?) |
103 | /// and O(n) iteration over the input to determine codepoint and line boundaries. |
104 | /// |
105 | /// [The `line-span` crate](https://docs.rs/line-span/latest/line_span/) can help with converting |
106 | /// byte offsets to line numbers. |
107 | /// |
108 | /// See [`Parser::span`][crate::Parser::span] and [`Parser::with_span`][crate::Parser::with_span] for more details |
109 | #[derive (Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)] |
110 | #[doc (alias = "LocatedSpan" )] |
111 | pub struct Located<I> { |
112 | initial: I, |
113 | input: I, |
114 | } |
115 | |
116 | impl<I> Located<I> |
117 | where |
118 | I: Clone + Offset, |
119 | { |
120 | /// Wrap another Stream with span tracking |
121 | pub fn new(input: I) -> Self { |
122 | let initial: I = input.clone(); |
123 | Self { initial, input } |
124 | } |
125 | |
126 | fn location(&self) -> usize { |
127 | self.input.offset_from(&self.initial) |
128 | } |
129 | } |
130 | |
131 | impl<I> AsRef<I> for Located<I> { |
132 | #[inline (always)] |
133 | fn as_ref(&self) -> &I { |
134 | &self.input |
135 | } |
136 | } |
137 | |
138 | impl<I> crate::lib::std::ops::Deref for Located<I> { |
139 | type Target = I; |
140 | |
141 | #[inline (always)] |
142 | fn deref(&self) -> &Self::Target { |
143 | &self.input |
144 | } |
145 | } |
146 | |
147 | impl<I: crate::lib::std::fmt::Display> crate::lib::std::fmt::Display for Located<I> { |
148 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
149 | self.input.fmt(f) |
150 | } |
151 | } |
152 | |
153 | /// Allow recovering from parse errors, capturing them as the parser continues |
154 | /// |
155 | /// Generally, this will be used indirectly via |
156 | /// [`RecoverableParser::recoverable_parse`][crate::RecoverableParser::recoverable_parse]. |
157 | #[cfg (feature = "unstable-recover" )] |
158 | #[derive (Clone, Debug)] |
159 | pub struct Recoverable<I, E> |
160 | where |
161 | I: Stream, |
162 | { |
163 | input: I, |
164 | errors: Vec<E>, |
165 | is_recoverable: bool, |
166 | } |
167 | |
168 | #[cfg (feature = "unstable-recover" )] |
169 | impl<I, E> Recoverable<I, E> |
170 | where |
171 | I: Stream, |
172 | { |
173 | /// Track recoverable errors with the stream |
174 | pub fn new(input: I) -> Self { |
175 | Self { |
176 | input, |
177 | errors: Default::default(), |
178 | is_recoverable: true, |
179 | } |
180 | } |
181 | |
182 | /// Act as a normal stream |
183 | pub fn unrecoverable(input: I) -> Self { |
184 | Self { |
185 | input, |
186 | errors: Default::default(), |
187 | is_recoverable: false, |
188 | } |
189 | } |
190 | |
191 | /// Access the current input and errors |
192 | pub fn into_parts(self) -> (I, Vec<E>) { |
193 | (self.input, self.errors) |
194 | } |
195 | } |
196 | |
197 | #[cfg (feature = "unstable-recover" )] |
198 | impl<I, E> AsRef<I> for Recoverable<I, E> |
199 | where |
200 | I: Stream, |
201 | { |
202 | #[inline (always)] |
203 | fn as_ref(&self) -> &I { |
204 | &self.input |
205 | } |
206 | } |
207 | |
208 | #[cfg (feature = "unstable-recover" )] |
209 | impl<I, E> crate::lib::std::ops::Deref for Recoverable<I, E> |
210 | where |
211 | I: Stream, |
212 | { |
213 | type Target = I; |
214 | |
215 | #[inline (always)] |
216 | fn deref(&self) -> &Self::Target { |
217 | &self.input |
218 | } |
219 | } |
220 | |
221 | #[cfg (feature = "unstable-recover" )] |
222 | impl<I: crate::lib::std::fmt::Display, E> crate::lib::std::fmt::Display for Recoverable<I, E> |
223 | where |
224 | I: Stream, |
225 | { |
226 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
227 | crate::lib::std::fmt::Display::fmt(&self.input, f) |
228 | } |
229 | } |
230 | |
231 | /// Thread global state through your parsers |
232 | /// |
233 | /// Use cases |
234 | /// - Recursion checks |
235 | /// - Error recovery |
236 | /// - Debugging |
237 | /// |
238 | /// # Example |
239 | /// |
240 | /// ``` |
241 | /// # use std::cell::Cell; |
242 | /// # use winnow::prelude::*; |
243 | /// # use winnow::stream::Stateful; |
244 | /// # use winnow::ascii::alpha1; |
245 | /// # type Error = (); |
246 | /// |
247 | /// #[derive(Clone, Debug)] |
248 | /// struct State<'s>(&'s Cell<u32>); |
249 | /// |
250 | /// impl<'s> State<'s> { |
251 | /// fn count(&self) { |
252 | /// self.0.set(self.0.get() + 1); |
253 | /// } |
254 | /// } |
255 | /// |
256 | /// type Stream<'is> = Stateful<&'is str, State<'is>>; |
257 | /// |
258 | /// fn word<'s>(i: &mut Stream<'s>) -> PResult<&'s str> { |
259 | /// i.state.count(); |
260 | /// alpha1.parse_next(i) |
261 | /// } |
262 | /// |
263 | /// let data = "Hello" ; |
264 | /// let state = Cell::new(0); |
265 | /// let input = Stream { input: data, state: State(&state) }; |
266 | /// let output = word.parse(input).unwrap(); |
267 | /// assert_eq!(state.get(), 1); |
268 | /// ``` |
269 | #[derive (Clone, Copy, Debug, Eq, PartialEq)] |
270 | #[doc (alias = "LocatedSpan" )] |
271 | pub struct Stateful<I, S> { |
272 | /// Inner input being wrapped in state |
273 | pub input: I, |
274 | /// User-provided state |
275 | pub state: S, |
276 | } |
277 | |
278 | impl<I, S> AsRef<I> for Stateful<I, S> { |
279 | #[inline (always)] |
280 | fn as_ref(&self) -> &I { |
281 | &self.input |
282 | } |
283 | } |
284 | |
285 | impl<I, S> crate::lib::std::ops::Deref for Stateful<I, S> { |
286 | type Target = I; |
287 | |
288 | #[inline (always)] |
289 | fn deref(&self) -> &Self::Target { |
290 | self.as_ref() |
291 | } |
292 | } |
293 | |
294 | impl<I: crate::lib::std::fmt::Display, S> crate::lib::std::fmt::Display for Stateful<I, S> { |
295 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
296 | self.input.fmt(f) |
297 | } |
298 | } |
299 | |
300 | /// Mark the input as a partial buffer for streaming input. |
301 | /// |
302 | /// Complete input means that we already have all of the data. This will be the common case with |
303 | /// small files that can be read entirely to memory. |
304 | /// |
305 | /// In contrast, streaming input assumes that we might not have all of the data. |
306 | /// This can happen with some network protocol or large file parsers, where the |
307 | /// input buffer can be full and need to be resized or refilled. |
308 | /// - [`ErrMode::Incomplete`] will report how much more data is needed. |
309 | /// - [`Parser::complete_err`][crate::Parser::complete_err] transform [`ErrMode::Incomplete`] to |
310 | /// [`ErrMode::Backtrack`] |
311 | /// |
312 | /// See also [`StreamIsPartial`] to tell whether the input supports complete or partial parsing. |
313 | /// |
314 | /// See also [Special Topics: Parsing Partial Input][crate::_topic::partial]. |
315 | /// |
316 | /// # Example |
317 | /// |
318 | /// Here is how it works in practice: |
319 | /// |
320 | /// ```rust |
321 | /// # use winnow::{PResult, error::ErrMode, error::Needed, error::{InputError, ErrorKind}, token, ascii, stream::Partial}; |
322 | /// # use winnow::prelude::*; |
323 | /// |
324 | /// fn take_partial<'s>(i: &mut Partial<&'s [u8]>) -> PResult<&'s [u8], InputError<Partial<&'s [u8]>>> { |
325 | /// token::take(4u8).parse_next(i) |
326 | /// } |
327 | /// |
328 | /// fn take_complete<'s>(i: &mut &'s [u8]) -> PResult<&'s [u8], InputError<&'s [u8]>> { |
329 | /// token::take(4u8).parse_next(i) |
330 | /// } |
331 | /// |
332 | /// // both parsers will take 4 bytes as expected |
333 | /// assert_eq!(take_partial.parse_peek(Partial::new(&b"abcde" [..])), Ok((Partial::new(&b"e" [..]), &b"abcd" [..]))); |
334 | /// assert_eq!(take_complete.parse_peek(&b"abcde" [..]), Ok((&b"e" [..], &b"abcd" [..]))); |
335 | /// |
336 | /// // if the input is smaller than 4 bytes, the partial parser |
337 | /// // will return `Incomplete` to indicate that we need more data |
338 | /// assert_eq!(take_partial.parse_peek(Partial::new(&b"abc" [..])), Err(ErrMode::Incomplete(Needed::new(1)))); |
339 | /// |
340 | /// // but the complete parser will return an error |
341 | /// assert_eq!(take_complete.parse_peek(&b"abc" [..]), Err(ErrMode::Backtrack(InputError::new(&b"abc" [..], ErrorKind::Slice)))); |
342 | /// |
343 | /// // the alpha0 function recognizes 0 or more alphabetic characters |
344 | /// fn alpha0_partial<'s>(i: &mut Partial<&'s str>) -> PResult<&'s str, InputError<Partial<&'s str>>> { |
345 | /// ascii::alpha0.parse_next(i) |
346 | /// } |
347 | /// |
348 | /// fn alpha0_complete<'s>(i: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> { |
349 | /// ascii::alpha0.parse_next(i) |
350 | /// } |
351 | /// |
352 | /// // if there's a clear limit to the recognized characters, both parsers work the same way |
353 | /// assert_eq!(alpha0_partial.parse_peek(Partial::new("abcd;" )), Ok((Partial::new(";" ), "abcd" ))); |
354 | /// assert_eq!(alpha0_complete.parse_peek("abcd;" ), Ok((";" , "abcd" ))); |
355 | /// |
356 | /// // but when there's no limit, the partial version returns `Incomplete`, because it cannot |
357 | /// // know if more input data should be recognized. The whole input could be "abcd;", or |
358 | /// // "abcde;" |
359 | /// assert_eq!(alpha0_partial.parse_peek(Partial::new("abcd" )), Err(ErrMode::Incomplete(Needed::new(1)))); |
360 | /// |
361 | /// // while the complete version knows that all of the data is there |
362 | /// assert_eq!(alpha0_complete.parse_peek("abcd" ), Ok(("" , "abcd" ))); |
363 | /// ``` |
364 | #[derive (Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] |
365 | pub struct Partial<I> { |
366 | input: I, |
367 | partial: bool, |
368 | } |
369 | |
370 | impl<I> Partial<I> |
371 | where |
372 | I: StreamIsPartial, |
373 | { |
374 | /// Create a partial input |
375 | pub fn new(input: I) -> Self { |
376 | debug_assert!( |
377 | !I::is_partial_supported(), |
378 | "`Partial` can only wrap complete sources" |
379 | ); |
380 | let partial: bool = true; |
381 | Self { input, partial } |
382 | } |
383 | |
384 | /// Extract the original [`Stream`] |
385 | #[inline (always)] |
386 | pub fn into_inner(self) -> I { |
387 | self.input |
388 | } |
389 | } |
390 | |
391 | impl<I> Default for Partial<I> |
392 | where |
393 | I: Default + StreamIsPartial, |
394 | { |
395 | fn default() -> Self { |
396 | Self::new(I::default()) |
397 | } |
398 | } |
399 | |
400 | impl<I> crate::lib::std::ops::Deref for Partial<I> { |
401 | type Target = I; |
402 | |
403 | #[inline (always)] |
404 | fn deref(&self) -> &Self::Target { |
405 | &self.input |
406 | } |
407 | } |
408 | |
409 | impl<I: crate::lib::std::fmt::Display> crate::lib::std::fmt::Display for Partial<I> { |
410 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
411 | self.input.fmt(f) |
412 | } |
413 | } |
414 | |
415 | /// Abstract method to calculate the input length |
416 | pub trait SliceLen { |
417 | /// Calculates the input length, as indicated by its name, |
418 | /// and the name of the trait itself |
419 | fn slice_len(&self) -> usize; |
420 | } |
421 | |
422 | impl<S: SliceLen> SliceLen for AsciiCaseless<S> { |
423 | #[inline (always)] |
424 | fn slice_len(&self) -> usize { |
425 | self.0.slice_len() |
426 | } |
427 | } |
428 | |
429 | impl<'a, T> SliceLen for &'a [T] { |
430 | #[inline (always)] |
431 | fn slice_len(&self) -> usize { |
432 | self.len() |
433 | } |
434 | } |
435 | |
436 | impl<T, const LEN: usize> SliceLen for [T; LEN] { |
437 | #[inline (always)] |
438 | fn slice_len(&self) -> usize { |
439 | self.len() |
440 | } |
441 | } |
442 | |
443 | impl<'a, T, const LEN: usize> SliceLen for &'a [T; LEN] { |
444 | #[inline (always)] |
445 | fn slice_len(&self) -> usize { |
446 | self.len() |
447 | } |
448 | } |
449 | |
450 | impl<'a> SliceLen for &'a str { |
451 | #[inline (always)] |
452 | fn slice_len(&self) -> usize { |
453 | self.len() |
454 | } |
455 | } |
456 | |
457 | impl SliceLen for u8 { |
458 | #[inline (always)] |
459 | fn slice_len(&self) -> usize { |
460 | 1 |
461 | } |
462 | } |
463 | |
464 | impl SliceLen for char { |
465 | #[inline (always)] |
466 | fn slice_len(&self) -> usize { |
467 | self.len_utf8() |
468 | } |
469 | } |
470 | |
471 | impl<'a> SliceLen for &'a Bytes { |
472 | #[inline (always)] |
473 | fn slice_len(&self) -> usize { |
474 | self.len() |
475 | } |
476 | } |
477 | |
478 | impl<'a> SliceLen for &'a BStr { |
479 | #[inline (always)] |
480 | fn slice_len(&self) -> usize { |
481 | self.len() |
482 | } |
483 | } |
484 | |
485 | impl<I> SliceLen for (I, usize, usize) |
486 | where |
487 | I: SliceLen, |
488 | { |
489 | #[inline (always)] |
490 | fn slice_len(&self) -> usize { |
491 | self.0.slice_len() * 8 + self.2 - self.1 |
492 | } |
493 | } |
494 | |
495 | impl<I> SliceLen for Located<I> |
496 | where |
497 | I: SliceLen, |
498 | { |
499 | #[inline (always)] |
500 | fn slice_len(&self) -> usize { |
501 | self.input.slice_len() |
502 | } |
503 | } |
504 | |
505 | #[cfg (feature = "unstable-recover" )] |
506 | impl<I, E> SliceLen for Recoverable<I, E> |
507 | where |
508 | I: SliceLen, |
509 | I: Stream, |
510 | { |
511 | #[inline (always)] |
512 | fn slice_len(&self) -> usize { |
513 | self.input.slice_len() |
514 | } |
515 | } |
516 | |
517 | impl<I, S> SliceLen for Stateful<I, S> |
518 | where |
519 | I: SliceLen, |
520 | { |
521 | #[inline (always)] |
522 | fn slice_len(&self) -> usize { |
523 | self.input.slice_len() |
524 | } |
525 | } |
526 | |
527 | impl<I> SliceLen for Partial<I> |
528 | where |
529 | I: SliceLen, |
530 | { |
531 | #[inline (always)] |
532 | fn slice_len(&self) -> usize { |
533 | self.input.slice_len() |
534 | } |
535 | } |
536 | |
537 | /// Core definition for parser input state |
538 | pub trait Stream: Offset<<Self as Stream>::Checkpoint> + crate::lib::std::fmt::Debug { |
539 | /// The smallest unit being parsed |
540 | /// |
541 | /// Example: `u8` for `&[u8]` or `char` for `&str` |
542 | type Token: crate::lib::std::fmt::Debug; |
543 | /// Sequence of `Token`s |
544 | /// |
545 | /// Example: `&[u8]` for `Located<&[u8]>` or `&str` for `Located<&str>` |
546 | type Slice: crate::lib::std::fmt::Debug; |
547 | |
548 | /// Iterate with the offset from the current location |
549 | type IterOffsets: Iterator<Item = (usize, Self::Token)>; |
550 | |
551 | /// A parse location within the stream |
552 | type Checkpoint: Offset + Clone + crate::lib::std::fmt::Debug; |
553 | |
554 | /// Iterate with the offset from the current location |
555 | fn iter_offsets(&self) -> Self::IterOffsets; |
556 | |
557 | /// Returns the offset to the end of the input |
558 | fn eof_offset(&self) -> usize; |
559 | |
560 | /// Split off the next token from the input |
561 | fn next_token(&mut self) -> Option<Self::Token>; |
562 | /// Split off the next token from the input |
563 | #[inline (always)] |
564 | fn peek_token(&self) -> Option<(Self, Self::Token)> |
565 | where |
566 | Self: Clone, |
567 | { |
568 | let mut peek = self.clone(); |
569 | let token = peek.next_token()?; |
570 | Some((peek, token)) |
571 | } |
572 | |
573 | /// Finds the offset of the next matching token |
574 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
575 | where |
576 | P: Fn(Self::Token) -> bool; |
577 | /// Get the offset for the number of `tokens` into the stream |
578 | /// |
579 | /// This means "0 tokens" will return `0` offset |
580 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed>; |
581 | /// Split off a slice of tokens from the input |
582 | /// |
583 | /// **NOTE:** For inputs with variable width tokens, like `&str`'s `char`, `offset` might not correspond |
584 | /// with the number of tokens. To get a valid offset, use: |
585 | /// - [`Stream::eof_offset`] |
586 | /// - [`Stream::iter_offsets`] |
587 | /// - [`Stream::offset_for`] |
588 | /// - [`Stream::offset_at`] |
589 | /// |
590 | /// # Panic |
591 | /// |
592 | /// This will panic if |
593 | /// |
594 | /// * Indexes must be within bounds of the original input; |
595 | /// * Indexes must uphold invariants of the stream, like for `str` they must lie on UTF-8 |
596 | /// sequence boundaries. |
597 | /// |
598 | fn next_slice(&mut self, offset: usize) -> Self::Slice; |
599 | /// Split off a slice of tokens from the input |
600 | #[inline (always)] |
601 | fn peek_slice(&self, offset: usize) -> (Self, Self::Slice) |
602 | where |
603 | Self: Clone, |
604 | { |
605 | let mut peek = self.clone(); |
606 | let slice = peek.next_slice(offset); |
607 | (peek, slice) |
608 | } |
609 | |
610 | /// Advance to the end of the stream |
611 | #[inline (always)] |
612 | fn finish(&mut self) -> Self::Slice { |
613 | self.next_slice(self.eof_offset()) |
614 | } |
615 | /// Advance to the end of the stream |
616 | #[inline (always)] |
617 | fn peek_finish(&self) -> (Self, Self::Slice) |
618 | where |
619 | Self: Clone, |
620 | { |
621 | let mut peek = self.clone(); |
622 | let slice = peek.finish(); |
623 | (peek, slice) |
624 | } |
625 | |
626 | /// Save the current parse location within the stream |
627 | fn checkpoint(&self) -> Self::Checkpoint; |
628 | /// Revert the stream to a prior [`Self::Checkpoint`] |
629 | /// |
630 | /// # Panic |
631 | /// |
632 | /// May panic if an invalid [`Self::Checkpoint`] is provided |
633 | fn reset(&mut self, checkpoint: &Self::Checkpoint); |
634 | |
635 | /// Return the inner-most stream |
636 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug; |
637 | } |
638 | |
639 | impl<'i, T> Stream for &'i [T] |
640 | where |
641 | T: Clone + crate::lib::std::fmt::Debug, |
642 | { |
643 | type Token = T; |
644 | type Slice = &'i [T]; |
645 | |
646 | type IterOffsets = Enumerate<Cloned<Iter<'i, T>>>; |
647 | |
648 | type Checkpoint = Checkpoint<Self, Self>; |
649 | |
650 | #[inline (always)] |
651 | fn iter_offsets(&self) -> Self::IterOffsets { |
652 | self.iter().cloned().enumerate() |
653 | } |
654 | #[inline (always)] |
655 | fn eof_offset(&self) -> usize { |
656 | self.len() |
657 | } |
658 | |
659 | #[inline (always)] |
660 | fn next_token(&mut self) -> Option<Self::Token> { |
661 | let (token, next) = self.split_first()?; |
662 | *self = next; |
663 | Some(token.clone()) |
664 | } |
665 | |
666 | #[inline (always)] |
667 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
668 | where |
669 | P: Fn(Self::Token) -> bool, |
670 | { |
671 | self.iter().position(|b| predicate(b.clone())) |
672 | } |
673 | #[inline (always)] |
674 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
675 | if let Some(needed) = tokens.checked_sub(self.len()).and_then(NonZeroUsize::new) { |
676 | Err(Needed::Size(needed)) |
677 | } else { |
678 | Ok(tokens) |
679 | } |
680 | } |
681 | #[inline (always)] |
682 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
683 | let (slice, next) = self.split_at(offset); |
684 | *self = next; |
685 | slice |
686 | } |
687 | |
688 | #[inline (always)] |
689 | fn checkpoint(&self) -> Self::Checkpoint { |
690 | Checkpoint::<_, Self>::new(*self) |
691 | } |
692 | #[inline (always)] |
693 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
694 | *self = checkpoint.inner; |
695 | } |
696 | |
697 | #[inline (always)] |
698 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
699 | self |
700 | } |
701 | } |
702 | |
703 | impl<'i> Stream for &'i str { |
704 | type Token = char; |
705 | type Slice = &'i str; |
706 | |
707 | type IterOffsets = CharIndices<'i>; |
708 | |
709 | type Checkpoint = Checkpoint<Self, Self>; |
710 | |
711 | #[inline (always)] |
712 | fn iter_offsets(&self) -> Self::IterOffsets { |
713 | self.char_indices() |
714 | } |
715 | #[inline (always)] |
716 | fn eof_offset(&self) -> usize { |
717 | self.len() |
718 | } |
719 | |
720 | #[inline (always)] |
721 | fn next_token(&mut self) -> Option<Self::Token> { |
722 | let c = self.chars().next()?; |
723 | let offset = c.len(); |
724 | *self = &self[offset..]; |
725 | Some(c) |
726 | } |
727 | |
728 | #[inline (always)] |
729 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
730 | where |
731 | P: Fn(Self::Token) -> bool, |
732 | { |
733 | for (o, c) in self.iter_offsets() { |
734 | if predicate(c) { |
735 | return Some(o); |
736 | } |
737 | } |
738 | None |
739 | } |
740 | #[inline ] |
741 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
742 | let mut cnt = 0; |
743 | for (offset, _) in self.iter_offsets() { |
744 | if cnt == tokens { |
745 | return Ok(offset); |
746 | } |
747 | cnt += 1; |
748 | } |
749 | |
750 | if cnt == tokens { |
751 | Ok(self.eof_offset()) |
752 | } else { |
753 | Err(Needed::Unknown) |
754 | } |
755 | } |
756 | #[inline (always)] |
757 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
758 | let (slice, next) = self.split_at(offset); |
759 | *self = next; |
760 | slice |
761 | } |
762 | |
763 | #[inline (always)] |
764 | fn checkpoint(&self) -> Self::Checkpoint { |
765 | Checkpoint::<_, Self>::new(*self) |
766 | } |
767 | #[inline (always)] |
768 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
769 | *self = checkpoint.inner; |
770 | } |
771 | |
772 | #[inline (always)] |
773 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
774 | self |
775 | } |
776 | } |
777 | |
778 | impl<'i> Stream for &'i Bytes { |
779 | type Token = u8; |
780 | type Slice = &'i [u8]; |
781 | |
782 | type IterOffsets = Enumerate<Cloned<Iter<'i, u8>>>; |
783 | |
784 | type Checkpoint = Checkpoint<Self, Self>; |
785 | |
786 | #[inline (always)] |
787 | fn iter_offsets(&self) -> Self::IterOffsets { |
788 | self.iter().cloned().enumerate() |
789 | } |
790 | #[inline (always)] |
791 | fn eof_offset(&self) -> usize { |
792 | self.len() |
793 | } |
794 | |
795 | #[inline (always)] |
796 | fn next_token(&mut self) -> Option<Self::Token> { |
797 | if self.is_empty() { |
798 | None |
799 | } else { |
800 | let token = self[0]; |
801 | *self = &self[1..]; |
802 | Some(token) |
803 | } |
804 | } |
805 | |
806 | #[inline (always)] |
807 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
808 | where |
809 | P: Fn(Self::Token) -> bool, |
810 | { |
811 | self.iter().position(|b| predicate(*b)) |
812 | } |
813 | #[inline (always)] |
814 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
815 | if let Some(needed) = tokens.checked_sub(self.len()).and_then(NonZeroUsize::new) { |
816 | Err(Needed::Size(needed)) |
817 | } else { |
818 | Ok(tokens) |
819 | } |
820 | } |
821 | #[inline (always)] |
822 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
823 | let (slice, next) = self.0.split_at(offset); |
824 | *self = Bytes::from_bytes(next); |
825 | slice |
826 | } |
827 | |
828 | #[inline (always)] |
829 | fn checkpoint(&self) -> Self::Checkpoint { |
830 | Checkpoint::<_, Self>::new(*self) |
831 | } |
832 | #[inline (always)] |
833 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
834 | *self = checkpoint.inner; |
835 | } |
836 | |
837 | #[inline (always)] |
838 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
839 | self |
840 | } |
841 | } |
842 | |
843 | impl<'i> Stream for &'i BStr { |
844 | type Token = u8; |
845 | type Slice = &'i [u8]; |
846 | |
847 | type IterOffsets = Enumerate<Cloned<Iter<'i, u8>>>; |
848 | |
849 | type Checkpoint = Checkpoint<Self, Self>; |
850 | |
851 | #[inline (always)] |
852 | fn iter_offsets(&self) -> Self::IterOffsets { |
853 | self.iter().cloned().enumerate() |
854 | } |
855 | #[inline (always)] |
856 | fn eof_offset(&self) -> usize { |
857 | self.len() |
858 | } |
859 | |
860 | #[inline (always)] |
861 | fn next_token(&mut self) -> Option<Self::Token> { |
862 | if self.is_empty() { |
863 | None |
864 | } else { |
865 | let token = self[0]; |
866 | *self = &self[1..]; |
867 | Some(token) |
868 | } |
869 | } |
870 | |
871 | #[inline (always)] |
872 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
873 | where |
874 | P: Fn(Self::Token) -> bool, |
875 | { |
876 | self.iter().position(|b| predicate(*b)) |
877 | } |
878 | #[inline (always)] |
879 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
880 | if let Some(needed) = tokens.checked_sub(self.len()).and_then(NonZeroUsize::new) { |
881 | Err(Needed::Size(needed)) |
882 | } else { |
883 | Ok(tokens) |
884 | } |
885 | } |
886 | #[inline (always)] |
887 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
888 | let (slice, next) = self.0.split_at(offset); |
889 | *self = BStr::from_bytes(next); |
890 | slice |
891 | } |
892 | |
893 | #[inline (always)] |
894 | fn checkpoint(&self) -> Self::Checkpoint { |
895 | Checkpoint::<_, Self>::new(*self) |
896 | } |
897 | #[inline (always)] |
898 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
899 | *self = checkpoint.inner; |
900 | } |
901 | |
902 | #[inline (always)] |
903 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
904 | self |
905 | } |
906 | } |
907 | |
908 | impl<I> Stream for (I, usize) |
909 | where |
910 | I: Stream<Token = u8> + Clone, |
911 | { |
912 | type Token = bool; |
913 | type Slice = (I::Slice, usize, usize); |
914 | |
915 | type IterOffsets = BitOffsets<I>; |
916 | |
917 | type Checkpoint = Checkpoint<(I::Checkpoint, usize), Self>; |
918 | |
919 | #[inline (always)] |
920 | fn iter_offsets(&self) -> Self::IterOffsets { |
921 | BitOffsets { |
922 | i: self.clone(), |
923 | o: 0, |
924 | } |
925 | } |
926 | #[inline (always)] |
927 | fn eof_offset(&self) -> usize { |
928 | let offset = self.0.eof_offset() * 8; |
929 | if offset == 0 { |
930 | 0 |
931 | } else { |
932 | offset - self.1 |
933 | } |
934 | } |
935 | |
936 | #[inline (always)] |
937 | fn next_token(&mut self) -> Option<Self::Token> { |
938 | next_bit(self) |
939 | } |
940 | |
941 | #[inline (always)] |
942 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
943 | where |
944 | P: Fn(Self::Token) -> bool, |
945 | { |
946 | self.iter_offsets() |
947 | .find_map(|(o, b)| predicate(b).then_some(o)) |
948 | } |
949 | #[inline (always)] |
950 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
951 | if let Some(needed) = tokens |
952 | .checked_sub(self.eof_offset()) |
953 | .and_then(NonZeroUsize::new) |
954 | { |
955 | Err(Needed::Size(needed)) |
956 | } else { |
957 | Ok(tokens) |
958 | } |
959 | } |
960 | #[inline (always)] |
961 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
962 | let byte_offset = (offset + self.1) / 8; |
963 | let end_offset = (offset + self.1) % 8; |
964 | let s = self.0.next_slice(byte_offset); |
965 | let start_offset = self.1; |
966 | self.1 = end_offset; |
967 | (s, start_offset, end_offset) |
968 | } |
969 | |
970 | #[inline (always)] |
971 | fn checkpoint(&self) -> Self::Checkpoint { |
972 | Checkpoint::<_, Self>::new((self.0.checkpoint(), self.1)) |
973 | } |
974 | #[inline (always)] |
975 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
976 | self.0.reset(&checkpoint.inner.0); |
977 | self.1 = checkpoint.inner.1; |
978 | } |
979 | |
980 | #[inline (always)] |
981 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
982 | &self.0 |
983 | } |
984 | } |
985 | |
986 | /// Iterator for [bit][crate::binary::bits] stream (`(I, usize)`) |
987 | pub struct BitOffsets<I> { |
988 | i: (I, usize), |
989 | o: usize, |
990 | } |
991 | |
992 | impl<I> Iterator for BitOffsets<I> |
993 | where |
994 | I: Stream<Token = u8> + Clone, |
995 | { |
996 | type Item = (usize, bool); |
997 | fn next(&mut self) -> Option<Self::Item> { |
998 | let b: bool = next_bit(&mut self.i)?; |
999 | let o: usize = self.o; |
1000 | |
1001 | self.o += 1; |
1002 | |
1003 | Some((o, b)) |
1004 | } |
1005 | } |
1006 | |
1007 | fn next_bit<I>(i: &mut (I, usize)) -> Option<bool> |
1008 | where |
1009 | I: Stream<Token = u8> + Clone, |
1010 | { |
1011 | if i.eof_offset() == 0 { |
1012 | return None; |
1013 | } |
1014 | let offset: usize = i.1; |
1015 | |
1016 | let mut next_i: I = i.0.clone(); |
1017 | let byte: u8 = next_i.next_token()?; |
1018 | let bit: bool = (byte >> offset) & 0x1 == 0x1; |
1019 | |
1020 | let next_offset: usize = offset + 1; |
1021 | if next_offset == 8 { |
1022 | i.0 = next_i; |
1023 | i.1 = 0; |
1024 | Some(bit) |
1025 | } else { |
1026 | i.1 = next_offset; |
1027 | Some(bit) |
1028 | } |
1029 | } |
1030 | |
1031 | impl<I: Stream> Stream for Located<I> { |
1032 | type Token = <I as Stream>::Token; |
1033 | type Slice = <I as Stream>::Slice; |
1034 | |
1035 | type IterOffsets = <I as Stream>::IterOffsets; |
1036 | |
1037 | type Checkpoint = Checkpoint<I::Checkpoint, Self>; |
1038 | |
1039 | #[inline (always)] |
1040 | fn iter_offsets(&self) -> Self::IterOffsets { |
1041 | self.input.iter_offsets() |
1042 | } |
1043 | #[inline (always)] |
1044 | fn eof_offset(&self) -> usize { |
1045 | self.input.eof_offset() |
1046 | } |
1047 | |
1048 | #[inline (always)] |
1049 | fn next_token(&mut self) -> Option<Self::Token> { |
1050 | self.input.next_token() |
1051 | } |
1052 | |
1053 | #[inline (always)] |
1054 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
1055 | where |
1056 | P: Fn(Self::Token) -> bool, |
1057 | { |
1058 | self.input.offset_for(predicate) |
1059 | } |
1060 | #[inline (always)] |
1061 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
1062 | self.input.offset_at(tokens) |
1063 | } |
1064 | #[inline (always)] |
1065 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
1066 | self.input.next_slice(offset) |
1067 | } |
1068 | |
1069 | #[inline (always)] |
1070 | fn checkpoint(&self) -> Self::Checkpoint { |
1071 | Checkpoint::<_, Self>::new(self.input.checkpoint()) |
1072 | } |
1073 | #[inline (always)] |
1074 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
1075 | self.input.reset(&checkpoint.inner); |
1076 | } |
1077 | |
1078 | #[inline (always)] |
1079 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
1080 | &self.input |
1081 | } |
1082 | } |
1083 | |
1084 | #[cfg (feature = "unstable-recover" )] |
1085 | impl<I, E: crate::lib::std::fmt::Debug> Stream for Recoverable<I, E> |
1086 | where |
1087 | I: Stream, |
1088 | { |
1089 | type Token = <I as Stream>::Token; |
1090 | type Slice = <I as Stream>::Slice; |
1091 | |
1092 | type IterOffsets = <I as Stream>::IterOffsets; |
1093 | |
1094 | type Checkpoint = Checkpoint<I::Checkpoint, Self>; |
1095 | |
1096 | #[inline (always)] |
1097 | fn iter_offsets(&self) -> Self::IterOffsets { |
1098 | self.input.iter_offsets() |
1099 | } |
1100 | #[inline (always)] |
1101 | fn eof_offset(&self) -> usize { |
1102 | self.input.eof_offset() |
1103 | } |
1104 | |
1105 | #[inline (always)] |
1106 | fn next_token(&mut self) -> Option<Self::Token> { |
1107 | self.input.next_token() |
1108 | } |
1109 | |
1110 | #[inline (always)] |
1111 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
1112 | where |
1113 | P: Fn(Self::Token) -> bool, |
1114 | { |
1115 | self.input.offset_for(predicate) |
1116 | } |
1117 | #[inline (always)] |
1118 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
1119 | self.input.offset_at(tokens) |
1120 | } |
1121 | #[inline (always)] |
1122 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
1123 | self.input.next_slice(offset) |
1124 | } |
1125 | |
1126 | #[inline (always)] |
1127 | fn checkpoint(&self) -> Self::Checkpoint { |
1128 | Checkpoint::<_, Self>::new(self.input.checkpoint()) |
1129 | } |
1130 | #[inline (always)] |
1131 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
1132 | self.input.reset(&checkpoint.inner); |
1133 | } |
1134 | |
1135 | #[inline (always)] |
1136 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
1137 | &self.input |
1138 | } |
1139 | } |
1140 | |
1141 | impl<I: Stream, S: crate::lib::std::fmt::Debug> Stream for Stateful<I, S> { |
1142 | type Token = <I as Stream>::Token; |
1143 | type Slice = <I as Stream>::Slice; |
1144 | |
1145 | type IterOffsets = <I as Stream>::IterOffsets; |
1146 | |
1147 | type Checkpoint = Checkpoint<I::Checkpoint, Self>; |
1148 | |
1149 | #[inline (always)] |
1150 | fn iter_offsets(&self) -> Self::IterOffsets { |
1151 | self.input.iter_offsets() |
1152 | } |
1153 | #[inline (always)] |
1154 | fn eof_offset(&self) -> usize { |
1155 | self.input.eof_offset() |
1156 | } |
1157 | |
1158 | #[inline (always)] |
1159 | fn next_token(&mut self) -> Option<Self::Token> { |
1160 | self.input.next_token() |
1161 | } |
1162 | |
1163 | #[inline (always)] |
1164 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
1165 | where |
1166 | P: Fn(Self::Token) -> bool, |
1167 | { |
1168 | self.input.offset_for(predicate) |
1169 | } |
1170 | #[inline (always)] |
1171 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
1172 | self.input.offset_at(tokens) |
1173 | } |
1174 | #[inline (always)] |
1175 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
1176 | self.input.next_slice(offset) |
1177 | } |
1178 | |
1179 | #[inline (always)] |
1180 | fn checkpoint(&self) -> Self::Checkpoint { |
1181 | Checkpoint::<_, Self>::new(self.input.checkpoint()) |
1182 | } |
1183 | #[inline (always)] |
1184 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
1185 | self.input.reset(&checkpoint.inner); |
1186 | } |
1187 | |
1188 | #[inline (always)] |
1189 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
1190 | &self.input |
1191 | } |
1192 | } |
1193 | |
1194 | impl<I: Stream> Stream for Partial<I> { |
1195 | type Token = <I as Stream>::Token; |
1196 | type Slice = <I as Stream>::Slice; |
1197 | |
1198 | type IterOffsets = <I as Stream>::IterOffsets; |
1199 | |
1200 | type Checkpoint = Checkpoint<I::Checkpoint, Self>; |
1201 | |
1202 | #[inline (always)] |
1203 | fn iter_offsets(&self) -> Self::IterOffsets { |
1204 | self.input.iter_offsets() |
1205 | } |
1206 | #[inline (always)] |
1207 | fn eof_offset(&self) -> usize { |
1208 | self.input.eof_offset() |
1209 | } |
1210 | |
1211 | #[inline (always)] |
1212 | fn next_token(&mut self) -> Option<Self::Token> { |
1213 | self.input.next_token() |
1214 | } |
1215 | |
1216 | #[inline (always)] |
1217 | fn offset_for<P>(&self, predicate: P) -> Option<usize> |
1218 | where |
1219 | P: Fn(Self::Token) -> bool, |
1220 | { |
1221 | self.input.offset_for(predicate) |
1222 | } |
1223 | #[inline (always)] |
1224 | fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { |
1225 | self.input.offset_at(tokens) |
1226 | } |
1227 | #[inline (always)] |
1228 | fn next_slice(&mut self, offset: usize) -> Self::Slice { |
1229 | self.input.next_slice(offset) |
1230 | } |
1231 | |
1232 | #[inline (always)] |
1233 | fn checkpoint(&self) -> Self::Checkpoint { |
1234 | Checkpoint::<_, Self>::new(self.input.checkpoint()) |
1235 | } |
1236 | #[inline (always)] |
1237 | fn reset(&mut self, checkpoint: &Self::Checkpoint) { |
1238 | self.input.reset(&checkpoint.inner); |
1239 | } |
1240 | |
1241 | #[inline (always)] |
1242 | fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { |
1243 | &self.input |
1244 | } |
1245 | } |
1246 | |
1247 | /// Number of indices input has advanced since start of parsing |
1248 | /// |
1249 | /// See [`Located`] for adding location tracking to your [`Stream`] |
1250 | pub trait Location { |
1251 | /// Number of indices input has advanced since start of parsing |
1252 | fn location(&self) -> usize; |
1253 | } |
1254 | |
1255 | impl<I> Location for Located<I> |
1256 | where |
1257 | I: Clone + Offset, |
1258 | { |
1259 | #[inline (always)] |
1260 | fn location(&self) -> usize { |
1261 | self.location() |
1262 | } |
1263 | } |
1264 | |
1265 | #[cfg (feature = "unstable-recover" )] |
1266 | impl<I, E> Location for Recoverable<I, E> |
1267 | where |
1268 | I: Location, |
1269 | I: Stream, |
1270 | { |
1271 | #[inline (always)] |
1272 | fn location(&self) -> usize { |
1273 | self.input.location() |
1274 | } |
1275 | } |
1276 | |
1277 | impl<I, S> Location for Stateful<I, S> |
1278 | where |
1279 | I: Location, |
1280 | { |
1281 | #[inline (always)] |
1282 | fn location(&self) -> usize { |
1283 | self.input.location() |
1284 | } |
1285 | } |
1286 | |
1287 | impl<I> Location for Partial<I> |
1288 | where |
1289 | I: Location, |
1290 | { |
1291 | #[inline (always)] |
1292 | fn location(&self) -> usize { |
1293 | self.input.location() |
1294 | } |
1295 | } |
1296 | |
1297 | /// Capture top-level errors in the middle of parsing so parsing can resume |
1298 | /// |
1299 | /// See [`Recoverable`] for adding error recovery tracking to your [`Stream`] |
1300 | #[cfg (feature = "unstable-recover" )] |
1301 | pub trait Recover<E>: Stream { |
1302 | /// Capture a top-level error |
1303 | /// |
1304 | /// May return `Err(err)` if recovery is not possible (e.g. if [`Recover::is_recovery_supported`] |
1305 | /// returns `false`). |
1306 | fn record_err( |
1307 | &mut self, |
1308 | token_start: &Self::Checkpoint, |
1309 | err_start: &Self::Checkpoint, |
1310 | err: ErrMode<E>, |
1311 | ) -> Result<(), ErrMode<E>>; |
1312 | |
1313 | /// Report whether the [`Stream`] can save off errors for recovery |
1314 | fn is_recovery_supported() -> bool; |
1315 | } |
1316 | |
1317 | #[cfg (feature = "unstable-recover" )] |
1318 | impl<'a, T, E> Recover<E> for &'a [T] |
1319 | where |
1320 | &'a [T]: Stream, |
1321 | { |
1322 | #[inline (always)] |
1323 | fn record_err( |
1324 | &mut self, |
1325 | _token_start: &Self::Checkpoint, |
1326 | _err_start: &Self::Checkpoint, |
1327 | err: ErrMode<E>, |
1328 | ) -> Result<(), ErrMode<E>> { |
1329 | Err(err) |
1330 | } |
1331 | |
1332 | /// Report whether the [`Stream`] can save off errors for recovery |
1333 | #[inline (always)] |
1334 | fn is_recovery_supported() -> bool { |
1335 | false |
1336 | } |
1337 | } |
1338 | |
1339 | #[cfg (feature = "unstable-recover" )] |
1340 | impl<'a, E> Recover<E> for &'a str { |
1341 | #[inline (always)] |
1342 | fn record_err( |
1343 | &mut self, |
1344 | _token_start: &Self::Checkpoint, |
1345 | _err_start: &Self::Checkpoint, |
1346 | err: ErrMode<E>, |
1347 | ) -> Result<(), ErrMode<E>> { |
1348 | Err(err) |
1349 | } |
1350 | |
1351 | /// Report whether the [`Stream`] can save off errors for recovery |
1352 | #[inline (always)] |
1353 | fn is_recovery_supported() -> bool { |
1354 | false |
1355 | } |
1356 | } |
1357 | |
1358 | #[cfg (feature = "unstable-recover" )] |
1359 | impl<'a, E> Recover<E> for &'a Bytes { |
1360 | #[inline (always)] |
1361 | fn record_err( |
1362 | &mut self, |
1363 | _token_start: &Self::Checkpoint, |
1364 | _err_start: &Self::Checkpoint, |
1365 | err: ErrMode<E>, |
1366 | ) -> Result<(), ErrMode<E>> { |
1367 | Err(err) |
1368 | } |
1369 | |
1370 | /// Report whether the [`Stream`] can save off errors for recovery |
1371 | #[inline (always)] |
1372 | fn is_recovery_supported() -> bool { |
1373 | false |
1374 | } |
1375 | } |
1376 | |
1377 | #[cfg (feature = "unstable-recover" )] |
1378 | impl<'a, E> Recover<E> for &'a BStr { |
1379 | #[inline (always)] |
1380 | fn record_err( |
1381 | &mut self, |
1382 | _token_start: &Self::Checkpoint, |
1383 | _err_start: &Self::Checkpoint, |
1384 | err: ErrMode<E>, |
1385 | ) -> Result<(), ErrMode<E>> { |
1386 | Err(err) |
1387 | } |
1388 | |
1389 | /// Report whether the [`Stream`] can save off errors for recovery |
1390 | #[inline (always)] |
1391 | fn is_recovery_supported() -> bool { |
1392 | false |
1393 | } |
1394 | } |
1395 | |
1396 | #[cfg (feature = "unstable-recover" )] |
1397 | impl<I, E> Recover<E> for (I, usize) |
1398 | where |
1399 | I: Recover<E>, |
1400 | I: Stream<Token = u8> + Clone, |
1401 | { |
1402 | #[inline (always)] |
1403 | fn record_err( |
1404 | &mut self, |
1405 | _token_start: &Self::Checkpoint, |
1406 | _err_start: &Self::Checkpoint, |
1407 | err: ErrMode<E>, |
1408 | ) -> Result<(), ErrMode<E>> { |
1409 | Err(err) |
1410 | } |
1411 | |
1412 | /// Report whether the [`Stream`] can save off errors for recovery |
1413 | #[inline (always)] |
1414 | fn is_recovery_supported() -> bool { |
1415 | false |
1416 | } |
1417 | } |
1418 | |
1419 | #[cfg (feature = "unstable-recover" )] |
1420 | impl<I, E> Recover<E> for Located<I> |
1421 | where |
1422 | I: Recover<E>, |
1423 | I: Stream, |
1424 | { |
1425 | #[inline (always)] |
1426 | fn record_err( |
1427 | &mut self, |
1428 | _token_start: &Self::Checkpoint, |
1429 | _err_start: &Self::Checkpoint, |
1430 | err: ErrMode<E>, |
1431 | ) -> Result<(), ErrMode<E>> { |
1432 | Err(err) |
1433 | } |
1434 | |
1435 | /// Report whether the [`Stream`] can save off errors for recovery |
1436 | #[inline (always)] |
1437 | fn is_recovery_supported() -> bool { |
1438 | false |
1439 | } |
1440 | } |
1441 | |
1442 | #[cfg (feature = "unstable-recover" )] |
1443 | impl<I, E, R> Recover<E> for Recoverable<I, R> |
1444 | where |
1445 | I: Stream, |
1446 | R: FromRecoverableError<Self, E>, |
1447 | R: crate::lib::std::fmt::Debug, |
1448 | { |
1449 | fn record_err( |
1450 | &mut self, |
1451 | token_start: &Self::Checkpoint, |
1452 | err_start: &Self::Checkpoint, |
1453 | err: ErrMode<E>, |
1454 | ) -> Result<(), ErrMode<E>> { |
1455 | if self.is_recoverable { |
1456 | match err { |
1457 | ErrMode::Incomplete(need) => Err(ErrMode::Incomplete(need)), |
1458 | ErrMode::Backtrack(err) | ErrMode::Cut(err) => { |
1459 | self.errors |
1460 | .push(R::from_recoverable_error(token_start, err_start, self, err)); |
1461 | Ok(()) |
1462 | } |
1463 | } |
1464 | } else { |
1465 | Err(err) |
1466 | } |
1467 | } |
1468 | |
1469 | /// Report whether the [`Stream`] can save off errors for recovery |
1470 | #[inline (always)] |
1471 | fn is_recovery_supported() -> bool { |
1472 | true |
1473 | } |
1474 | } |
1475 | |
1476 | #[cfg (feature = "unstable-recover" )] |
1477 | impl<I, E, S> Recover<E> for Stateful<I, S> |
1478 | where |
1479 | I: Recover<E>, |
1480 | I: Stream, |
1481 | S: Clone + crate::lib::std::fmt::Debug, |
1482 | { |
1483 | #[inline (always)] |
1484 | fn record_err( |
1485 | &mut self, |
1486 | _token_start: &Self::Checkpoint, |
1487 | _err_start: &Self::Checkpoint, |
1488 | err: ErrMode<E>, |
1489 | ) -> Result<(), ErrMode<E>> { |
1490 | Err(err) |
1491 | } |
1492 | |
1493 | /// Report whether the [`Stream`] can save off errors for recovery |
1494 | #[inline (always)] |
1495 | fn is_recovery_supported() -> bool { |
1496 | false |
1497 | } |
1498 | } |
1499 | |
1500 | #[cfg (feature = "unstable-recover" )] |
1501 | impl<I, E> Recover<E> for Partial<I> |
1502 | where |
1503 | I: Recover<E>, |
1504 | I: Stream, |
1505 | { |
1506 | #[inline (always)] |
1507 | fn record_err( |
1508 | &mut self, |
1509 | _token_start: &Self::Checkpoint, |
1510 | _err_start: &Self::Checkpoint, |
1511 | err: ErrMode<E>, |
1512 | ) -> Result<(), ErrMode<E>> { |
1513 | Err(err) |
1514 | } |
1515 | |
1516 | /// Report whether the [`Stream`] can save off errors for recovery |
1517 | #[inline (always)] |
1518 | fn is_recovery_supported() -> bool { |
1519 | false |
1520 | } |
1521 | } |
1522 | |
1523 | /// Marks the input as being the complete buffer or a partial buffer for streaming input |
1524 | /// |
1525 | /// See [`Partial`] for marking a presumed complete buffer type as a streaming buffer. |
1526 | pub trait StreamIsPartial: Sized { |
1527 | /// Whether the stream is currently partial or complete |
1528 | type PartialState; |
1529 | |
1530 | /// Mark the stream is complete |
1531 | #[must_use ] |
1532 | fn complete(&mut self) -> Self::PartialState; |
1533 | |
1534 | /// Restore the stream back to its previous state |
1535 | fn restore_partial(&mut self, state: Self::PartialState); |
1536 | |
1537 | /// Report whether the [`Stream`] is can ever be incomplete |
1538 | fn is_partial_supported() -> bool; |
1539 | |
1540 | /// Report whether the [`Stream`] is currently incomplete |
1541 | #[inline (always)] |
1542 | fn is_partial(&self) -> bool { |
1543 | Self::is_partial_supported() |
1544 | } |
1545 | } |
1546 | |
1547 | impl<'a, T> StreamIsPartial for &'a [T] { |
1548 | type PartialState = (); |
1549 | |
1550 | fn complete(&mut self) -> Self::PartialState {} |
1551 | |
1552 | fn restore_partial(&mut self, _state: Self::PartialState) {} |
1553 | |
1554 | #[inline (always)] |
1555 | fn is_partial_supported() -> bool { |
1556 | false |
1557 | } |
1558 | } |
1559 | |
1560 | impl<'a> StreamIsPartial for &'a str { |
1561 | type PartialState = (); |
1562 | |
1563 | fn complete(&mut self) -> Self::PartialState { |
1564 | // Already complete |
1565 | } |
1566 | |
1567 | fn restore_partial(&mut self, _state: Self::PartialState) {} |
1568 | |
1569 | #[inline (always)] |
1570 | fn is_partial_supported() -> bool { |
1571 | false |
1572 | } |
1573 | } |
1574 | |
1575 | impl<'a> StreamIsPartial for &'a Bytes { |
1576 | type PartialState = (); |
1577 | |
1578 | fn complete(&mut self) -> Self::PartialState { |
1579 | // Already complete |
1580 | } |
1581 | |
1582 | fn restore_partial(&mut self, _state: Self::PartialState) {} |
1583 | |
1584 | #[inline (always)] |
1585 | fn is_partial_supported() -> bool { |
1586 | false |
1587 | } |
1588 | } |
1589 | |
1590 | impl<'a> StreamIsPartial for &'a BStr { |
1591 | type PartialState = (); |
1592 | |
1593 | fn complete(&mut self) -> Self::PartialState { |
1594 | // Already complete |
1595 | } |
1596 | |
1597 | fn restore_partial(&mut self, _state: Self::PartialState) {} |
1598 | |
1599 | #[inline (always)] |
1600 | fn is_partial_supported() -> bool { |
1601 | false |
1602 | } |
1603 | } |
1604 | |
1605 | impl<I> StreamIsPartial for (I, usize) |
1606 | where |
1607 | I: StreamIsPartial, |
1608 | { |
1609 | type PartialState = I::PartialState; |
1610 | |
1611 | fn complete(&mut self) -> Self::PartialState { |
1612 | self.0.complete() |
1613 | } |
1614 | |
1615 | fn restore_partial(&mut self, state: Self::PartialState) { |
1616 | self.0.restore_partial(state); |
1617 | } |
1618 | |
1619 | #[inline (always)] |
1620 | fn is_partial_supported() -> bool { |
1621 | I::is_partial_supported() |
1622 | } |
1623 | |
1624 | #[inline (always)] |
1625 | fn is_partial(&self) -> bool { |
1626 | self.0.is_partial() |
1627 | } |
1628 | } |
1629 | |
1630 | impl<I> StreamIsPartial for Located<I> |
1631 | where |
1632 | I: StreamIsPartial, |
1633 | { |
1634 | type PartialState = I::PartialState; |
1635 | |
1636 | fn complete(&mut self) -> Self::PartialState { |
1637 | self.input.complete() |
1638 | } |
1639 | |
1640 | fn restore_partial(&mut self, state: Self::PartialState) { |
1641 | self.input.restore_partial(state); |
1642 | } |
1643 | |
1644 | #[inline (always)] |
1645 | fn is_partial_supported() -> bool { |
1646 | I::is_partial_supported() |
1647 | } |
1648 | |
1649 | #[inline (always)] |
1650 | fn is_partial(&self) -> bool { |
1651 | self.input.is_partial() |
1652 | } |
1653 | } |
1654 | |
1655 | #[cfg (feature = "unstable-recover" )] |
1656 | impl<I, E> StreamIsPartial for Recoverable<I, E> |
1657 | where |
1658 | I: StreamIsPartial, |
1659 | I: Stream, |
1660 | { |
1661 | type PartialState = I::PartialState; |
1662 | |
1663 | fn complete(&mut self) -> Self::PartialState { |
1664 | self.input.complete() |
1665 | } |
1666 | |
1667 | fn restore_partial(&mut self, state: Self::PartialState) { |
1668 | self.input.restore_partial(state); |
1669 | } |
1670 | |
1671 | #[inline (always)] |
1672 | fn is_partial_supported() -> bool { |
1673 | I::is_partial_supported() |
1674 | } |
1675 | |
1676 | #[inline (always)] |
1677 | fn is_partial(&self) -> bool { |
1678 | self.input.is_partial() |
1679 | } |
1680 | } |
1681 | |
1682 | impl<I, S> StreamIsPartial for Stateful<I, S> |
1683 | where |
1684 | I: StreamIsPartial, |
1685 | { |
1686 | type PartialState = I::PartialState; |
1687 | |
1688 | fn complete(&mut self) -> Self::PartialState { |
1689 | self.input.complete() |
1690 | } |
1691 | |
1692 | fn restore_partial(&mut self, state: Self::PartialState) { |
1693 | self.input.restore_partial(state); |
1694 | } |
1695 | |
1696 | #[inline (always)] |
1697 | fn is_partial_supported() -> bool { |
1698 | I::is_partial_supported() |
1699 | } |
1700 | |
1701 | #[inline (always)] |
1702 | fn is_partial(&self) -> bool { |
1703 | self.input.is_partial() |
1704 | } |
1705 | } |
1706 | |
1707 | impl<I> StreamIsPartial for Partial<I> |
1708 | where |
1709 | I: StreamIsPartial, |
1710 | { |
1711 | type PartialState = bool; |
1712 | |
1713 | fn complete(&mut self) -> Self::PartialState { |
1714 | core::mem::replace(&mut self.partial, src:false) |
1715 | } |
1716 | |
1717 | fn restore_partial(&mut self, state: Self::PartialState) { |
1718 | self.partial = state; |
1719 | } |
1720 | |
1721 | #[inline (always)] |
1722 | fn is_partial_supported() -> bool { |
1723 | true |
1724 | } |
1725 | |
1726 | #[inline (always)] |
1727 | fn is_partial(&self) -> bool { |
1728 | self.partial |
1729 | } |
1730 | } |
1731 | |
1732 | /// Useful functions to calculate the offset between slices and show a hexdump of a slice |
1733 | pub trait Offset<Start = Self> { |
1734 | /// Offset between the first byte of `start` and the first byte of `self`a |
1735 | /// |
1736 | /// **Note:** This is an offset, not an index, and may point to the end of input |
1737 | /// (`start.len()`) when `self` is exhausted. |
1738 | fn offset_from(&self, start: &Start) -> usize; |
1739 | } |
1740 | |
1741 | impl<'a, T> Offset for &'a [T] { |
1742 | #[inline ] |
1743 | fn offset_from(&self, start: &Self) -> usize { |
1744 | let fst: *const T = (*start).as_ptr(); |
1745 | let snd: *const T = (*self).as_ptr(); |
1746 | |
1747 | debug_assert!( |
1748 | fst <= snd, |
1749 | "`Offset::offset_from( {snd:?}, {fst:?})` only accepts slices of `self`" |
1750 | ); |
1751 | (snd as usize - fst as usize) / crate::lib::std::mem::size_of::<T>() |
1752 | } |
1753 | } |
1754 | |
1755 | impl<'a, T> Offset<<&'a [T] as Stream>::Checkpoint> for &'a [T] |
1756 | where |
1757 | T: Clone + crate::lib::std::fmt::Debug, |
1758 | { |
1759 | #[inline (always)] |
1760 | fn offset_from(&self, other: &<&'a [T] as Stream>::Checkpoint) -> usize { |
1761 | self.checkpoint().offset_from(start:other) |
1762 | } |
1763 | } |
1764 | |
1765 | impl<'a> Offset for &'a str { |
1766 | #[inline (always)] |
1767 | fn offset_from(&self, start: &Self) -> usize { |
1768 | self.as_bytes().offset_from(&start.as_bytes()) |
1769 | } |
1770 | } |
1771 | |
1772 | impl<'a> Offset<<&'a str as Stream>::Checkpoint> for &'a str { |
1773 | #[inline (always)] |
1774 | fn offset_from(&self, other: &<&'a str as Stream>::Checkpoint) -> usize { |
1775 | self.checkpoint().offset_from(start:other) |
1776 | } |
1777 | } |
1778 | |
1779 | impl<'a> Offset for &'a Bytes { |
1780 | #[inline (always)] |
1781 | fn offset_from(&self, start: &Self) -> usize { |
1782 | self.as_bytes().offset_from(&start.as_bytes()) |
1783 | } |
1784 | } |
1785 | |
1786 | impl<'a> Offset<<&'a Bytes as Stream>::Checkpoint> for &'a Bytes { |
1787 | #[inline (always)] |
1788 | fn offset_from(&self, other: &<&'a Bytes as Stream>::Checkpoint) -> usize { |
1789 | self.checkpoint().offset_from(start:other) |
1790 | } |
1791 | } |
1792 | |
1793 | impl<'a> Offset for &'a BStr { |
1794 | #[inline (always)] |
1795 | fn offset_from(&self, start: &Self) -> usize { |
1796 | self.as_bytes().offset_from(&start.as_bytes()) |
1797 | } |
1798 | } |
1799 | |
1800 | impl<'a> Offset<<&'a BStr as Stream>::Checkpoint> for &'a BStr { |
1801 | #[inline (always)] |
1802 | fn offset_from(&self, other: &<&'a BStr as Stream>::Checkpoint) -> usize { |
1803 | self.checkpoint().offset_from(start:other) |
1804 | } |
1805 | } |
1806 | |
1807 | impl<I> Offset for (I, usize) |
1808 | where |
1809 | I: Offset, |
1810 | { |
1811 | #[inline (always)] |
1812 | fn offset_from(&self, start: &Self) -> usize { |
1813 | self.0.offset_from(&start.0) * 8 + self.1 - start.1 |
1814 | } |
1815 | } |
1816 | |
1817 | impl<I> Offset<<(I, usize) as Stream>::Checkpoint> for (I, usize) |
1818 | where |
1819 | I: Stream<Token = u8> + Clone, |
1820 | { |
1821 | #[inline (always)] |
1822 | fn offset_from(&self, other: &<(I, usize) as Stream>::Checkpoint) -> usize { |
1823 | self.checkpoint().offset_from(start:other) |
1824 | } |
1825 | } |
1826 | |
1827 | impl<I> Offset for Located<I> |
1828 | where |
1829 | I: Stream, |
1830 | { |
1831 | #[inline (always)] |
1832 | fn offset_from(&self, other: &Self) -> usize { |
1833 | self.offset_from(&other.checkpoint()) |
1834 | } |
1835 | } |
1836 | |
1837 | impl<I> Offset<<Located<I> as Stream>::Checkpoint> for Located<I> |
1838 | where |
1839 | I: Stream, |
1840 | { |
1841 | #[inline (always)] |
1842 | fn offset_from(&self, other: &<Located<I> as Stream>::Checkpoint) -> usize { |
1843 | self.checkpoint().offset_from(start:other) |
1844 | } |
1845 | } |
1846 | |
1847 | #[cfg (feature = "unstable-recover" )] |
1848 | impl<I, E> Offset for Recoverable<I, E> |
1849 | where |
1850 | I: Stream, |
1851 | E: crate::lib::std::fmt::Debug, |
1852 | { |
1853 | #[inline (always)] |
1854 | fn offset_from(&self, other: &Self) -> usize { |
1855 | self.offset_from(&other.checkpoint()) |
1856 | } |
1857 | } |
1858 | |
1859 | #[cfg (feature = "unstable-recover" )] |
1860 | impl<I, E> Offset<<Recoverable<I, E> as Stream>::Checkpoint> for Recoverable<I, E> |
1861 | where |
1862 | I: Stream, |
1863 | E: crate::lib::std::fmt::Debug, |
1864 | { |
1865 | #[inline (always)] |
1866 | fn offset_from(&self, other: &<Recoverable<I, E> as Stream>::Checkpoint) -> usize { |
1867 | self.checkpoint().offset_from(other) |
1868 | } |
1869 | } |
1870 | |
1871 | impl<I, S> Offset for Stateful<I, S> |
1872 | where |
1873 | I: Stream, |
1874 | S: Clone + crate::lib::std::fmt::Debug, |
1875 | { |
1876 | #[inline (always)] |
1877 | fn offset_from(&self, start: &Self) -> usize { |
1878 | self.offset_from(&start.checkpoint()) |
1879 | } |
1880 | } |
1881 | |
1882 | impl<I, S> Offset<<Stateful<I, S> as Stream>::Checkpoint> for Stateful<I, S> |
1883 | where |
1884 | I: Stream, |
1885 | S: crate::lib::std::fmt::Debug, |
1886 | { |
1887 | #[inline (always)] |
1888 | fn offset_from(&self, other: &<Stateful<I, S> as Stream>::Checkpoint) -> usize { |
1889 | self.checkpoint().offset_from(start:other) |
1890 | } |
1891 | } |
1892 | |
1893 | impl<I> Offset for Partial<I> |
1894 | where |
1895 | I: Stream, |
1896 | { |
1897 | #[inline (always)] |
1898 | fn offset_from(&self, start: &Self) -> usize { |
1899 | self.offset_from(&start.checkpoint()) |
1900 | } |
1901 | } |
1902 | |
1903 | impl<I> Offset<<Partial<I> as Stream>::Checkpoint> for Partial<I> |
1904 | where |
1905 | I: Stream, |
1906 | { |
1907 | #[inline (always)] |
1908 | fn offset_from(&self, other: &<Partial<I> as Stream>::Checkpoint) -> usize { |
1909 | self.checkpoint().offset_from(start:other) |
1910 | } |
1911 | } |
1912 | |
1913 | impl<I, S> Offset for Checkpoint<I, S> |
1914 | where |
1915 | I: Offset, |
1916 | { |
1917 | #[inline (always)] |
1918 | fn offset_from(&self, start: &Self) -> usize { |
1919 | self.inner.offset_from(&start.inner) |
1920 | } |
1921 | } |
1922 | |
1923 | /// Helper trait for types that can be viewed as a byte slice |
1924 | pub trait AsBytes { |
1925 | /// Casts the input type to a byte slice |
1926 | fn as_bytes(&self) -> &[u8]; |
1927 | } |
1928 | |
1929 | impl<'a> AsBytes for &'a [u8] { |
1930 | #[inline (always)] |
1931 | fn as_bytes(&self) -> &[u8] { |
1932 | self |
1933 | } |
1934 | } |
1935 | |
1936 | impl<'a> AsBytes for &'a Bytes { |
1937 | #[inline (always)] |
1938 | fn as_bytes(&self) -> &[u8] { |
1939 | (*self).as_bytes() |
1940 | } |
1941 | } |
1942 | |
1943 | impl<I> AsBytes for Located<I> |
1944 | where |
1945 | I: AsBytes, |
1946 | { |
1947 | #[inline (always)] |
1948 | fn as_bytes(&self) -> &[u8] { |
1949 | self.input.as_bytes() |
1950 | } |
1951 | } |
1952 | |
1953 | #[cfg (feature = "unstable-recover" )] |
1954 | impl<I, E> AsBytes for Recoverable<I, E> |
1955 | where |
1956 | I: Stream, |
1957 | I: AsBytes, |
1958 | { |
1959 | #[inline (always)] |
1960 | fn as_bytes(&self) -> &[u8] { |
1961 | self.input.as_bytes() |
1962 | } |
1963 | } |
1964 | |
1965 | impl<I, S> AsBytes for Stateful<I, S> |
1966 | where |
1967 | I: AsBytes, |
1968 | { |
1969 | #[inline (always)] |
1970 | fn as_bytes(&self) -> &[u8] { |
1971 | self.input.as_bytes() |
1972 | } |
1973 | } |
1974 | |
1975 | impl<I> AsBytes for Partial<I> |
1976 | where |
1977 | I: AsBytes, |
1978 | { |
1979 | #[inline (always)] |
1980 | fn as_bytes(&self) -> &[u8] { |
1981 | self.input.as_bytes() |
1982 | } |
1983 | } |
1984 | |
1985 | /// Helper trait for types that can be viewed as a byte slice |
1986 | pub trait AsBStr { |
1987 | /// Casts the input type to a byte slice |
1988 | fn as_bstr(&self) -> &[u8]; |
1989 | } |
1990 | |
1991 | impl<'a> AsBStr for &'a [u8] { |
1992 | #[inline (always)] |
1993 | fn as_bstr(&self) -> &[u8] { |
1994 | self |
1995 | } |
1996 | } |
1997 | |
1998 | impl<'a> AsBStr for &'a BStr { |
1999 | #[inline (always)] |
2000 | fn as_bstr(&self) -> &[u8] { |
2001 | (*self).as_bytes() |
2002 | } |
2003 | } |
2004 | |
2005 | impl<'a> AsBStr for &'a str { |
2006 | #[inline (always)] |
2007 | fn as_bstr(&self) -> &[u8] { |
2008 | (*self).as_bytes() |
2009 | } |
2010 | } |
2011 | |
2012 | impl<I> AsBStr for Located<I> |
2013 | where |
2014 | I: AsBStr, |
2015 | { |
2016 | #[inline (always)] |
2017 | fn as_bstr(&self) -> &[u8] { |
2018 | self.input.as_bstr() |
2019 | } |
2020 | } |
2021 | |
2022 | #[cfg (feature = "unstable-recover" )] |
2023 | impl<I, E> AsBStr for Recoverable<I, E> |
2024 | where |
2025 | I: Stream, |
2026 | I: AsBStr, |
2027 | { |
2028 | #[inline (always)] |
2029 | fn as_bstr(&self) -> &[u8] { |
2030 | self.input.as_bstr() |
2031 | } |
2032 | } |
2033 | |
2034 | impl<I, S> AsBStr for Stateful<I, S> |
2035 | where |
2036 | I: AsBStr, |
2037 | { |
2038 | #[inline (always)] |
2039 | fn as_bstr(&self) -> &[u8] { |
2040 | self.input.as_bstr() |
2041 | } |
2042 | } |
2043 | |
2044 | impl<I> AsBStr for Partial<I> |
2045 | where |
2046 | I: AsBStr, |
2047 | { |
2048 | #[inline (always)] |
2049 | fn as_bstr(&self) -> &[u8] { |
2050 | self.input.as_bstr() |
2051 | } |
2052 | } |
2053 | |
2054 | /// Result of [`Compare::compare`] |
2055 | #[derive (Debug, Eq, PartialEq)] |
2056 | pub enum CompareResult { |
2057 | /// Comparison was successful |
2058 | /// |
2059 | /// `usize` is the end of the successful match within the buffer. |
2060 | /// This is most relevant for caseless UTF-8 where `Compare::compare`'s parameter might be a different |
2061 | /// length than the match within the buffer. |
2062 | Ok(usize), |
2063 | /// We need more data to be sure |
2064 | Incomplete, |
2065 | /// Comparison failed |
2066 | Error, |
2067 | } |
2068 | |
2069 | /// Abstracts comparison operations |
2070 | pub trait Compare<T> { |
2071 | /// Compares self to another value for equality |
2072 | fn compare(&self, t: T) -> CompareResult; |
2073 | } |
2074 | |
2075 | impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { |
2076 | #[inline ] |
2077 | fn compare(&self, t: &'b [u8]) -> CompareResult { |
2078 | if t.iter().zip(*self).any(|(a: &u8, b: &u8)| a != b) { |
2079 | CompareResult::Error |
2080 | } else if self.len() < t.slice_len() { |
2081 | CompareResult::Incomplete |
2082 | } else { |
2083 | CompareResult::Ok(t.slice_len()) |
2084 | } |
2085 | } |
2086 | } |
2087 | |
2088 | impl<'a, 'b> Compare<AsciiCaseless<&'b [u8]>> for &'a [u8] { |
2089 | #[inline ] |
2090 | fn compare(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult { |
2091 | if timpl Iterator .0 |
2092 | .iter() |
2093 | .zip(*self) |
2094 | .any(|(a: &u8, b: &u8)| !a.eq_ignore_ascii_case(b)) |
2095 | { |
2096 | CompareResult::Error |
2097 | } else if self.len() < t.slice_len() { |
2098 | CompareResult::Incomplete |
2099 | } else { |
2100 | CompareResult::Ok(t.slice_len()) |
2101 | } |
2102 | } |
2103 | } |
2104 | |
2105 | impl<'a, const LEN: usize> Compare<[u8; LEN]> for &'a [u8] { |
2106 | #[inline (always)] |
2107 | fn compare(&self, t: [u8; LEN]) -> CompareResult { |
2108 | self.compare(&t[..]) |
2109 | } |
2110 | } |
2111 | |
2112 | impl<'a, const LEN: usize> Compare<AsciiCaseless<[u8; LEN]>> for &'a [u8] { |
2113 | #[inline (always)] |
2114 | fn compare(&self, t: AsciiCaseless<[u8; LEN]>) -> CompareResult { |
2115 | self.compare(AsciiCaseless(&t.0[..])) |
2116 | } |
2117 | } |
2118 | |
2119 | impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] { |
2120 | #[inline (always)] |
2121 | fn compare(&self, t: &'b [u8; LEN]) -> CompareResult { |
2122 | self.compare(&t[..]) |
2123 | } |
2124 | } |
2125 | |
2126 | impl<'a, 'b, const LEN: usize> Compare<AsciiCaseless<&'b [u8; LEN]>> for &'a [u8] { |
2127 | #[inline (always)] |
2128 | fn compare(&self, t: AsciiCaseless<&'b [u8; LEN]>) -> CompareResult { |
2129 | self.compare(AsciiCaseless(&t.0[..])) |
2130 | } |
2131 | } |
2132 | |
2133 | impl<'a, 'b> Compare<&'b str> for &'a [u8] { |
2134 | #[inline (always)] |
2135 | fn compare(&self, t: &'b str) -> CompareResult { |
2136 | self.compare(t.as_bytes()) |
2137 | } |
2138 | } |
2139 | |
2140 | impl<'a, 'b> Compare<AsciiCaseless<&'b str>> for &'a [u8] { |
2141 | #[inline (always)] |
2142 | fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult { |
2143 | self.compare(AsciiCaseless(t.0.as_bytes())) |
2144 | } |
2145 | } |
2146 | |
2147 | impl<'a> Compare<u8> for &'a [u8] { |
2148 | #[inline ] |
2149 | fn compare(&self, t: u8) -> CompareResult { |
2150 | match self.first().copied() { |
2151 | Some(c: u8) if t == c => CompareResult::Ok(t.slice_len()), |
2152 | Some(_) => CompareResult::Error, |
2153 | None => CompareResult::Incomplete, |
2154 | } |
2155 | } |
2156 | } |
2157 | |
2158 | impl<'a> Compare<AsciiCaseless<u8>> for &'a [u8] { |
2159 | #[inline ] |
2160 | fn compare(&self, t: AsciiCaseless<u8>) -> CompareResult { |
2161 | match self.first() { |
2162 | Some(c: &u8) if t.0.eq_ignore_ascii_case(c) => CompareResult::Ok(t.slice_len()), |
2163 | Some(_) => CompareResult::Error, |
2164 | None => CompareResult::Incomplete, |
2165 | } |
2166 | } |
2167 | } |
2168 | |
2169 | impl<'a> Compare<char> for &'a [u8] { |
2170 | #[inline (always)] |
2171 | fn compare(&self, t: char) -> CompareResult { |
2172 | self.compare(t.encode_utf8(&mut [0; 4]).as_bytes()) |
2173 | } |
2174 | } |
2175 | |
2176 | impl<'a> Compare<AsciiCaseless<char>> for &'a [u8] { |
2177 | #[inline (always)] |
2178 | fn compare(&self, t: AsciiCaseless<char>) -> CompareResult { |
2179 | self.compare(AsciiCaseless(t.0.encode_utf8(&mut [0; 4]).as_bytes())) |
2180 | } |
2181 | } |
2182 | |
2183 | impl<'a, 'b> Compare<&'b str> for &'a str { |
2184 | #[inline (always)] |
2185 | fn compare(&self, t: &'b str) -> CompareResult { |
2186 | self.as_bytes().compare(t.as_bytes()) |
2187 | } |
2188 | } |
2189 | |
2190 | impl<'a, 'b> Compare<AsciiCaseless<&'b str>> for &'a str { |
2191 | #[inline (always)] |
2192 | fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult { |
2193 | self.as_bytes().compare(t.as_bytes()) |
2194 | } |
2195 | } |
2196 | |
2197 | impl<'a> Compare<char> for &'a str { |
2198 | #[inline (always)] |
2199 | fn compare(&self, t: char) -> CompareResult { |
2200 | self.as_bytes().compare(t) |
2201 | } |
2202 | } |
2203 | |
2204 | impl<'a> Compare<AsciiCaseless<char>> for &'a str { |
2205 | #[inline (always)] |
2206 | fn compare(&self, t: AsciiCaseless<char>) -> CompareResult { |
2207 | self.as_bytes().compare(t) |
2208 | } |
2209 | } |
2210 | |
2211 | impl<'a, T> Compare<T> for &'a Bytes |
2212 | where |
2213 | &'a [u8]: Compare<T>, |
2214 | { |
2215 | #[inline (always)] |
2216 | fn compare(&self, t: T) -> CompareResult { |
2217 | let bytes: &[u8] = (*self).as_bytes(); |
2218 | bytes.compare(t) |
2219 | } |
2220 | } |
2221 | |
2222 | impl<'a, T> Compare<T> for &'a BStr |
2223 | where |
2224 | &'a [u8]: Compare<T>, |
2225 | { |
2226 | #[inline (always)] |
2227 | fn compare(&self, t: T) -> CompareResult { |
2228 | let bytes: &[u8] = (*self).as_bytes(); |
2229 | bytes.compare(t) |
2230 | } |
2231 | } |
2232 | |
2233 | impl<I, U> Compare<U> for Located<I> |
2234 | where |
2235 | I: Compare<U>, |
2236 | { |
2237 | #[inline (always)] |
2238 | fn compare(&self, other: U) -> CompareResult { |
2239 | self.input.compare(other) |
2240 | } |
2241 | } |
2242 | |
2243 | #[cfg (feature = "unstable-recover" )] |
2244 | impl<I, E, U> Compare<U> for Recoverable<I, E> |
2245 | where |
2246 | I: Stream, |
2247 | I: Compare<U>, |
2248 | { |
2249 | #[inline (always)] |
2250 | fn compare(&self, other: U) -> CompareResult { |
2251 | self.input.compare(other) |
2252 | } |
2253 | } |
2254 | |
2255 | impl<I, S, U> Compare<U> for Stateful<I, S> |
2256 | where |
2257 | I: Compare<U>, |
2258 | { |
2259 | #[inline (always)] |
2260 | fn compare(&self, other: U) -> CompareResult { |
2261 | self.input.compare(other) |
2262 | } |
2263 | } |
2264 | |
2265 | impl<I, T> Compare<T> for Partial<I> |
2266 | where |
2267 | I: Compare<T>, |
2268 | { |
2269 | #[inline (always)] |
2270 | fn compare(&self, t: T) -> CompareResult { |
2271 | self.input.compare(t) |
2272 | } |
2273 | } |
2274 | |
2275 | /// Look for a slice in self |
2276 | pub trait FindSlice<T> { |
2277 | /// Returns the offset of the slice if it is found |
2278 | fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>>; |
2279 | } |
2280 | |
2281 | impl<'i, 's> FindSlice<&'s [u8]> for &'i [u8] { |
2282 | #[inline (always)] |
2283 | fn find_slice(&self, substr: &'s [u8]) -> Option<crate::lib::std::ops::Range<usize>> { |
2284 | memmem(self, literal:substr) |
2285 | } |
2286 | } |
2287 | |
2288 | impl<'i, 's> FindSlice<(&'s [u8],)> for &'i [u8] { |
2289 | #[inline (always)] |
2290 | fn find_slice(&self, substr: (&'s [u8],)) -> Option<crate::lib::std::ops::Range<usize>> { |
2291 | memmem(self, literal:substr.0) |
2292 | } |
2293 | } |
2294 | |
2295 | impl<'i, 's> FindSlice<(&'s [u8], &'s [u8])> for &'i [u8] { |
2296 | #[inline (always)] |
2297 | fn find_slice( |
2298 | &self, |
2299 | substr: (&'s [u8], &'s [u8]), |
2300 | ) -> Option<crate::lib::std::ops::Range<usize>> { |
2301 | memmem2(self, literal:substr) |
2302 | } |
2303 | } |
2304 | |
2305 | impl<'i, 's> FindSlice<(&'s [u8], &'s [u8], &'s [u8])> for &'i [u8] { |
2306 | #[inline (always)] |
2307 | fn find_slice( |
2308 | &self, |
2309 | substr: (&'s [u8], &'s [u8], &'s [u8]), |
2310 | ) -> Option<crate::lib::std::ops::Range<usize>> { |
2311 | memmem3(self, literal:substr) |
2312 | } |
2313 | } |
2314 | |
2315 | impl<'i> FindSlice<char> for &'i [u8] { |
2316 | #[inline (always)] |
2317 | fn find_slice(&self, substr: char) -> Option<crate::lib::std::ops::Range<usize>> { |
2318 | let mut b: [u8; 4] = [0; 4]; |
2319 | let substr: &mut str = substr.encode_utf8(&mut b); |
2320 | self.find_slice(&*substr) |
2321 | } |
2322 | } |
2323 | |
2324 | impl<'i> FindSlice<(char,)> for &'i [u8] { |
2325 | #[inline (always)] |
2326 | fn find_slice(&self, substr: (char,)) -> Option<crate::lib::std::ops::Range<usize>> { |
2327 | let mut b: [u8; 4] = [0; 4]; |
2328 | let substr0: &mut str = substr.0.encode_utf8(&mut b); |
2329 | self.find_slice((&*substr0,)) |
2330 | } |
2331 | } |
2332 | |
2333 | impl<'i> FindSlice<(char, char)> for &'i [u8] { |
2334 | #[inline (always)] |
2335 | fn find_slice(&self, substr: (char, char)) -> Option<crate::lib::std::ops::Range<usize>> { |
2336 | let mut b: [u8; 4] = [0; 4]; |
2337 | let substr0: &mut str = substr.0.encode_utf8(&mut b); |
2338 | let mut b: [u8; 4] = [0; 4]; |
2339 | let substr1: &mut str = substr.1.encode_utf8(&mut b); |
2340 | self.find_slice((&*substr0, &*substr1)) |
2341 | } |
2342 | } |
2343 | |
2344 | impl<'i> FindSlice<(char, char, char)> for &'i [u8] { |
2345 | #[inline (always)] |
2346 | fn find_slice(&self, substr: (char, char, char)) -> Option<crate::lib::std::ops::Range<usize>> { |
2347 | let mut b: [u8; 4] = [0; 4]; |
2348 | let substr0: &mut str = substr.0.encode_utf8(&mut b); |
2349 | let mut b: [u8; 4] = [0; 4]; |
2350 | let substr1: &mut str = substr.1.encode_utf8(&mut b); |
2351 | let mut b: [u8; 4] = [0; 4]; |
2352 | let substr2: &mut str = substr.2.encode_utf8(&mut b); |
2353 | self.find_slice((&*substr0, &*substr1, &*substr2)) |
2354 | } |
2355 | } |
2356 | |
2357 | impl<'i> FindSlice<u8> for &'i [u8] { |
2358 | #[inline (always)] |
2359 | fn find_slice(&self, substr: u8) -> Option<crate::lib::std::ops::Range<usize>> { |
2360 | memchr(token:substr, self).map(|i: usize| i..i + 1) |
2361 | } |
2362 | } |
2363 | |
2364 | impl<'i> FindSlice<(u8,)> for &'i [u8] { |
2365 | #[inline (always)] |
2366 | fn find_slice(&self, substr: (u8,)) -> Option<crate::lib::std::ops::Range<usize>> { |
2367 | memchr(token:substr.0, self).map(|i: usize| i..i + 1) |
2368 | } |
2369 | } |
2370 | |
2371 | impl<'i> FindSlice<(u8, u8)> for &'i [u8] { |
2372 | #[inline (always)] |
2373 | fn find_slice(&self, substr: (u8, u8)) -> Option<crate::lib::std::ops::Range<usize>> { |
2374 | memchr2(token:substr, self).map(|i: usize| i..i + 1) |
2375 | } |
2376 | } |
2377 | |
2378 | impl<'i> FindSlice<(u8, u8, u8)> for &'i [u8] { |
2379 | #[inline (always)] |
2380 | fn find_slice(&self, substr: (u8, u8, u8)) -> Option<crate::lib::std::ops::Range<usize>> { |
2381 | memchr3(token:substr, self).map(|i: usize| i..i + 1) |
2382 | } |
2383 | } |
2384 | |
2385 | impl<'i, 's> FindSlice<&'s str> for &'i [u8] { |
2386 | #[inline (always)] |
2387 | fn find_slice(&self, substr: &'s str) -> Option<crate::lib::std::ops::Range<usize>> { |
2388 | self.find_slice(substr:substr.as_bytes()) |
2389 | } |
2390 | } |
2391 | |
2392 | impl<'i, 's> FindSlice<(&'s str,)> for &'i [u8] { |
2393 | #[inline (always)] |
2394 | fn find_slice(&self, substr: (&'s str,)) -> Option<crate::lib::std::ops::Range<usize>> { |
2395 | memmem(self, literal:substr.0.as_bytes()) |
2396 | } |
2397 | } |
2398 | |
2399 | impl<'i, 's> FindSlice<(&'s str, &'s str)> for &'i [u8] { |
2400 | #[inline (always)] |
2401 | fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<crate::lib::std::ops::Range<usize>> { |
2402 | memmem2(self, (substr.0.as_bytes(), substr.1.as_bytes())) |
2403 | } |
2404 | } |
2405 | |
2406 | impl<'i, 's> FindSlice<(&'s str, &'s str, &'s str)> for &'i [u8] { |
2407 | #[inline (always)] |
2408 | fn find_slice( |
2409 | &self, |
2410 | substr: (&'s str, &'s str, &'s str), |
2411 | ) -> Option<crate::lib::std::ops::Range<usize>> { |
2412 | memmem3( |
2413 | self, |
2414 | ( |
2415 | substr.0.as_bytes(), |
2416 | substr.1.as_bytes(), |
2417 | substr.2.as_bytes(), |
2418 | ), |
2419 | ) |
2420 | } |
2421 | } |
2422 | |
2423 | impl<'i, 's> FindSlice<&'s str> for &'i str { |
2424 | #[inline (always)] |
2425 | fn find_slice(&self, substr: &'s str) -> Option<crate::lib::std::ops::Range<usize>> { |
2426 | self.as_bytes().find_slice(substr) |
2427 | } |
2428 | } |
2429 | |
2430 | impl<'i, 's> FindSlice<(&'s str,)> for &'i str { |
2431 | #[inline (always)] |
2432 | fn find_slice(&self, substr: (&'s str,)) -> Option<crate::lib::std::ops::Range<usize>> { |
2433 | self.as_bytes().find_slice(substr) |
2434 | } |
2435 | } |
2436 | |
2437 | impl<'i, 's> FindSlice<(&'s str, &'s str)> for &'i str { |
2438 | #[inline (always)] |
2439 | fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<crate::lib::std::ops::Range<usize>> { |
2440 | self.as_bytes().find_slice(substr) |
2441 | } |
2442 | } |
2443 | |
2444 | impl<'i, 's> FindSlice<(&'s str, &'s str, &'s str)> for &'i str { |
2445 | #[inline (always)] |
2446 | fn find_slice( |
2447 | &self, |
2448 | substr: (&'s str, &'s str, &'s str), |
2449 | ) -> Option<crate::lib::std::ops::Range<usize>> { |
2450 | self.as_bytes().find_slice(substr) |
2451 | } |
2452 | } |
2453 | |
2454 | impl<'i> FindSlice<char> for &'i str { |
2455 | #[inline (always)] |
2456 | fn find_slice(&self, substr: char) -> Option<crate::lib::std::ops::Range<usize>> { |
2457 | self.as_bytes().find_slice(substr) |
2458 | } |
2459 | } |
2460 | |
2461 | impl<'i> FindSlice<(char,)> for &'i str { |
2462 | #[inline (always)] |
2463 | fn find_slice(&self, substr: (char,)) -> Option<crate::lib::std::ops::Range<usize>> { |
2464 | self.as_bytes().find_slice(substr) |
2465 | } |
2466 | } |
2467 | |
2468 | impl<'i> FindSlice<(char, char)> for &'i str { |
2469 | #[inline (always)] |
2470 | fn find_slice(&self, substr: (char, char)) -> Option<crate::lib::std::ops::Range<usize>> { |
2471 | self.as_bytes().find_slice(substr) |
2472 | } |
2473 | } |
2474 | |
2475 | impl<'i> FindSlice<(char, char, char)> for &'i str { |
2476 | #[inline (always)] |
2477 | fn find_slice(&self, substr: (char, char, char)) -> Option<crate::lib::std::ops::Range<usize>> { |
2478 | self.as_bytes().find_slice(substr) |
2479 | } |
2480 | } |
2481 | |
2482 | impl<'i, S> FindSlice<S> for &'i Bytes |
2483 | where |
2484 | &'i [u8]: FindSlice<S>, |
2485 | { |
2486 | #[inline (always)] |
2487 | fn find_slice(&self, substr: S) -> Option<crate::lib::std::ops::Range<usize>> { |
2488 | let bytes: &[u8] = (*self).as_bytes(); |
2489 | let offset: Option> = bytes.find_slice(substr); |
2490 | offset |
2491 | } |
2492 | } |
2493 | |
2494 | impl<'i, S> FindSlice<S> for &'i BStr |
2495 | where |
2496 | &'i [u8]: FindSlice<S>, |
2497 | { |
2498 | #[inline (always)] |
2499 | fn find_slice(&self, substr: S) -> Option<crate::lib::std::ops::Range<usize>> { |
2500 | let bytes: &[u8] = (*self).as_bytes(); |
2501 | let offset: Option> = bytes.find_slice(substr); |
2502 | offset |
2503 | } |
2504 | } |
2505 | |
2506 | impl<I, T> FindSlice<T> for Located<I> |
2507 | where |
2508 | I: FindSlice<T>, |
2509 | { |
2510 | #[inline (always)] |
2511 | fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> { |
2512 | self.input.find_slice(substr) |
2513 | } |
2514 | } |
2515 | |
2516 | #[cfg (feature = "unstable-recover" )] |
2517 | impl<I, E, T> FindSlice<T> for Recoverable<I, E> |
2518 | where |
2519 | I: Stream, |
2520 | I: FindSlice<T>, |
2521 | { |
2522 | #[inline (always)] |
2523 | fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> { |
2524 | self.input.find_slice(substr) |
2525 | } |
2526 | } |
2527 | |
2528 | impl<I, S, T> FindSlice<T> for Stateful<I, S> |
2529 | where |
2530 | I: FindSlice<T>, |
2531 | { |
2532 | #[inline (always)] |
2533 | fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> { |
2534 | self.input.find_slice(substr) |
2535 | } |
2536 | } |
2537 | |
2538 | impl<I, T> FindSlice<T> for Partial<I> |
2539 | where |
2540 | I: FindSlice<T>, |
2541 | { |
2542 | #[inline (always)] |
2543 | fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> { |
2544 | self.input.find_slice(substr) |
2545 | } |
2546 | } |
2547 | |
2548 | /// Used to integrate `str`'s `parse()` method |
2549 | pub trait ParseSlice<R> { |
2550 | /// Succeeds if `parse()` succeeded |
2551 | /// |
2552 | /// The byte slice implementation will first convert it to a `&str`, then apply the `parse()` |
2553 | /// function |
2554 | fn parse_slice(&self) -> Option<R>; |
2555 | } |
2556 | |
2557 | impl<'a, R: FromStr> ParseSlice<R> for &'a [u8] { |
2558 | #[inline (always)] |
2559 | fn parse_slice(&self) -> Option<R> { |
2560 | from_utf8(self).ok().and_then(|s: &str| s.parse().ok()) |
2561 | } |
2562 | } |
2563 | |
2564 | impl<'a, R: FromStr> ParseSlice<R> for &'a str { |
2565 | #[inline (always)] |
2566 | fn parse_slice(&self) -> Option<R> { |
2567 | self.parse().ok() |
2568 | } |
2569 | } |
2570 | |
2571 | /// Convert a `Stream` into an appropriate `Output` type |
2572 | pub trait UpdateSlice: Stream { |
2573 | /// Convert an `Output` type to be used as `Stream` |
2574 | fn update_slice(self, inner: Self::Slice) -> Self; |
2575 | } |
2576 | |
2577 | impl<'a, T> UpdateSlice for &'a [T] |
2578 | where |
2579 | T: Clone + crate::lib::std::fmt::Debug, |
2580 | { |
2581 | #[inline (always)] |
2582 | fn update_slice(self, inner: Self::Slice) -> Self { |
2583 | inner |
2584 | } |
2585 | } |
2586 | |
2587 | impl<'a> UpdateSlice for &'a str { |
2588 | #[inline (always)] |
2589 | fn update_slice(self, inner: Self::Slice) -> Self { |
2590 | inner |
2591 | } |
2592 | } |
2593 | |
2594 | impl<'a> UpdateSlice for &'a Bytes { |
2595 | #[inline (always)] |
2596 | fn update_slice(self, inner: Self::Slice) -> Self { |
2597 | Bytes::new(bytes:inner) |
2598 | } |
2599 | } |
2600 | |
2601 | impl<'a> UpdateSlice for &'a BStr { |
2602 | #[inline (always)] |
2603 | fn update_slice(self, inner: Self::Slice) -> Self { |
2604 | BStr::new(bytes:inner) |
2605 | } |
2606 | } |
2607 | |
2608 | impl<I> UpdateSlice for Located<I> |
2609 | where |
2610 | I: UpdateSlice, |
2611 | { |
2612 | #[inline (always)] |
2613 | fn update_slice(mut self, inner: Self::Slice) -> Self { |
2614 | self.input = I::update_slice(self.input, inner); |
2615 | self |
2616 | } |
2617 | } |
2618 | |
2619 | #[cfg (feature = "unstable-recover" )] |
2620 | impl<I, E> UpdateSlice for Recoverable<I, E> |
2621 | where |
2622 | I: Stream, |
2623 | I: UpdateSlice, |
2624 | E: crate::lib::std::fmt::Debug, |
2625 | { |
2626 | #[inline (always)] |
2627 | fn update_slice(mut self, inner: Self::Slice) -> Self { |
2628 | self.input = I::update_slice(self.input, inner); |
2629 | self |
2630 | } |
2631 | } |
2632 | |
2633 | impl<I, S> UpdateSlice for Stateful<I, S> |
2634 | where |
2635 | I: UpdateSlice, |
2636 | S: Clone + crate::lib::std::fmt::Debug, |
2637 | { |
2638 | #[inline (always)] |
2639 | fn update_slice(mut self, inner: Self::Slice) -> Self { |
2640 | self.input = I::update_slice(self.input, inner); |
2641 | self |
2642 | } |
2643 | } |
2644 | |
2645 | impl<I> UpdateSlice for Partial<I> |
2646 | where |
2647 | I: UpdateSlice, |
2648 | { |
2649 | #[inline (always)] |
2650 | fn update_slice(self, inner: Self::Slice) -> Self { |
2651 | Partial { |
2652 | input: I::update_slice(self.input, inner), |
2653 | partial: self.partial, |
2654 | } |
2655 | } |
2656 | } |
2657 | |
2658 | /// Ensure checkpoint details are kept private |
2659 | pub struct Checkpoint<T, S> { |
2660 | inner: T, |
2661 | stream: core::marker::PhantomData<S>, |
2662 | } |
2663 | |
2664 | impl<T, S> Checkpoint<T, S> { |
2665 | fn new(inner: T) -> Self { |
2666 | Self { |
2667 | inner, |
2668 | stream: Default::default(), |
2669 | } |
2670 | } |
2671 | } |
2672 | |
2673 | impl<T: Copy, S> Copy for Checkpoint<T, S> {} |
2674 | |
2675 | impl<T: Clone, S> Clone for Checkpoint<T, S> { |
2676 | fn clone(&self) -> Self { |
2677 | Self { |
2678 | inner: self.inner.clone(), |
2679 | stream: Default::default(), |
2680 | } |
2681 | } |
2682 | } |
2683 | |
2684 | impl<T: crate::lib::std::fmt::Debug, S> crate::lib::std::fmt::Debug for Checkpoint<T, S> { |
2685 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
2686 | self.inner.fmt(f) |
2687 | } |
2688 | } |
2689 | |
2690 | /// A range bounded inclusively for counting parses performed |
2691 | /// |
2692 | /// This is flexible in what can be converted to a [Range]: |
2693 | /// ```rust |
2694 | /// # use winnow::prelude::*; |
2695 | /// # use winnow::token::any; |
2696 | /// # use winnow::combinator::repeat; |
2697 | /// # fn inner(input: &mut &str) -> PResult<char> { |
2698 | /// # any.parse_next(input) |
2699 | /// # } |
2700 | /// # let mut input = "0123456789012345678901234567890123456789" ; |
2701 | /// # let input = &mut input; |
2702 | /// let parser: Vec<_> = repeat(5, inner).parse_next(input).unwrap(); |
2703 | /// # let mut input = "0123456789012345678901234567890123456789" ; |
2704 | /// # let input = &mut input; |
2705 | /// let parser: Vec<_> = repeat(.., inner).parse_next(input).unwrap(); |
2706 | /// # let mut input = "0123456789012345678901234567890123456789" ; |
2707 | /// # let input = &mut input; |
2708 | /// let parser: Vec<_> = repeat(1.., inner).parse_next(input).unwrap(); |
2709 | /// # let mut input = "0123456789012345678901234567890123456789" ; |
2710 | /// # let input = &mut input; |
2711 | /// let parser: Vec<_> = repeat(5..8, inner).parse_next(input).unwrap(); |
2712 | /// # let mut input = "0123456789012345678901234567890123456789" ; |
2713 | /// # let input = &mut input; |
2714 | /// let parser: Vec<_> = repeat(5..=8, inner).parse_next(input).unwrap(); |
2715 | /// ``` |
2716 | #[derive (PartialEq, Eq)] |
2717 | pub struct Range { |
2718 | pub(crate) start_inclusive: usize, |
2719 | pub(crate) end_inclusive: Option<usize>, |
2720 | } |
2721 | |
2722 | impl Range { |
2723 | #[inline (always)] |
2724 | fn raw(start_inclusive: usize, end_inclusive: Option<usize>) -> Self { |
2725 | Self { |
2726 | start_inclusive, |
2727 | end_inclusive, |
2728 | } |
2729 | } |
2730 | } |
2731 | |
2732 | impl crate::lib::std::ops::RangeBounds<usize> for Range { |
2733 | #[inline (always)] |
2734 | fn start_bound(&self) -> crate::lib::std::ops::Bound<&usize> { |
2735 | crate::lib::std::ops::Bound::Included(&self.start_inclusive) |
2736 | } |
2737 | |
2738 | #[inline (always)] |
2739 | fn end_bound(&self) -> crate::lib::std::ops::Bound<&usize> { |
2740 | if let Some(end_inclusive: &usize) = &self.end_inclusive { |
2741 | crate::lib::std::ops::Bound::Included(end_inclusive) |
2742 | } else { |
2743 | crate::lib::std::ops::Bound::Unbounded |
2744 | } |
2745 | } |
2746 | } |
2747 | |
2748 | impl From<usize> for Range { |
2749 | #[inline (always)] |
2750 | fn from(fixed: usize) -> Self { |
2751 | (fixed..=fixed).into() |
2752 | } |
2753 | } |
2754 | |
2755 | impl From<crate::lib::std::ops::Range<usize>> for Range { |
2756 | #[inline (always)] |
2757 | fn from(range: crate::lib::std::ops::Range<usize>) -> Self { |
2758 | let start_inclusive: usize = range.start; |
2759 | let end_inclusive: Option = Some(range.end.saturating_sub(1)); |
2760 | Self::raw(start_inclusive, end_inclusive) |
2761 | } |
2762 | } |
2763 | |
2764 | impl From<crate::lib::std::ops::RangeFull> for Range { |
2765 | #[inline (always)] |
2766 | fn from(_: crate::lib::std::ops::RangeFull) -> Self { |
2767 | let start_inclusive: usize = 0; |
2768 | let end_inclusive: Option = None; |
2769 | Self::raw(start_inclusive, end_inclusive) |
2770 | } |
2771 | } |
2772 | |
2773 | impl From<crate::lib::std::ops::RangeFrom<usize>> for Range { |
2774 | #[inline (always)] |
2775 | fn from(range: crate::lib::std::ops::RangeFrom<usize>) -> Self { |
2776 | let start_inclusive: usize = range.start; |
2777 | let end_inclusive: Option = None; |
2778 | Self::raw(start_inclusive, end_inclusive) |
2779 | } |
2780 | } |
2781 | |
2782 | impl From<crate::lib::std::ops::RangeTo<usize>> for Range { |
2783 | #[inline (always)] |
2784 | fn from(range: crate::lib::std::ops::RangeTo<usize>) -> Self { |
2785 | let start_inclusive: usize = 0; |
2786 | let end_inclusive: Option = Some(range.end.saturating_sub(1)); |
2787 | Self::raw(start_inclusive, end_inclusive) |
2788 | } |
2789 | } |
2790 | |
2791 | impl From<crate::lib::std::ops::RangeInclusive<usize>> for Range { |
2792 | #[inline (always)] |
2793 | fn from(range: crate::lib::std::ops::RangeInclusive<usize>) -> Self { |
2794 | let start_inclusive: usize = *range.start(); |
2795 | let end_inclusive: Option = Some(*range.end()); |
2796 | Self::raw(start_inclusive, end_inclusive) |
2797 | } |
2798 | } |
2799 | |
2800 | impl From<crate::lib::std::ops::RangeToInclusive<usize>> for Range { |
2801 | #[inline (always)] |
2802 | fn from(range: crate::lib::std::ops::RangeToInclusive<usize>) -> Self { |
2803 | let start_inclusive: usize = 0; |
2804 | let end_inclusive: Option = Some(range.end); |
2805 | Self::raw(start_inclusive, end_inclusive) |
2806 | } |
2807 | } |
2808 | |
2809 | impl crate::lib::std::fmt::Display for Range { |
2810 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
2811 | self.start_inclusive.fmt(f)?; |
2812 | match self.end_inclusive { |
2813 | Some(e: usize) if e == self.start_inclusive => {} |
2814 | Some(e: usize) => { |
2815 | "..=" .fmt(f)?; |
2816 | e.fmt(f)?; |
2817 | } |
2818 | None => { |
2819 | ".." .fmt(f)?; |
2820 | } |
2821 | } |
2822 | Ok(()) |
2823 | } |
2824 | } |
2825 | |
2826 | impl crate::lib::std::fmt::Debug for Range { |
2827 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
2828 | write!(f, " {self}" ) |
2829 | } |
2830 | } |
2831 | |
2832 | /// Abstracts something which can extend an `Extend`. |
2833 | /// Used to build modified input slices in `escaped_transform` |
2834 | pub trait Accumulate<T>: Sized { |
2835 | /// Create a new `Extend` of the correct type |
2836 | fn initial(capacity: Option<usize>) -> Self; |
2837 | /// Accumulate the input into an accumulator |
2838 | fn accumulate(&mut self, acc: T); |
2839 | } |
2840 | |
2841 | impl<T> Accumulate<T> for () { |
2842 | #[inline (always)] |
2843 | fn initial(_capacity: Option<usize>) -> Self {} |
2844 | #[inline (always)] |
2845 | fn accumulate(&mut self, _acc: T) {} |
2846 | } |
2847 | |
2848 | impl<T> Accumulate<T> for usize { |
2849 | #[inline (always)] |
2850 | fn initial(_capacity: Option<usize>) -> Self { |
2851 | 0 |
2852 | } |
2853 | #[inline (always)] |
2854 | fn accumulate(&mut self, _acc: T) { |
2855 | *self += 1; |
2856 | } |
2857 | } |
2858 | |
2859 | #[cfg (feature = "alloc" )] |
2860 | impl<T> Accumulate<T> for Vec<T> { |
2861 | #[inline (always)] |
2862 | fn initial(capacity: Option<usize>) -> Self { |
2863 | match capacity { |
2864 | Some(capacity: usize) => Vec::with_capacity(clamp_capacity::<T>(capacity)), |
2865 | None => Vec::new(), |
2866 | } |
2867 | } |
2868 | #[inline (always)] |
2869 | fn accumulate(&mut self, acc: T) { |
2870 | self.push(acc); |
2871 | } |
2872 | } |
2873 | |
2874 | #[cfg (feature = "alloc" )] |
2875 | impl<'i, T: Clone> Accumulate<&'i [T]> for Vec<T> { |
2876 | #[inline (always)] |
2877 | fn initial(capacity: Option<usize>) -> Self { |
2878 | match capacity { |
2879 | Some(capacity: usize) => Vec::with_capacity(clamp_capacity::<T>(capacity)), |
2880 | None => Vec::new(), |
2881 | } |
2882 | } |
2883 | #[inline (always)] |
2884 | fn accumulate(&mut self, acc: &'i [T]) { |
2885 | self.extend(iter:acc.iter().cloned()); |
2886 | } |
2887 | } |
2888 | |
2889 | #[cfg (feature = "alloc" )] |
2890 | impl Accumulate<char> for String { |
2891 | #[inline (always)] |
2892 | fn initial(capacity: Option<usize>) -> Self { |
2893 | match capacity { |
2894 | Some(capacity: usize) => String::with_capacity(clamp_capacity::<char>(capacity)), |
2895 | None => String::new(), |
2896 | } |
2897 | } |
2898 | #[inline (always)] |
2899 | fn accumulate(&mut self, acc: char) { |
2900 | self.push(ch:acc); |
2901 | } |
2902 | } |
2903 | |
2904 | #[cfg (feature = "alloc" )] |
2905 | impl<'i> Accumulate<&'i str> for String { |
2906 | #[inline (always)] |
2907 | fn initial(capacity: Option<usize>) -> Self { |
2908 | match capacity { |
2909 | Some(capacity: usize) => String::with_capacity(clamp_capacity::<char>(capacity)), |
2910 | None => String::new(), |
2911 | } |
2912 | } |
2913 | #[inline (always)] |
2914 | fn accumulate(&mut self, acc: &'i str) { |
2915 | self.push_str(string:acc); |
2916 | } |
2917 | } |
2918 | |
2919 | #[cfg (feature = "alloc" )] |
2920 | impl<K, V> Accumulate<(K, V)> for BTreeMap<K, V> |
2921 | where |
2922 | K: crate::lib::std::cmp::Ord, |
2923 | { |
2924 | #[inline (always)] |
2925 | fn initial(_capacity: Option<usize>) -> Self { |
2926 | BTreeMap::new() |
2927 | } |
2928 | #[inline (always)] |
2929 | fn accumulate(&mut self, (key: K, value: V): (K, V)) { |
2930 | self.insert(key, value); |
2931 | } |
2932 | } |
2933 | |
2934 | #[cfg (feature = "std" )] |
2935 | impl<K, V, S> Accumulate<(K, V)> for HashMap<K, V, S> |
2936 | where |
2937 | K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash, |
2938 | S: BuildHasher + Default, |
2939 | { |
2940 | #[inline (always)] |
2941 | fn initial(capacity: Option<usize>) -> Self { |
2942 | let h: S = S::default(); |
2943 | match capacity { |
2944 | Some(capacity: usize) => { |
2945 | HashMap::with_capacity_and_hasher(capacity:clamp_capacity::<(K, V)>(capacity), hasher:h) |
2946 | } |
2947 | None => HashMap::with_hasher(hash_builder:h), |
2948 | } |
2949 | } |
2950 | #[inline (always)] |
2951 | fn accumulate(&mut self, (key: K, value: V): (K, V)) { |
2952 | self.insert(k:key, v:value); |
2953 | } |
2954 | } |
2955 | |
2956 | #[cfg (feature = "alloc" )] |
2957 | impl<K> Accumulate<K> for BTreeSet<K> |
2958 | where |
2959 | K: crate::lib::std::cmp::Ord, |
2960 | { |
2961 | #[inline (always)] |
2962 | fn initial(_capacity: Option<usize>) -> Self { |
2963 | BTreeSet::new() |
2964 | } |
2965 | #[inline (always)] |
2966 | fn accumulate(&mut self, key: K) { |
2967 | self.insert(key); |
2968 | } |
2969 | } |
2970 | |
2971 | #[cfg (feature = "std" )] |
2972 | impl<K, S> Accumulate<K> for HashSet<K, S> |
2973 | where |
2974 | K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash, |
2975 | S: BuildHasher + Default, |
2976 | { |
2977 | #[inline (always)] |
2978 | fn initial(capacity: Option<usize>) -> Self { |
2979 | let h: S = S::default(); |
2980 | match capacity { |
2981 | Some(capacity: usize) => HashSet::with_capacity_and_hasher(capacity:clamp_capacity::<K>(capacity), hasher:h), |
2982 | None => HashSet::with_hasher(h), |
2983 | } |
2984 | } |
2985 | #[inline (always)] |
2986 | fn accumulate(&mut self, key: K) { |
2987 | self.insert(key); |
2988 | } |
2989 | } |
2990 | |
2991 | #[cfg (feature = "alloc" )] |
2992 | #[inline ] |
2993 | pub(crate) fn clamp_capacity<T>(capacity: usize) -> usize { |
2994 | /// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`. |
2995 | /// |
2996 | /// Pre-allocating memory is a nice optimization but count fields can't |
2997 | /// always be trusted. We should clamp initial capacities to some reasonable |
2998 | /// amount. This reduces the risk of a bogus count value triggering a panic |
2999 | /// due to an OOM error. |
3000 | /// |
3001 | /// This does not affect correctness. `winnow` will always read the full number |
3002 | /// of elements regardless of the capacity cap. |
3003 | const MAX_INITIAL_CAPACITY_BYTES: usize = 65536; |
3004 | |
3005 | let max_initial_capacity: usize = |
3006 | MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::<T>().max(1); |
3007 | capacity.min(max_initial_capacity) |
3008 | } |
3009 | |
3010 | /// Helper trait to convert numbers to usize. |
3011 | /// |
3012 | /// By default, usize implements `From<u8>` and `From<u16>` but not |
3013 | /// `From<u32>` and `From<u64>` because that would be invalid on some |
3014 | /// platforms. This trait implements the conversion for platforms |
3015 | /// with 32 and 64 bits pointer platforms |
3016 | pub trait ToUsize { |
3017 | /// converts self to usize |
3018 | fn to_usize(&self) -> usize; |
3019 | } |
3020 | |
3021 | impl ToUsize for u8 { |
3022 | #[inline (always)] |
3023 | fn to_usize(&self) -> usize { |
3024 | *self as usize |
3025 | } |
3026 | } |
3027 | |
3028 | impl ToUsize for u16 { |
3029 | #[inline (always)] |
3030 | fn to_usize(&self) -> usize { |
3031 | *self as usize |
3032 | } |
3033 | } |
3034 | |
3035 | impl ToUsize for usize { |
3036 | #[inline (always)] |
3037 | fn to_usize(&self) -> usize { |
3038 | *self |
3039 | } |
3040 | } |
3041 | |
3042 | #[cfg (any(target_pointer_width = "32" , target_pointer_width = "64" ))] |
3043 | impl ToUsize for u32 { |
3044 | #[inline (always)] |
3045 | fn to_usize(&self) -> usize { |
3046 | *self as usize |
3047 | } |
3048 | } |
3049 | |
3050 | #[cfg (target_pointer_width = "64" )] |
3051 | impl ToUsize for u64 { |
3052 | #[inline (always)] |
3053 | fn to_usize(&self) -> usize { |
3054 | *self as usize |
3055 | } |
3056 | } |
3057 | |
3058 | /// Transforms a token into a char for basic string parsing |
3059 | #[allow (clippy::len_without_is_empty)] |
3060 | #[allow (clippy::wrong_self_convention)] |
3061 | pub trait AsChar { |
3062 | /// Makes a char from self |
3063 | /// |
3064 | /// # Example |
3065 | /// |
3066 | /// ``` |
3067 | /// use winnow::stream::AsChar as _; |
3068 | /// |
3069 | /// assert_eq!('a' .as_char(), 'a' ); |
3070 | /// assert_eq!(u8::MAX.as_char(), std::char::from_u32(u8::MAX as u32).unwrap()); |
3071 | /// ``` |
3072 | fn as_char(self) -> char; |
3073 | |
3074 | /// Tests that self is an alphabetic character |
3075 | /// |
3076 | /// **Warning:** for `&str` it recognizes alphabetic |
3077 | /// characters outside of the 52 ASCII letters |
3078 | fn is_alpha(self) -> bool; |
3079 | |
3080 | /// Tests that self is an alphabetic character |
3081 | /// or a decimal digit |
3082 | fn is_alphanum(self) -> bool; |
3083 | /// Tests that self is a decimal digit |
3084 | fn is_dec_digit(self) -> bool; |
3085 | /// Tests that self is an hex digit |
3086 | fn is_hex_digit(self) -> bool; |
3087 | /// Tests that self is an octal digit |
3088 | fn is_oct_digit(self) -> bool; |
3089 | /// Gets the len in bytes for self |
3090 | fn len(self) -> usize; |
3091 | /// Tests that self is ASCII space or tab |
3092 | fn is_space(self) -> bool; |
3093 | /// Tests if byte is ASCII newline: \n |
3094 | fn is_newline(self) -> bool; |
3095 | } |
3096 | |
3097 | impl AsChar for u8 { |
3098 | #[inline (always)] |
3099 | fn as_char(self) -> char { |
3100 | self as char |
3101 | } |
3102 | #[inline ] |
3103 | fn is_alpha(self) -> bool { |
3104 | matches!(self, 0x41..=0x5A | 0x61..=0x7A) |
3105 | } |
3106 | #[inline ] |
3107 | fn is_alphanum(self) -> bool { |
3108 | self.is_alpha() || self.is_dec_digit() |
3109 | } |
3110 | #[inline ] |
3111 | fn is_dec_digit(self) -> bool { |
3112 | matches!(self, 0x30..=0x39) |
3113 | } |
3114 | #[inline ] |
3115 | fn is_hex_digit(self) -> bool { |
3116 | matches!(self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) |
3117 | } |
3118 | #[inline ] |
3119 | fn is_oct_digit(self) -> bool { |
3120 | matches!(self, 0x30..=0x37) |
3121 | } |
3122 | #[inline ] |
3123 | fn len(self) -> usize { |
3124 | 1 |
3125 | } |
3126 | #[inline ] |
3127 | fn is_space(self) -> bool { |
3128 | self == b' ' || self == b' \t' |
3129 | } |
3130 | #[inline ] |
3131 | fn is_newline(self) -> bool { |
3132 | self == b' \n' |
3133 | } |
3134 | } |
3135 | |
3136 | impl<'a> AsChar for &'a u8 { |
3137 | #[inline (always)] |
3138 | fn as_char(self) -> char { |
3139 | (*self).as_char() |
3140 | } |
3141 | #[inline (always)] |
3142 | fn is_alpha(self) -> bool { |
3143 | (*self).is_alpha() |
3144 | } |
3145 | #[inline (always)] |
3146 | fn is_alphanum(self) -> bool { |
3147 | (*self).is_alphanum() |
3148 | } |
3149 | #[inline (always)] |
3150 | fn is_dec_digit(self) -> bool { |
3151 | (*self).is_dec_digit() |
3152 | } |
3153 | #[inline (always)] |
3154 | fn is_hex_digit(self) -> bool { |
3155 | (*self).is_hex_digit() |
3156 | } |
3157 | #[inline (always)] |
3158 | fn is_oct_digit(self) -> bool { |
3159 | (*self).is_oct_digit() |
3160 | } |
3161 | #[inline (always)] |
3162 | fn len(self) -> usize { |
3163 | (*self).len() |
3164 | } |
3165 | #[inline (always)] |
3166 | fn is_space(self) -> bool { |
3167 | (*self).is_space() |
3168 | } |
3169 | #[inline (always)] |
3170 | fn is_newline(self) -> bool { |
3171 | (*self).is_newline() |
3172 | } |
3173 | } |
3174 | |
3175 | impl AsChar for char { |
3176 | #[inline (always)] |
3177 | fn as_char(self) -> char { |
3178 | self |
3179 | } |
3180 | #[inline ] |
3181 | fn is_alpha(self) -> bool { |
3182 | self.is_ascii_alphabetic() |
3183 | } |
3184 | #[inline ] |
3185 | fn is_alphanum(self) -> bool { |
3186 | self.is_alpha() || self.is_dec_digit() |
3187 | } |
3188 | #[inline ] |
3189 | fn is_dec_digit(self) -> bool { |
3190 | self.is_ascii_digit() |
3191 | } |
3192 | #[inline ] |
3193 | fn is_hex_digit(self) -> bool { |
3194 | self.is_ascii_hexdigit() |
3195 | } |
3196 | #[inline ] |
3197 | fn is_oct_digit(self) -> bool { |
3198 | self.is_digit(8) |
3199 | } |
3200 | #[inline ] |
3201 | fn len(self) -> usize { |
3202 | self.len_utf8() |
3203 | } |
3204 | #[inline ] |
3205 | fn is_space(self) -> bool { |
3206 | self == ' ' || self == ' \t' |
3207 | } |
3208 | #[inline ] |
3209 | fn is_newline(self) -> bool { |
3210 | self == ' \n' |
3211 | } |
3212 | } |
3213 | |
3214 | impl<'a> AsChar for &'a char { |
3215 | #[inline (always)] |
3216 | fn as_char(self) -> char { |
3217 | (*self).as_char() |
3218 | } |
3219 | #[inline (always)] |
3220 | fn is_alpha(self) -> bool { |
3221 | (*self).is_alpha() |
3222 | } |
3223 | #[inline (always)] |
3224 | fn is_alphanum(self) -> bool { |
3225 | (*self).is_alphanum() |
3226 | } |
3227 | #[inline (always)] |
3228 | fn is_dec_digit(self) -> bool { |
3229 | (*self).is_dec_digit() |
3230 | } |
3231 | #[inline (always)] |
3232 | fn is_hex_digit(self) -> bool { |
3233 | (*self).is_hex_digit() |
3234 | } |
3235 | #[inline (always)] |
3236 | fn is_oct_digit(self) -> bool { |
3237 | (*self).is_oct_digit() |
3238 | } |
3239 | #[inline (always)] |
3240 | fn len(self) -> usize { |
3241 | (*self).len() |
3242 | } |
3243 | #[inline (always)] |
3244 | fn is_space(self) -> bool { |
3245 | (*self).is_space() |
3246 | } |
3247 | #[inline (always)] |
3248 | fn is_newline(self) -> bool { |
3249 | (*self).is_newline() |
3250 | } |
3251 | } |
3252 | |
3253 | /// Check if a token is in a set of possible tokens |
3254 | /// |
3255 | /// While this can be implemented manually, you can also build up sets using: |
3256 | /// - `b'c'` and `'c'` |
3257 | /// - `b""` |
3258 | /// - `|c| true` |
3259 | /// - `b'a'..=b'z'`, `'a'..='z'` (etc for each [range type][std::ops]) |
3260 | /// - `(set1, set2, ...)` |
3261 | /// |
3262 | /// # Example |
3263 | /// |
3264 | /// For example, you could implement `hex_digit0` as: |
3265 | /// ``` |
3266 | /// # use winnow::prelude::*; |
3267 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; |
3268 | /// # use winnow::token::take_while; |
3269 | /// fn hex_digit1<'s>(input: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> { |
3270 | /// take_while(1.., ('a' ..='f' , 'A' ..='F' , '0' ..='9' )).parse_next(input) |
3271 | /// } |
3272 | /// |
3273 | /// assert_eq!(hex_digit1.parse_peek("21cZ" ), Ok(("Z" , "21c" ))); |
3274 | /// assert_eq!(hex_digit1.parse_peek("H2" ), Err(ErrMode::Backtrack(InputError::new("H2" , ErrorKind::Slice)))); |
3275 | /// assert_eq!(hex_digit1.parse_peek("" ), Err(ErrMode::Backtrack(InputError::new("" , ErrorKind::Slice)))); |
3276 | /// ``` |
3277 | pub trait ContainsToken<T> { |
3278 | /// Returns true if self contains the token |
3279 | fn contains_token(&self, token: T) -> bool; |
3280 | } |
3281 | |
3282 | impl ContainsToken<u8> for u8 { |
3283 | #[inline (always)] |
3284 | fn contains_token(&self, token: u8) -> bool { |
3285 | *self == token |
3286 | } |
3287 | } |
3288 | |
3289 | impl<'a> ContainsToken<&'a u8> for u8 { |
3290 | #[inline (always)] |
3291 | fn contains_token(&self, token: &u8) -> bool { |
3292 | self.contains_token(*token) |
3293 | } |
3294 | } |
3295 | |
3296 | impl ContainsToken<char> for u8 { |
3297 | #[inline (always)] |
3298 | fn contains_token(&self, token: char) -> bool { |
3299 | self.as_char() == token |
3300 | } |
3301 | } |
3302 | |
3303 | impl<'a> ContainsToken<&'a char> for u8 { |
3304 | #[inline (always)] |
3305 | fn contains_token(&self, token: &char) -> bool { |
3306 | self.contains_token(*token) |
3307 | } |
3308 | } |
3309 | |
3310 | impl<C: AsChar> ContainsToken<C> for char { |
3311 | #[inline (always)] |
3312 | fn contains_token(&self, token: C) -> bool { |
3313 | *self == token.as_char() |
3314 | } |
3315 | } |
3316 | |
3317 | impl<C, F: Fn(C) -> bool> ContainsToken<C> for F { |
3318 | #[inline (always)] |
3319 | fn contains_token(&self, token: C) -> bool { |
3320 | self(token) |
3321 | } |
3322 | } |
3323 | |
3324 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for crate::lib::std::ops::Range<C2> { |
3325 | #[inline (always)] |
3326 | fn contains_token(&self, token: C1) -> bool { |
3327 | let start: char = self.start.clone().as_char(); |
3328 | let end: char = self.end.clone().as_char(); |
3329 | (start..end).contains(&token.as_char()) |
3330 | } |
3331 | } |
3332 | |
3333 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> |
3334 | for crate::lib::std::ops::RangeInclusive<C2> |
3335 | { |
3336 | #[inline (always)] |
3337 | fn contains_token(&self, token: C1) -> bool { |
3338 | let start: char = self.start().clone().as_char(); |
3339 | let end: char = self.end().clone().as_char(); |
3340 | (start..=end).contains(&token.as_char()) |
3341 | } |
3342 | } |
3343 | |
3344 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for crate::lib::std::ops::RangeFrom<C2> { |
3345 | #[inline (always)] |
3346 | fn contains_token(&self, token: C1) -> bool { |
3347 | let start: char = self.start.clone().as_char(); |
3348 | (start..).contains(&token.as_char()) |
3349 | } |
3350 | } |
3351 | |
3352 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for crate::lib::std::ops::RangeTo<C2> { |
3353 | #[inline (always)] |
3354 | fn contains_token(&self, token: C1) -> bool { |
3355 | let end: char = self.end.clone().as_char(); |
3356 | (..end).contains(&token.as_char()) |
3357 | } |
3358 | } |
3359 | |
3360 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> |
3361 | for crate::lib::std::ops::RangeToInclusive<C2> |
3362 | { |
3363 | #[inline (always)] |
3364 | fn contains_token(&self, token: C1) -> bool { |
3365 | let end: char = self.end.clone().as_char(); |
3366 | (..=end).contains(&token.as_char()) |
3367 | } |
3368 | } |
3369 | |
3370 | impl<C1: AsChar> ContainsToken<C1> for crate::lib::std::ops::RangeFull { |
3371 | #[inline (always)] |
3372 | fn contains_token(&self, _token: C1) -> bool { |
3373 | true |
3374 | } |
3375 | } |
3376 | |
3377 | impl<C: AsChar> ContainsToken<C> for &'_ [u8] { |
3378 | #[inline ] |
3379 | fn contains_token(&self, token: C) -> bool { |
3380 | let token: char = token.as_char(); |
3381 | self.iter().any(|t: &u8| t.as_char() == token) |
3382 | } |
3383 | } |
3384 | |
3385 | impl<C: AsChar> ContainsToken<C> for &'_ [char] { |
3386 | #[inline ] |
3387 | fn contains_token(&self, token: C) -> bool { |
3388 | let token: char = token.as_char(); |
3389 | self.iter().any(|t: &char| *t == token) |
3390 | } |
3391 | } |
3392 | |
3393 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for &'_ [u8; LEN] { |
3394 | #[inline ] |
3395 | fn contains_token(&self, token: C) -> bool { |
3396 | let token: char = token.as_char(); |
3397 | self.iter().any(|t: &u8| t.as_char() == token) |
3398 | } |
3399 | } |
3400 | |
3401 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for &'_ [char; LEN] { |
3402 | #[inline ] |
3403 | fn contains_token(&self, token: C) -> bool { |
3404 | let token: char = token.as_char(); |
3405 | self.iter().any(|t: &char| *t == token) |
3406 | } |
3407 | } |
3408 | |
3409 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for [u8; LEN] { |
3410 | #[inline ] |
3411 | fn contains_token(&self, token: C) -> bool { |
3412 | let token: char = token.as_char(); |
3413 | self.iter().any(|t: &u8| t.as_char() == token) |
3414 | } |
3415 | } |
3416 | |
3417 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for [char; LEN] { |
3418 | #[inline ] |
3419 | fn contains_token(&self, token: C) -> bool { |
3420 | let token: char = token.as_char(); |
3421 | self.iter().any(|t: &char| *t == token) |
3422 | } |
3423 | } |
3424 | |
3425 | impl<T> ContainsToken<T> for () { |
3426 | #[inline (always)] |
3427 | fn contains_token(&self, _token: T) -> bool { |
3428 | false |
3429 | } |
3430 | } |
3431 | |
3432 | macro_rules! impl_contains_token_for_tuple { |
3433 | ($($haystack:ident),+) => ( |
3434 | #[allow(non_snake_case)] |
3435 | impl<T, $($haystack),+> ContainsToken<T> for ($($haystack),+,) |
3436 | where |
3437 | T: Clone, |
3438 | $($haystack: ContainsToken<T>),+ |
3439 | { |
3440 | #[inline] |
3441 | fn contains_token(&self, token: T) -> bool { |
3442 | let ($(ref $haystack),+,) = *self; |
3443 | $($haystack.contains_token(token.clone()) || )+ false |
3444 | } |
3445 | } |
3446 | ) |
3447 | } |
3448 | |
3449 | macro_rules! impl_contains_token_for_tuples { |
3450 | ($haystack1:ident, $($haystack:ident),+) => { |
3451 | impl_contains_token_for_tuples!(__impl $haystack1; $($haystack),+); |
3452 | }; |
3453 | (__impl $($haystack:ident),+; $haystack1:ident $(,$haystack2:ident)*) => { |
3454 | impl_contains_token_for_tuple!($($haystack),+); |
3455 | impl_contains_token_for_tuples!(__impl $($haystack),+, $haystack1; $($haystack2),*); |
3456 | }; |
3457 | (__impl $($haystack:ident),+;) => { |
3458 | impl_contains_token_for_tuple!($($haystack),+); |
3459 | } |
3460 | } |
3461 | |
3462 | impl_contains_token_for_tuples!( |
3463 | F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21 |
3464 | ); |
3465 | |
3466 | #[cfg (feature = "simd" )] |
3467 | #[inline (always)] |
3468 | fn memchr(token: u8, slice: &[u8]) -> Option<usize> { |
3469 | memchr::memchr(token, slice) |
3470 | } |
3471 | |
3472 | #[cfg (feature = "simd" )] |
3473 | #[inline (always)] |
3474 | fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> { |
3475 | memchr::memchr2(token.0, token.1, slice) |
3476 | } |
3477 | |
3478 | #[cfg (feature = "simd" )] |
3479 | #[inline (always)] |
3480 | fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> { |
3481 | memchr::memchr3(token.0, token.1, token.2, slice) |
3482 | } |
3483 | |
3484 | #[cfg (not(feature = "simd" ))] |
3485 | #[inline (always)] |
3486 | fn memchr(token: u8, slice: &[u8]) -> Option<usize> { |
3487 | slice.iter().position(|t: &u8| *t == token) |
3488 | } |
3489 | |
3490 | #[cfg (not(feature = "simd" ))] |
3491 | #[inline (always)] |
3492 | fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> { |
3493 | slice.iter().position(|t: &u8| *t == token.0 || *t == token.1) |
3494 | } |
3495 | |
3496 | #[cfg (not(feature = "simd" ))] |
3497 | #[inline (always)] |
3498 | fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> { |
3499 | sliceIter<'_, u8> |
3500 | .iter() |
3501 | .position(|t: &u8| *t == token.0 || *t == token.1 || *t == token.2) |
3502 | } |
3503 | |
3504 | #[inline (always)] |
3505 | fn memmem(slice: &[u8], literal: &[u8]) -> Option<crate::lib::std::ops::Range<usize>> { |
3506 | match literal.len() { |
3507 | 0 => Some(0..0), |
3508 | 1 => memchr(token:literal[0], slice).map(|i: usize| i..i + 1), |
3509 | _ => memmem_(slice, literal), |
3510 | } |
3511 | } |
3512 | |
3513 | #[inline (always)] |
3514 | fn memmem2(slice: &[u8], literal: (&[u8], &[u8])) -> Option<crate::lib::std::ops::Range<usize>> { |
3515 | match (literal.0.len(), literal.1.len()) { |
3516 | (0, _) | (_, 0) => Some(0..0), |
3517 | (1, 1) => memchr2((literal.0[0], literal.1[0]), slice).map(|i: usize| i..i + 1), |
3518 | _ => memmem2_(slice, literal), |
3519 | } |
3520 | } |
3521 | |
3522 | #[inline (always)] |
3523 | fn memmem3( |
3524 | slice: &[u8], |
3525 | literal: (&[u8], &[u8], &[u8]), |
3526 | ) -> Option<crate::lib::std::ops::Range<usize>> { |
3527 | match (literal.0.len(), literal.1.len(), literal.2.len()) { |
3528 | (0, _, _) | (_, 0, _) | (_, _, 0) => Some(0..0), |
3529 | (1, 1, 1) => memchr3((literal.0[0], literal.1[0], literal.2[0]), slice).map(|i: usize| i..i + 1), |
3530 | _ => memmem3_(slice, literal), |
3531 | } |
3532 | } |
3533 | |
3534 | #[cfg (feature = "simd" )] |
3535 | #[inline (always)] |
3536 | fn memmem_(slice: &[u8], literal: &[u8]) -> Option<crate::lib::std::ops::Range<usize>> { |
3537 | let &prefix = match literal.first() { |
3538 | Some(x) => x, |
3539 | None => return Some(0..0), |
3540 | }; |
3541 | #[allow (clippy::manual_find)] // faster this way |
3542 | for i in memchr::memchr_iter(prefix, slice) { |
3543 | if slice[i..].starts_with(literal) { |
3544 | let i_end = i + literal.len(); |
3545 | return Some(i..i_end); |
3546 | } |
3547 | } |
3548 | None |
3549 | } |
3550 | |
3551 | #[cfg (feature = "simd" )] |
3552 | fn memmem2_(slice: &[u8], literal: (&[u8], &[u8])) -> Option<crate::lib::std::ops::Range<usize>> { |
3553 | let prefix = match (literal.0.first(), literal.1.first()) { |
3554 | (Some(&a), Some(&b)) => (a, b), |
3555 | _ => return Some(0..0), |
3556 | }; |
3557 | #[allow (clippy::manual_find)] // faster this way |
3558 | for i in memchr::memchr2_iter(prefix.0, prefix.1, slice) { |
3559 | let subslice = &slice[i..]; |
3560 | if subslice.starts_with(literal.0) { |
3561 | let i_end = i + literal.0.len(); |
3562 | return Some(i..i_end); |
3563 | } |
3564 | if subslice.starts_with(literal.1) { |
3565 | let i_end = i + literal.1.len(); |
3566 | return Some(i..i_end); |
3567 | } |
3568 | } |
3569 | None |
3570 | } |
3571 | |
3572 | #[cfg (feature = "simd" )] |
3573 | fn memmem3_( |
3574 | slice: &[u8], |
3575 | literal: (&[u8], &[u8], &[u8]), |
3576 | ) -> Option<crate::lib::std::ops::Range<usize>> { |
3577 | let prefix = match (literal.0.first(), literal.1.first(), literal.2.first()) { |
3578 | (Some(&a), Some(&b), Some(&c)) => (a, b, c), |
3579 | _ => return Some(0..0), |
3580 | }; |
3581 | #[allow (clippy::manual_find)] // faster this way |
3582 | for i in memchr::memchr3_iter(prefix.0, prefix.1, prefix.2, slice) { |
3583 | let subslice = &slice[i..]; |
3584 | if subslice.starts_with(literal.0) { |
3585 | let i_end = i + literal.0.len(); |
3586 | return Some(i..i_end); |
3587 | } |
3588 | if subslice.starts_with(literal.1) { |
3589 | let i_end = i + literal.1.len(); |
3590 | return Some(i..i_end); |
3591 | } |
3592 | if subslice.starts_with(literal.2) { |
3593 | let i_end = i + literal.2.len(); |
3594 | return Some(i..i_end); |
3595 | } |
3596 | } |
3597 | None |
3598 | } |
3599 | |
3600 | #[cfg (not(feature = "simd" ))] |
3601 | fn memmem_(slice: &[u8], literal: &[u8]) -> Option<crate::lib::std::ops::Range<usize>> { |
3602 | for i: usize in 0..slice.len() { |
3603 | let subslice: &[u8] = &slice[i..]; |
3604 | if subslice.starts_with(needle:literal) { |
3605 | let i_end: usize = i + literal.len(); |
3606 | return Some(i..i_end); |
3607 | } |
3608 | } |
3609 | None |
3610 | } |
3611 | |
3612 | #[cfg (not(feature = "simd" ))] |
3613 | fn memmem2_(slice: &[u8], literal: (&[u8], &[u8])) -> Option<crate::lib::std::ops::Range<usize>> { |
3614 | for i: usize in 0..slice.len() { |
3615 | let subslice: &[u8] = &slice[i..]; |
3616 | if subslice.starts_with(needle:literal.0) { |
3617 | let i_end: usize = i + literal.0.len(); |
3618 | return Some(i..i_end); |
3619 | } |
3620 | if subslice.starts_with(needle:literal.1) { |
3621 | let i_end: usize = i + literal.1.len(); |
3622 | return Some(i..i_end); |
3623 | } |
3624 | } |
3625 | None |
3626 | } |
3627 | |
3628 | #[cfg (not(feature = "simd" ))] |
3629 | fn memmem3_( |
3630 | slice: &[u8], |
3631 | literal: (&[u8], &[u8], &[u8]), |
3632 | ) -> Option<crate::lib::std::ops::Range<usize>> { |
3633 | for i: usize in 0..slice.len() { |
3634 | let subslice: &[u8] = &slice[i..]; |
3635 | if subslice.starts_with(needle:literal.0) { |
3636 | let i_end: usize = i + literal.0.len(); |
3637 | return Some(i..i_end); |
3638 | } |
3639 | if subslice.starts_with(needle:literal.1) { |
3640 | let i_end: usize = i + literal.1.len(); |
3641 | return Some(i..i_end); |
3642 | } |
3643 | if subslice.starts_with(needle:literal.2) { |
3644 | let i_end: usize = i + literal.2.len(); |
3645 | return Some(i..i_end); |
3646 | } |
3647 | } |
3648 | None |
3649 | } |
3650 | |