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>; |
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) |
691 | } |
692 | #[inline (always)] |
693 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
694 | *self = checkpoint.0; |
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>; |
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) |
766 | } |
767 | #[inline (always)] |
768 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
769 | *self = checkpoint.0; |
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>; |
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) |
831 | } |
832 | #[inline (always)] |
833 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
834 | *self = checkpoint.0; |
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>; |
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) |
896 | } |
897 | #[inline (always)] |
898 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
899 | *self = checkpoint.0; |
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)>; |
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.0.checkpoint(), self.1)) |
973 | } |
974 | #[inline (always)] |
975 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
976 | self.0.reset(checkpoint.0 .0); |
977 | self.1 = checkpoint.0 .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>; |
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.input.checkpoint()) |
1072 | } |
1073 | #[inline (always)] |
1074 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
1075 | self.input.reset(checkpoint.0); |
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>; |
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.input.checkpoint()) |
1129 | } |
1130 | #[inline (always)] |
1131 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
1132 | self.input.reset(checkpoint.0); |
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>; |
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.input.checkpoint()) |
1182 | } |
1183 | #[inline (always)] |
1184 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
1185 | self.input.reset(checkpoint.0); |
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>; |
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.input.checkpoint()) |
1235 | } |
1236 | #[inline (always)] |
1237 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
1238 | self.input.reset(checkpoint.0); |
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> Offset for Checkpoint<I> |
1914 | where |
1915 | I: Offset, |
1916 | { |
1917 | #[inline (always)] |
1918 | fn offset_from(&self, start: &Self) -> usize { |
1919 | self.0.offset_from(&start.0) |
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 | Ok, |
2059 | /// We need more data to be sure |
2060 | Incomplete, |
2061 | /// Comparison failed |
2062 | Error, |
2063 | } |
2064 | |
2065 | /// Abstracts comparison operations |
2066 | pub trait Compare<T> { |
2067 | /// Compares self to another value for equality |
2068 | fn compare(&self, t: T) -> CompareResult; |
2069 | /// Compares self to another value for equality |
2070 | /// independently of the case. |
2071 | /// |
2072 | /// Warning: for `&str`, the comparison is done |
2073 | /// by lowercasing both strings and comparing |
2074 | /// the result. This is a temporary solution until |
2075 | /// a better one appears |
2076 | #[deprecated (since = "0.5.20" , note = "Replaced with `compare(ascii::Caseless(_))`" )] |
2077 | fn compare_no_case(&self, t: T) -> CompareResult; |
2078 | } |
2079 | |
2080 | impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { |
2081 | #[inline ] |
2082 | fn compare(&self, t: &'b [u8]) -> CompareResult { |
2083 | if t.iter().zip(*self).any(|(a: &u8, b: &u8)| a != b) { |
2084 | CompareResult::Error |
2085 | } else if self.len() < t.slice_len() { |
2086 | CompareResult::Incomplete |
2087 | } else { |
2088 | CompareResult::Ok |
2089 | } |
2090 | } |
2091 | |
2092 | #[inline (always)] |
2093 | #[allow (deprecated)] |
2094 | fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { |
2095 | self.compare(AsciiCaseless(t)) |
2096 | } |
2097 | } |
2098 | |
2099 | impl<'a, 'b> Compare<AsciiCaseless<&'b [u8]>> for &'a [u8] { |
2100 | #[inline ] |
2101 | fn compare(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult { |
2102 | if timpl Iterator .0 |
2103 | .iter() |
2104 | .zip(*self) |
2105 | .any(|(a: &u8, b: &u8)| !a.eq_ignore_ascii_case(b)) |
2106 | { |
2107 | CompareResult::Error |
2108 | } else if self.len() < t.slice_len() { |
2109 | CompareResult::Incomplete |
2110 | } else { |
2111 | CompareResult::Ok |
2112 | } |
2113 | } |
2114 | |
2115 | #[inline (always)] |
2116 | #[allow (deprecated)] |
2117 | fn compare_no_case(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult { |
2118 | self.compare(t) |
2119 | } |
2120 | } |
2121 | |
2122 | impl<'a, const LEN: usize> Compare<[u8; LEN]> for &'a [u8] { |
2123 | #[inline (always)] |
2124 | fn compare(&self, t: [u8; LEN]) -> CompareResult { |
2125 | self.compare(&t[..]) |
2126 | } |
2127 | |
2128 | #[inline (always)] |
2129 | #[allow (deprecated)] |
2130 | fn compare_no_case(&self, t: [u8; LEN]) -> CompareResult { |
2131 | self.compare_no_case(&t[..]) |
2132 | } |
2133 | } |
2134 | |
2135 | impl<'a, const LEN: usize> Compare<AsciiCaseless<[u8; LEN]>> for &'a [u8] { |
2136 | #[inline (always)] |
2137 | fn compare(&self, t: AsciiCaseless<[u8; LEN]>) -> CompareResult { |
2138 | self.compare(AsciiCaseless(&t.0[..])) |
2139 | } |
2140 | |
2141 | #[inline (always)] |
2142 | #[allow (deprecated)] |
2143 | fn compare_no_case(&self, t: AsciiCaseless<[u8; LEN]>) -> CompareResult { |
2144 | self.compare_no_case(AsciiCaseless(&t.0[..])) |
2145 | } |
2146 | } |
2147 | |
2148 | impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] { |
2149 | #[inline (always)] |
2150 | fn compare(&self, t: &'b [u8; LEN]) -> CompareResult { |
2151 | self.compare(&t[..]) |
2152 | } |
2153 | |
2154 | #[inline (always)] |
2155 | #[allow (deprecated)] |
2156 | fn compare_no_case(&self, t: &'b [u8; LEN]) -> CompareResult { |
2157 | self.compare_no_case(&t[..]) |
2158 | } |
2159 | } |
2160 | |
2161 | impl<'a, 'b, const LEN: usize> Compare<AsciiCaseless<&'b [u8; LEN]>> for &'a [u8] { |
2162 | #[inline (always)] |
2163 | fn compare(&self, t: AsciiCaseless<&'b [u8; LEN]>) -> CompareResult { |
2164 | self.compare(AsciiCaseless(&t.0[..])) |
2165 | } |
2166 | |
2167 | #[inline (always)] |
2168 | #[allow (deprecated)] |
2169 | fn compare_no_case(&self, t: AsciiCaseless<&'b [u8; LEN]>) -> CompareResult { |
2170 | self.compare_no_case(AsciiCaseless(&t.0[..])) |
2171 | } |
2172 | } |
2173 | |
2174 | impl<'a, 'b> Compare<&'b str> for &'a [u8] { |
2175 | #[inline (always)] |
2176 | fn compare(&self, t: &'b str) -> CompareResult { |
2177 | self.compare(t.as_bytes()) |
2178 | } |
2179 | #[inline (always)] |
2180 | #[allow (deprecated)] |
2181 | fn compare_no_case(&self, t: &'b str) -> CompareResult { |
2182 | self.compare_no_case(t.as_bytes()) |
2183 | } |
2184 | } |
2185 | |
2186 | impl<'a, 'b> Compare<AsciiCaseless<&'b str>> for &'a [u8] { |
2187 | #[inline (always)] |
2188 | fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult { |
2189 | self.compare(AsciiCaseless(t.0.as_bytes())) |
2190 | } |
2191 | #[inline (always)] |
2192 | #[allow (deprecated)] |
2193 | fn compare_no_case(&self, t: AsciiCaseless<&'b str>) -> CompareResult { |
2194 | self.compare_no_case(AsciiCaseless(t.0.as_bytes())) |
2195 | } |
2196 | } |
2197 | |
2198 | impl<'a> Compare<u8> for &'a [u8] { |
2199 | #[inline ] |
2200 | fn compare(&self, t: u8) -> CompareResult { |
2201 | match self.first().copied() { |
2202 | Some(c: u8) if t == c => CompareResult::Ok, |
2203 | Some(_) => CompareResult::Error, |
2204 | None => CompareResult::Incomplete, |
2205 | } |
2206 | } |
2207 | #[inline (always)] |
2208 | #[allow (deprecated)] |
2209 | fn compare_no_case(&self, t: u8) -> CompareResult { |
2210 | self.compare(AsciiCaseless(t)) |
2211 | } |
2212 | } |
2213 | |
2214 | impl<'a> Compare<AsciiCaseless<u8>> for &'a [u8] { |
2215 | #[inline ] |
2216 | fn compare(&self, t: AsciiCaseless<u8>) -> CompareResult { |
2217 | match self.first() { |
2218 | Some(c: &u8) if t.0.eq_ignore_ascii_case(c) => CompareResult::Ok, |
2219 | Some(_) => CompareResult::Error, |
2220 | None => CompareResult::Incomplete, |
2221 | } |
2222 | } |
2223 | #[inline (always)] |
2224 | #[allow (deprecated)] |
2225 | fn compare_no_case(&self, t: AsciiCaseless<u8>) -> CompareResult { |
2226 | self.compare(t) |
2227 | } |
2228 | } |
2229 | |
2230 | impl<'a> Compare<char> for &'a [u8] { |
2231 | #[inline (always)] |
2232 | fn compare(&self, t: char) -> CompareResult { |
2233 | self.compare(t.encode_utf8(&mut [0; 4]).as_bytes()) |
2234 | } |
2235 | |
2236 | #[inline (always)] |
2237 | #[allow (deprecated)] |
2238 | fn compare_no_case(&self, t: char) -> CompareResult { |
2239 | self.compare_no_case(t.encode_utf8(&mut [0; 4]).as_bytes()) |
2240 | } |
2241 | } |
2242 | |
2243 | impl<'a> Compare<AsciiCaseless<char>> for &'a [u8] { |
2244 | #[inline (always)] |
2245 | fn compare(&self, t: AsciiCaseless<char>) -> CompareResult { |
2246 | self.compare(AsciiCaseless(t.0.encode_utf8(&mut [0; 4]).as_bytes())) |
2247 | } |
2248 | |
2249 | #[inline (always)] |
2250 | #[allow (deprecated)] |
2251 | fn compare_no_case(&self, t: AsciiCaseless<char>) -> CompareResult { |
2252 | self.compare_no_case(AsciiCaseless(t.0.encode_utf8(&mut [0; 4]).as_bytes())) |
2253 | } |
2254 | } |
2255 | |
2256 | impl<'a, 'b> Compare<&'b str> for &'a str { |
2257 | #[inline (always)] |
2258 | fn compare(&self, t: &'b str) -> CompareResult { |
2259 | self.as_bytes().compare(t.as_bytes()) |
2260 | } |
2261 | |
2262 | #[inline ] |
2263 | #[allow (deprecated)] |
2264 | fn compare_no_case(&self, t: &'b str) -> CompareResult { |
2265 | self.compare(AsciiCaseless(t)) |
2266 | } |
2267 | } |
2268 | |
2269 | impl<'a, 'b> Compare<AsciiCaseless<&'b str>> for &'a str { |
2270 | #[inline (always)] |
2271 | fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult { |
2272 | self.as_bytes().compare(t.as_bytes()) |
2273 | } |
2274 | |
2275 | #[inline (always)] |
2276 | #[allow (deprecated)] |
2277 | fn compare_no_case(&self, t: AsciiCaseless<&'b str>) -> CompareResult { |
2278 | self.compare(t) |
2279 | } |
2280 | } |
2281 | |
2282 | impl<'a> Compare<u8> for &'a str { |
2283 | #[inline (always)] |
2284 | fn compare(&self, t: u8) -> CompareResult { |
2285 | self.as_bytes().compare(t) |
2286 | } |
2287 | #[inline (always)] |
2288 | #[allow (deprecated)] |
2289 | fn compare_no_case(&self, t: u8) -> CompareResult { |
2290 | self.compare(AsciiCaseless(t)) |
2291 | } |
2292 | } |
2293 | |
2294 | impl<'a> Compare<AsciiCaseless<u8>> for &'a str { |
2295 | #[inline (always)] |
2296 | fn compare(&self, t: AsciiCaseless<u8>) -> CompareResult { |
2297 | self.as_bytes().compare(t) |
2298 | } |
2299 | #[inline (always)] |
2300 | #[allow (deprecated)] |
2301 | fn compare_no_case(&self, t: AsciiCaseless<u8>) -> CompareResult { |
2302 | self.compare(t) |
2303 | } |
2304 | } |
2305 | |
2306 | impl<'a> Compare<char> for &'a str { |
2307 | #[inline (always)] |
2308 | fn compare(&self, t: char) -> CompareResult { |
2309 | self.as_bytes().compare(t) |
2310 | } |
2311 | |
2312 | #[inline (always)] |
2313 | #[allow (deprecated)] |
2314 | fn compare_no_case(&self, t: char) -> CompareResult { |
2315 | self.compare_no_case(t.encode_utf8(&mut [0; 4]).as_bytes()) |
2316 | } |
2317 | } |
2318 | |
2319 | impl<'a> Compare<AsciiCaseless<char>> for &'a str { |
2320 | #[inline (always)] |
2321 | fn compare(&self, t: AsciiCaseless<char>) -> CompareResult { |
2322 | self.as_bytes().compare(t) |
2323 | } |
2324 | |
2325 | #[inline (always)] |
2326 | #[allow (deprecated)] |
2327 | fn compare_no_case(&self, t: AsciiCaseless<char>) -> CompareResult { |
2328 | self.compare_no_case(AsciiCaseless(t.0.encode_utf8(&mut [0; 4]).as_bytes())) |
2329 | } |
2330 | } |
2331 | |
2332 | impl<'a, 'b> Compare<&'b [u8]> for &'a str { |
2333 | #[inline (always)] |
2334 | fn compare(&self, t: &'b [u8]) -> CompareResult { |
2335 | self.as_bytes().compare(t) |
2336 | } |
2337 | #[inline (always)] |
2338 | #[allow (deprecated)] |
2339 | fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { |
2340 | AsBStr::as_bstr(self).compare_no_case(t) |
2341 | } |
2342 | } |
2343 | |
2344 | impl<'a, 'b> Compare<AsciiCaseless<&'b [u8]>> for &'a str { |
2345 | #[inline (always)] |
2346 | fn compare(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult { |
2347 | self.as_bytes().compare(t) |
2348 | } |
2349 | #[inline (always)] |
2350 | #[allow (deprecated)] |
2351 | fn compare_no_case(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult { |
2352 | AsBStr::as_bstr(self).compare_no_case(t) |
2353 | } |
2354 | } |
2355 | |
2356 | impl<'a, T> Compare<T> for &'a Bytes |
2357 | where |
2358 | &'a [u8]: Compare<T>, |
2359 | { |
2360 | #[inline (always)] |
2361 | fn compare(&self, t: T) -> CompareResult { |
2362 | let bytes: &[u8] = (*self).as_bytes(); |
2363 | bytes.compare(t) |
2364 | } |
2365 | |
2366 | #[inline (always)] |
2367 | #[allow (deprecated)] |
2368 | fn compare_no_case(&self, t: T) -> CompareResult { |
2369 | let bytes: &[u8] = (*self).as_bytes(); |
2370 | bytes.compare_no_case(t) |
2371 | } |
2372 | } |
2373 | |
2374 | impl<'a, T> Compare<T> for &'a BStr |
2375 | where |
2376 | &'a [u8]: Compare<T>, |
2377 | { |
2378 | #[inline (always)] |
2379 | fn compare(&self, t: T) -> CompareResult { |
2380 | let bytes: &[u8] = (*self).as_bytes(); |
2381 | bytes.compare(t) |
2382 | } |
2383 | |
2384 | #[inline (always)] |
2385 | #[allow (deprecated)] |
2386 | fn compare_no_case(&self, t: T) -> CompareResult { |
2387 | let bytes: &[u8] = (*self).as_bytes(); |
2388 | bytes.compare_no_case(t) |
2389 | } |
2390 | } |
2391 | |
2392 | impl<I, U> Compare<U> for Located<I> |
2393 | where |
2394 | I: Compare<U>, |
2395 | { |
2396 | #[inline (always)] |
2397 | fn compare(&self, other: U) -> CompareResult { |
2398 | self.input.compare(other) |
2399 | } |
2400 | |
2401 | #[inline (always)] |
2402 | #[allow (deprecated)] |
2403 | fn compare_no_case(&self, other: U) -> CompareResult { |
2404 | self.input.compare_no_case(other) |
2405 | } |
2406 | } |
2407 | |
2408 | #[cfg (feature = "unstable-recover" )] |
2409 | impl<I, E, U> Compare<U> for Recoverable<I, E> |
2410 | where |
2411 | I: Stream, |
2412 | I: Compare<U>, |
2413 | { |
2414 | #[inline (always)] |
2415 | fn compare(&self, other: U) -> CompareResult { |
2416 | self.input.compare(other) |
2417 | } |
2418 | |
2419 | #[inline (always)] |
2420 | #[allow (deprecated)] |
2421 | fn compare_no_case(&self, other: U) -> CompareResult { |
2422 | self.input.compare_no_case(other) |
2423 | } |
2424 | } |
2425 | |
2426 | impl<I, S, U> Compare<U> for Stateful<I, S> |
2427 | where |
2428 | I: Compare<U>, |
2429 | { |
2430 | #[inline (always)] |
2431 | fn compare(&self, other: U) -> CompareResult { |
2432 | self.input.compare(other) |
2433 | } |
2434 | |
2435 | #[inline (always)] |
2436 | #[allow (deprecated)] |
2437 | fn compare_no_case(&self, other: U) -> CompareResult { |
2438 | self.input.compare_no_case(other) |
2439 | } |
2440 | } |
2441 | |
2442 | impl<I, T> Compare<T> for Partial<I> |
2443 | where |
2444 | I: Compare<T>, |
2445 | { |
2446 | #[inline (always)] |
2447 | fn compare(&self, t: T) -> CompareResult { |
2448 | self.input.compare(t) |
2449 | } |
2450 | |
2451 | #[inline (always)] |
2452 | #[allow (deprecated)] |
2453 | fn compare_no_case(&self, t: T) -> CompareResult { |
2454 | self.input.compare_no_case(t) |
2455 | } |
2456 | } |
2457 | |
2458 | /// Look for a slice in self |
2459 | pub trait FindSlice<T> { |
2460 | /// Returns the offset of the slice if it is found |
2461 | fn find_slice(&self, substr: T) -> Option<usize>; |
2462 | } |
2463 | |
2464 | impl<'i, 's> FindSlice<&'s [u8]> for &'i [u8] { |
2465 | #[inline (always)] |
2466 | fn find_slice(&self, substr: &'s [u8]) -> Option<usize> { |
2467 | memmem(self, tag:substr) |
2468 | } |
2469 | } |
2470 | |
2471 | impl<'i, 's> FindSlice<(&'s [u8],)> for &'i [u8] { |
2472 | #[inline (always)] |
2473 | fn find_slice(&self, substr: (&'s [u8],)) -> Option<usize> { |
2474 | memmem(self, tag:substr.0) |
2475 | } |
2476 | } |
2477 | |
2478 | impl<'i, 's> FindSlice<(&'s [u8], &'s [u8])> for &'i [u8] { |
2479 | #[inline (always)] |
2480 | fn find_slice(&self, substr: (&'s [u8], &'s [u8])) -> Option<usize> { |
2481 | memmem2(self, tag:substr) |
2482 | } |
2483 | } |
2484 | |
2485 | impl<'i, 's> FindSlice<(&'s [u8], &'s [u8], &'s [u8])> for &'i [u8] { |
2486 | #[inline (always)] |
2487 | fn find_slice(&self, substr: (&'s [u8], &'s [u8], &'s [u8])) -> Option<usize> { |
2488 | memmem3(self, tag:substr) |
2489 | } |
2490 | } |
2491 | |
2492 | impl<'i> FindSlice<char> for &'i [u8] { |
2493 | #[inline (always)] |
2494 | fn find_slice(&self, substr: char) -> Option<usize> { |
2495 | let mut b: [u8; 4] = [0; 4]; |
2496 | let substr: &mut str = substr.encode_utf8(&mut b); |
2497 | self.find_slice(&*substr) |
2498 | } |
2499 | } |
2500 | |
2501 | impl<'i> FindSlice<(char,)> for &'i [u8] { |
2502 | #[inline (always)] |
2503 | fn find_slice(&self, substr: (char,)) -> Option<usize> { |
2504 | let mut b: [u8; 4] = [0; 4]; |
2505 | let substr0: &mut str = substr.0.encode_utf8(&mut b); |
2506 | self.find_slice((&*substr0,)) |
2507 | } |
2508 | } |
2509 | |
2510 | impl<'i> FindSlice<(char, char)> for &'i [u8] { |
2511 | #[inline (always)] |
2512 | fn find_slice(&self, substr: (char, char)) -> Option<usize> { |
2513 | let mut b: [u8; 4] = [0; 4]; |
2514 | let substr0: &mut str = substr.0.encode_utf8(&mut b); |
2515 | let mut b: [u8; 4] = [0; 4]; |
2516 | let substr1: &mut str = substr.1.encode_utf8(&mut b); |
2517 | self.find_slice((&*substr0, &*substr1)) |
2518 | } |
2519 | } |
2520 | |
2521 | impl<'i> FindSlice<(char, char, char)> for &'i [u8] { |
2522 | #[inline (always)] |
2523 | fn find_slice(&self, substr: (char, char, char)) -> Option<usize> { |
2524 | let mut b: [u8; 4] = [0; 4]; |
2525 | let substr0: &mut str = substr.0.encode_utf8(&mut b); |
2526 | let mut b: [u8; 4] = [0; 4]; |
2527 | let substr1: &mut str = substr.1.encode_utf8(&mut b); |
2528 | let mut b: [u8; 4] = [0; 4]; |
2529 | let substr2: &mut str = substr.2.encode_utf8(&mut b); |
2530 | self.find_slice((&*substr0, &*substr1, &*substr2)) |
2531 | } |
2532 | } |
2533 | |
2534 | impl<'i> FindSlice<u8> for &'i [u8] { |
2535 | #[inline (always)] |
2536 | fn find_slice(&self, substr: u8) -> Option<usize> { |
2537 | memchr(token:substr, self) |
2538 | } |
2539 | } |
2540 | |
2541 | impl<'i> FindSlice<(u8,)> for &'i [u8] { |
2542 | #[inline (always)] |
2543 | fn find_slice(&self, substr: (u8,)) -> Option<usize> { |
2544 | memchr(token:substr.0, self) |
2545 | } |
2546 | } |
2547 | |
2548 | impl<'i> FindSlice<(u8, u8)> for &'i [u8] { |
2549 | #[inline (always)] |
2550 | fn find_slice(&self, substr: (u8, u8)) -> Option<usize> { |
2551 | memchr2(token:substr, self) |
2552 | } |
2553 | } |
2554 | |
2555 | impl<'i> FindSlice<(u8, u8, u8)> for &'i [u8] { |
2556 | #[inline (always)] |
2557 | fn find_slice(&self, substr: (u8, u8, u8)) -> Option<usize> { |
2558 | memchr3(token:substr, self) |
2559 | } |
2560 | } |
2561 | |
2562 | impl<'i, 's> FindSlice<&'s str> for &'i [u8] { |
2563 | #[inline (always)] |
2564 | fn find_slice(&self, substr: &'s str) -> Option<usize> { |
2565 | self.find_slice(substr:substr.as_bytes()) |
2566 | } |
2567 | } |
2568 | |
2569 | impl<'i, 's> FindSlice<(&'s str,)> for &'i [u8] { |
2570 | #[inline (always)] |
2571 | fn find_slice(&self, substr: (&'s str,)) -> Option<usize> { |
2572 | memmem(self, tag:substr.0.as_bytes()) |
2573 | } |
2574 | } |
2575 | |
2576 | impl<'i, 's> FindSlice<(&'s str, &'s str)> for &'i [u8] { |
2577 | #[inline (always)] |
2578 | fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<usize> { |
2579 | memmem2(self, (substr.0.as_bytes(), substr.1.as_bytes())) |
2580 | } |
2581 | } |
2582 | |
2583 | impl<'i, 's> FindSlice<(&'s str, &'s str, &'s str)> for &'i [u8] { |
2584 | #[inline (always)] |
2585 | fn find_slice(&self, substr: (&'s str, &'s str, &'s str)) -> Option<usize> { |
2586 | memmem3( |
2587 | self, |
2588 | ( |
2589 | substr.0.as_bytes(), |
2590 | substr.1.as_bytes(), |
2591 | substr.2.as_bytes(), |
2592 | ), |
2593 | ) |
2594 | } |
2595 | } |
2596 | |
2597 | impl<'i, 's> FindSlice<&'s str> for &'i str { |
2598 | #[inline (always)] |
2599 | fn find_slice(&self, substr: &'s str) -> Option<usize> { |
2600 | self.as_bytes().find_slice(substr) |
2601 | } |
2602 | } |
2603 | |
2604 | impl<'i, 's> FindSlice<(&'s str,)> for &'i str { |
2605 | #[inline (always)] |
2606 | fn find_slice(&self, substr: (&'s str,)) -> Option<usize> { |
2607 | self.as_bytes().find_slice(substr) |
2608 | } |
2609 | } |
2610 | |
2611 | impl<'i, 's> FindSlice<(&'s str, &'s str)> for &'i str { |
2612 | #[inline (always)] |
2613 | fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<usize> { |
2614 | self.as_bytes().find_slice(substr) |
2615 | } |
2616 | } |
2617 | |
2618 | impl<'i, 's> FindSlice<(&'s str, &'s str, &'s str)> for &'i str { |
2619 | #[inline (always)] |
2620 | fn find_slice(&self, substr: (&'s str, &'s str, &'s str)) -> Option<usize> { |
2621 | self.as_bytes().find_slice(substr) |
2622 | } |
2623 | } |
2624 | |
2625 | impl<'i> FindSlice<char> for &'i str { |
2626 | #[inline (always)] |
2627 | fn find_slice(&self, substr: char) -> Option<usize> { |
2628 | self.as_bytes().find_slice(substr) |
2629 | } |
2630 | } |
2631 | |
2632 | impl<'i> FindSlice<(char,)> for &'i str { |
2633 | #[inline (always)] |
2634 | fn find_slice(&self, substr: (char,)) -> Option<usize> { |
2635 | self.as_bytes().find_slice(substr) |
2636 | } |
2637 | } |
2638 | |
2639 | impl<'i> FindSlice<(char, char)> for &'i str { |
2640 | #[inline (always)] |
2641 | fn find_slice(&self, substr: (char, char)) -> Option<usize> { |
2642 | self.as_bytes().find_slice(substr) |
2643 | } |
2644 | } |
2645 | |
2646 | impl<'i> FindSlice<(char, char, char)> for &'i str { |
2647 | #[inline (always)] |
2648 | fn find_slice(&self, substr: (char, char, char)) -> Option<usize> { |
2649 | self.as_bytes().find_slice(substr) |
2650 | } |
2651 | } |
2652 | |
2653 | impl<'i> FindSlice<u8> for &'i str { |
2654 | #[inline (always)] |
2655 | fn find_slice(&self, substr: u8) -> Option<usize> { |
2656 | self.as_bytes().find_slice(substr) |
2657 | } |
2658 | } |
2659 | |
2660 | impl<'i> FindSlice<(u8,)> for &'i str { |
2661 | #[inline (always)] |
2662 | fn find_slice(&self, substr: (u8,)) -> Option<usize> { |
2663 | self.as_bytes().find_slice(substr) |
2664 | } |
2665 | } |
2666 | |
2667 | impl<'i> FindSlice<(u8, u8)> for &'i str { |
2668 | #[inline (always)] |
2669 | fn find_slice(&self, substr: (u8, u8)) -> Option<usize> { |
2670 | self.as_bytes().find_slice(substr) |
2671 | } |
2672 | } |
2673 | |
2674 | impl<'i> FindSlice<(u8, u8, u8)> for &'i str { |
2675 | #[inline (always)] |
2676 | fn find_slice(&self, substr: (u8, u8, u8)) -> Option<usize> { |
2677 | self.as_bytes().find_slice(substr) |
2678 | } |
2679 | } |
2680 | |
2681 | impl<'i, S> FindSlice<S> for &'i Bytes |
2682 | where |
2683 | &'i [u8]: FindSlice<S>, |
2684 | { |
2685 | #[inline (always)] |
2686 | fn find_slice(&self, substr: S) -> Option<usize> { |
2687 | let bytes: &[u8] = (*self).as_bytes(); |
2688 | let offset: Option = bytes.find_slice(substr); |
2689 | offset |
2690 | } |
2691 | } |
2692 | |
2693 | impl<'i, S> FindSlice<S> for &'i BStr |
2694 | where |
2695 | &'i [u8]: FindSlice<S>, |
2696 | { |
2697 | #[inline (always)] |
2698 | fn find_slice(&self, substr: S) -> Option<usize> { |
2699 | let bytes: &[u8] = (*self).as_bytes(); |
2700 | let offset: Option = bytes.find_slice(substr); |
2701 | offset |
2702 | } |
2703 | } |
2704 | |
2705 | impl<I, T> FindSlice<T> for Located<I> |
2706 | where |
2707 | I: FindSlice<T>, |
2708 | { |
2709 | #[inline (always)] |
2710 | fn find_slice(&self, substr: T) -> Option<usize> { |
2711 | self.input.find_slice(substr) |
2712 | } |
2713 | } |
2714 | |
2715 | #[cfg (feature = "unstable-recover" )] |
2716 | impl<I, E, T> FindSlice<T> for Recoverable<I, E> |
2717 | where |
2718 | I: Stream, |
2719 | I: FindSlice<T>, |
2720 | { |
2721 | #[inline (always)] |
2722 | fn find_slice(&self, substr: T) -> Option<usize> { |
2723 | self.input.find_slice(substr) |
2724 | } |
2725 | } |
2726 | |
2727 | impl<I, S, T> FindSlice<T> for Stateful<I, S> |
2728 | where |
2729 | I: FindSlice<T>, |
2730 | { |
2731 | #[inline (always)] |
2732 | fn find_slice(&self, substr: T) -> Option<usize> { |
2733 | self.input.find_slice(substr) |
2734 | } |
2735 | } |
2736 | |
2737 | impl<I, T> FindSlice<T> for Partial<I> |
2738 | where |
2739 | I: FindSlice<T>, |
2740 | { |
2741 | #[inline (always)] |
2742 | fn find_slice(&self, substr: T) -> Option<usize> { |
2743 | self.input.find_slice(substr) |
2744 | } |
2745 | } |
2746 | |
2747 | /// Used to integrate `str`'s `parse()` method |
2748 | pub trait ParseSlice<R> { |
2749 | /// Succeeds if `parse()` succeededThe |
2750 | /// |
2751 | /// The byte slice implementation will first convert it to a `&str`, then apply the `parse()` |
2752 | /// function |
2753 | fn parse_slice(&self) -> Option<R>; |
2754 | } |
2755 | |
2756 | impl<'a, R: FromStr> ParseSlice<R> for &'a [u8] { |
2757 | #[inline (always)] |
2758 | fn parse_slice(&self) -> Option<R> { |
2759 | from_utf8(self).ok().and_then(|s: &str| s.parse().ok()) |
2760 | } |
2761 | } |
2762 | |
2763 | impl<'a, R: FromStr> ParseSlice<R> for &'a str { |
2764 | #[inline (always)] |
2765 | fn parse_slice(&self) -> Option<R> { |
2766 | self.parse().ok() |
2767 | } |
2768 | } |
2769 | |
2770 | /// Convert a `Stream` into an appropriate `Output` type |
2771 | pub trait UpdateSlice: Stream { |
2772 | /// Convert an `Output` type to be used as `Stream` |
2773 | fn update_slice(self, inner: Self::Slice) -> Self; |
2774 | } |
2775 | |
2776 | impl<'a, T> UpdateSlice for &'a [T] |
2777 | where |
2778 | T: Clone + crate::lib::std::fmt::Debug, |
2779 | { |
2780 | #[inline (always)] |
2781 | fn update_slice(self, inner: Self::Slice) -> Self { |
2782 | inner |
2783 | } |
2784 | } |
2785 | |
2786 | impl<'a> UpdateSlice for &'a str { |
2787 | #[inline (always)] |
2788 | fn update_slice(self, inner: Self::Slice) -> Self { |
2789 | inner |
2790 | } |
2791 | } |
2792 | |
2793 | impl<'a> UpdateSlice for &'a Bytes { |
2794 | #[inline (always)] |
2795 | fn update_slice(self, inner: Self::Slice) -> Self { |
2796 | Bytes::new(bytes:inner) |
2797 | } |
2798 | } |
2799 | |
2800 | impl<'a> UpdateSlice for &'a BStr { |
2801 | #[inline (always)] |
2802 | fn update_slice(self, inner: Self::Slice) -> Self { |
2803 | BStr::new(bytes:inner) |
2804 | } |
2805 | } |
2806 | |
2807 | impl<I> UpdateSlice for Located<I> |
2808 | where |
2809 | I: UpdateSlice, |
2810 | { |
2811 | #[inline (always)] |
2812 | fn update_slice(mut self, inner: Self::Slice) -> Self { |
2813 | self.input = I::update_slice(self.input, inner); |
2814 | self |
2815 | } |
2816 | } |
2817 | |
2818 | #[cfg (feature = "unstable-recover" )] |
2819 | impl<I, E> UpdateSlice for Recoverable<I, E> |
2820 | where |
2821 | I: Stream, |
2822 | I: UpdateSlice, |
2823 | E: crate::lib::std::fmt::Debug, |
2824 | { |
2825 | #[inline (always)] |
2826 | fn update_slice(mut self, inner: Self::Slice) -> Self { |
2827 | self.input = I::update_slice(self.input, inner); |
2828 | self |
2829 | } |
2830 | } |
2831 | |
2832 | impl<I, S> UpdateSlice for Stateful<I, S> |
2833 | where |
2834 | I: UpdateSlice, |
2835 | S: Clone + crate::lib::std::fmt::Debug, |
2836 | { |
2837 | #[inline (always)] |
2838 | fn update_slice(mut self, inner: Self::Slice) -> Self { |
2839 | self.input = I::update_slice(self.input, inner); |
2840 | self |
2841 | } |
2842 | } |
2843 | |
2844 | impl<I> UpdateSlice for Partial<I> |
2845 | where |
2846 | I: UpdateSlice, |
2847 | { |
2848 | #[inline (always)] |
2849 | fn update_slice(self, inner: Self::Slice) -> Self { |
2850 | Partial { |
2851 | input: I::update_slice(self.input, inner), |
2852 | partial: self.partial, |
2853 | } |
2854 | } |
2855 | } |
2856 | |
2857 | /// Ensure checkpoint details are kept private |
2858 | #[derive (Copy, Clone, Debug)] |
2859 | pub struct Checkpoint<T>(T); |
2860 | |
2861 | /// A range bounded inclusively for counting parses performed |
2862 | #[derive (PartialEq, Eq)] |
2863 | pub struct Range { |
2864 | pub(crate) start_inclusive: usize, |
2865 | pub(crate) end_inclusive: Option<usize>, |
2866 | } |
2867 | |
2868 | impl Range { |
2869 | #[inline (always)] |
2870 | fn raw(start_inclusive: usize, end_inclusive: Option<usize>) -> Self { |
2871 | Self { |
2872 | start_inclusive, |
2873 | end_inclusive, |
2874 | } |
2875 | } |
2876 | } |
2877 | |
2878 | impl crate::lib::std::ops::RangeBounds<usize> for Range { |
2879 | #[inline (always)] |
2880 | fn start_bound(&self) -> crate::lib::std::ops::Bound<&usize> { |
2881 | crate::lib::std::ops::Bound::Included(&self.start_inclusive) |
2882 | } |
2883 | |
2884 | #[inline (always)] |
2885 | fn end_bound(&self) -> crate::lib::std::ops::Bound<&usize> { |
2886 | if let Some(end_inclusive: &usize) = &self.end_inclusive { |
2887 | crate::lib::std::ops::Bound::Included(end_inclusive) |
2888 | } else { |
2889 | crate::lib::std::ops::Bound::Unbounded |
2890 | } |
2891 | } |
2892 | } |
2893 | |
2894 | impl From<usize> for Range { |
2895 | #[inline (always)] |
2896 | fn from(fixed: usize) -> Self { |
2897 | (fixed..=fixed).into() |
2898 | } |
2899 | } |
2900 | |
2901 | impl From<crate::lib::std::ops::Range<usize>> for Range { |
2902 | #[inline (always)] |
2903 | fn from(range: crate::lib::std::ops::Range<usize>) -> Self { |
2904 | let start_inclusive: usize = range.start; |
2905 | let end_inclusive: Option = Some(range.end.saturating_sub(1)); |
2906 | Self::raw(start_inclusive, end_inclusive) |
2907 | } |
2908 | } |
2909 | |
2910 | impl From<crate::lib::std::ops::RangeFull> for Range { |
2911 | #[inline (always)] |
2912 | fn from(_: crate::lib::std::ops::RangeFull) -> Self { |
2913 | let start_inclusive: usize = 0; |
2914 | let end_inclusive: Option = None; |
2915 | Self::raw(start_inclusive, end_inclusive) |
2916 | } |
2917 | } |
2918 | |
2919 | impl From<crate::lib::std::ops::RangeFrom<usize>> for Range { |
2920 | #[inline (always)] |
2921 | fn from(range: crate::lib::std::ops::RangeFrom<usize>) -> Self { |
2922 | let start_inclusive: usize = range.start; |
2923 | let end_inclusive: Option = None; |
2924 | Self::raw(start_inclusive, end_inclusive) |
2925 | } |
2926 | } |
2927 | |
2928 | impl From<crate::lib::std::ops::RangeTo<usize>> for Range { |
2929 | #[inline (always)] |
2930 | fn from(range: crate::lib::std::ops::RangeTo<usize>) -> Self { |
2931 | let start_inclusive: usize = 0; |
2932 | let end_inclusive: Option = Some(range.end.saturating_sub(1)); |
2933 | Self::raw(start_inclusive, end_inclusive) |
2934 | } |
2935 | } |
2936 | |
2937 | impl From<crate::lib::std::ops::RangeInclusive<usize>> for Range { |
2938 | #[inline (always)] |
2939 | fn from(range: crate::lib::std::ops::RangeInclusive<usize>) -> Self { |
2940 | let start_inclusive: usize = *range.start(); |
2941 | let end_inclusive: Option = Some(*range.end()); |
2942 | Self::raw(start_inclusive, end_inclusive) |
2943 | } |
2944 | } |
2945 | |
2946 | impl From<crate::lib::std::ops::RangeToInclusive<usize>> for Range { |
2947 | #[inline (always)] |
2948 | fn from(range: crate::lib::std::ops::RangeToInclusive<usize>) -> Self { |
2949 | let start_inclusive: usize = 0; |
2950 | let end_inclusive: Option = Some(range.end); |
2951 | Self::raw(start_inclusive, end_inclusive) |
2952 | } |
2953 | } |
2954 | |
2955 | impl crate::lib::std::fmt::Display for Range { |
2956 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
2957 | self.start_inclusive.fmt(f)?; |
2958 | match self.end_inclusive { |
2959 | Some(e: usize) if e == self.start_inclusive => {} |
2960 | Some(e: usize) => { |
2961 | "..=" .fmt(f)?; |
2962 | e.fmt(f)?; |
2963 | } |
2964 | None => { |
2965 | ".." .fmt(f)?; |
2966 | } |
2967 | } |
2968 | Ok(()) |
2969 | } |
2970 | } |
2971 | |
2972 | impl crate::lib::std::fmt::Debug for Range { |
2973 | fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { |
2974 | write!(f, " {self}" ) |
2975 | } |
2976 | } |
2977 | |
2978 | /// Abstracts something which can extend an `Extend`. |
2979 | /// Used to build modified input slices in `escaped_transform` |
2980 | pub trait Accumulate<T>: Sized { |
2981 | /// Create a new `Extend` of the correct type |
2982 | fn initial(capacity: Option<usize>) -> Self; |
2983 | /// Accumulate the input into an accumulator |
2984 | fn accumulate(&mut self, acc: T); |
2985 | } |
2986 | |
2987 | impl<T> Accumulate<T> for () { |
2988 | #[inline (always)] |
2989 | fn initial(_capacity: Option<usize>) -> Self {} |
2990 | #[inline (always)] |
2991 | fn accumulate(&mut self, _acc: T) {} |
2992 | } |
2993 | |
2994 | impl<T> Accumulate<T> for usize { |
2995 | #[inline (always)] |
2996 | fn initial(_capacity: Option<usize>) -> Self { |
2997 | 0 |
2998 | } |
2999 | #[inline (always)] |
3000 | fn accumulate(&mut self, _acc: T) { |
3001 | *self += 1; |
3002 | } |
3003 | } |
3004 | |
3005 | #[cfg (feature = "alloc" )] |
3006 | impl<T> Accumulate<T> for Vec<T> { |
3007 | #[inline (always)] |
3008 | fn initial(capacity: Option<usize>) -> Self { |
3009 | match capacity { |
3010 | Some(capacity: usize) => Vec::with_capacity(clamp_capacity::<T>(capacity)), |
3011 | None => Vec::new(), |
3012 | } |
3013 | } |
3014 | #[inline (always)] |
3015 | fn accumulate(&mut self, acc: T) { |
3016 | self.push(acc); |
3017 | } |
3018 | } |
3019 | |
3020 | #[cfg (feature = "alloc" )] |
3021 | impl<'i, T: Clone> Accumulate<&'i [T]> for Vec<T> { |
3022 | #[inline (always)] |
3023 | fn initial(capacity: Option<usize>) -> Self { |
3024 | match capacity { |
3025 | Some(capacity: usize) => Vec::with_capacity(clamp_capacity::<T>(capacity)), |
3026 | None => Vec::new(), |
3027 | } |
3028 | } |
3029 | #[inline (always)] |
3030 | fn accumulate(&mut self, acc: &'i [T]) { |
3031 | self.extend(iter:acc.iter().cloned()); |
3032 | } |
3033 | } |
3034 | |
3035 | #[cfg (feature = "alloc" )] |
3036 | impl Accumulate<char> for String { |
3037 | #[inline (always)] |
3038 | fn initial(capacity: Option<usize>) -> Self { |
3039 | match capacity { |
3040 | Some(capacity: usize) => String::with_capacity(clamp_capacity::<char>(capacity)), |
3041 | None => String::new(), |
3042 | } |
3043 | } |
3044 | #[inline (always)] |
3045 | fn accumulate(&mut self, acc: char) { |
3046 | self.push(ch:acc); |
3047 | } |
3048 | } |
3049 | |
3050 | #[cfg (feature = "alloc" )] |
3051 | impl<'i> Accumulate<&'i str> for String { |
3052 | #[inline (always)] |
3053 | fn initial(capacity: Option<usize>) -> Self { |
3054 | match capacity { |
3055 | Some(capacity: usize) => String::with_capacity(clamp_capacity::<char>(capacity)), |
3056 | None => String::new(), |
3057 | } |
3058 | } |
3059 | #[inline (always)] |
3060 | fn accumulate(&mut self, acc: &'i str) { |
3061 | self.push_str(string:acc); |
3062 | } |
3063 | } |
3064 | |
3065 | #[cfg (feature = "alloc" )] |
3066 | impl<K, V> Accumulate<(K, V)> for BTreeMap<K, V> |
3067 | where |
3068 | K: crate::lib::std::cmp::Ord, |
3069 | { |
3070 | #[inline (always)] |
3071 | fn initial(_capacity: Option<usize>) -> Self { |
3072 | BTreeMap::new() |
3073 | } |
3074 | #[inline (always)] |
3075 | fn accumulate(&mut self, (key: K, value: V): (K, V)) { |
3076 | self.insert(key, value); |
3077 | } |
3078 | } |
3079 | |
3080 | #[cfg (feature = "std" )] |
3081 | impl<K, V, S> Accumulate<(K, V)> for HashMap<K, V, S> |
3082 | where |
3083 | K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash, |
3084 | S: BuildHasher + Default, |
3085 | { |
3086 | #[inline (always)] |
3087 | fn initial(capacity: Option<usize>) -> Self { |
3088 | let h: S = S::default(); |
3089 | match capacity { |
3090 | Some(capacity: usize) => { |
3091 | HashMap::with_capacity_and_hasher(capacity:clamp_capacity::<(K, V)>(capacity), hasher:h) |
3092 | } |
3093 | None => HashMap::with_hasher(hash_builder:h), |
3094 | } |
3095 | } |
3096 | #[inline (always)] |
3097 | fn accumulate(&mut self, (key: K, value: V): (K, V)) { |
3098 | self.insert(k:key, v:value); |
3099 | } |
3100 | } |
3101 | |
3102 | #[cfg (feature = "alloc" )] |
3103 | impl<K> Accumulate<K> for BTreeSet<K> |
3104 | where |
3105 | K: crate::lib::std::cmp::Ord, |
3106 | { |
3107 | #[inline (always)] |
3108 | fn initial(_capacity: Option<usize>) -> Self { |
3109 | BTreeSet::new() |
3110 | } |
3111 | #[inline (always)] |
3112 | fn accumulate(&mut self, key: K) { |
3113 | self.insert(key); |
3114 | } |
3115 | } |
3116 | |
3117 | #[cfg (feature = "std" )] |
3118 | impl<K, S> Accumulate<K> for HashSet<K, S> |
3119 | where |
3120 | K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash, |
3121 | S: BuildHasher + Default, |
3122 | { |
3123 | #[inline (always)] |
3124 | fn initial(capacity: Option<usize>) -> Self { |
3125 | let h: S = S::default(); |
3126 | match capacity { |
3127 | Some(capacity: usize) => HashSet::with_capacity_and_hasher(capacity:clamp_capacity::<K>(capacity), hasher:h), |
3128 | None => HashSet::with_hasher(h), |
3129 | } |
3130 | } |
3131 | #[inline (always)] |
3132 | fn accumulate(&mut self, key: K) { |
3133 | self.insert(key); |
3134 | } |
3135 | } |
3136 | |
3137 | #[cfg (feature = "alloc" )] |
3138 | #[inline ] |
3139 | pub(crate) fn clamp_capacity<T>(capacity: usize) -> usize { |
3140 | /// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`. |
3141 | /// |
3142 | /// Pre-allocating memory is a nice optimization but count fields can't |
3143 | /// always be trusted. We should clamp initial capacities to some reasonable |
3144 | /// amount. This reduces the risk of a bogus count value triggering a panic |
3145 | /// due to an OOM error. |
3146 | /// |
3147 | /// This does not affect correctness. `winnow` will always read the full number |
3148 | /// of elements regardless of the capacity cap. |
3149 | const MAX_INITIAL_CAPACITY_BYTES: usize = 65536; |
3150 | |
3151 | let max_initial_capacity: usize = |
3152 | MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::<T>().max(1); |
3153 | capacity.min(max_initial_capacity) |
3154 | } |
3155 | |
3156 | /// Helper trait to convert numbers to usize. |
3157 | /// |
3158 | /// By default, usize implements `From<u8>` and `From<u16>` but not |
3159 | /// `From<u32>` and `From<u64>` because that would be invalid on some |
3160 | /// platforms. This trait implements the conversion for platforms |
3161 | /// with 32 and 64 bits pointer platforms |
3162 | pub trait ToUsize { |
3163 | /// converts self to usize |
3164 | fn to_usize(&self) -> usize; |
3165 | } |
3166 | |
3167 | impl ToUsize for u8 { |
3168 | #[inline (always)] |
3169 | fn to_usize(&self) -> usize { |
3170 | *self as usize |
3171 | } |
3172 | } |
3173 | |
3174 | impl ToUsize for u16 { |
3175 | #[inline (always)] |
3176 | fn to_usize(&self) -> usize { |
3177 | *self as usize |
3178 | } |
3179 | } |
3180 | |
3181 | impl ToUsize for usize { |
3182 | #[inline (always)] |
3183 | fn to_usize(&self) -> usize { |
3184 | *self |
3185 | } |
3186 | } |
3187 | |
3188 | #[cfg (any(target_pointer_width = "32" , target_pointer_width = "64" ))] |
3189 | impl ToUsize for u32 { |
3190 | #[inline (always)] |
3191 | fn to_usize(&self) -> usize { |
3192 | *self as usize |
3193 | } |
3194 | } |
3195 | |
3196 | #[cfg (target_pointer_width = "64" )] |
3197 | impl ToUsize for u64 { |
3198 | #[inline (always)] |
3199 | fn to_usize(&self) -> usize { |
3200 | *self as usize |
3201 | } |
3202 | } |
3203 | |
3204 | /// Transforms a token into a char for basic string parsing |
3205 | #[allow (clippy::len_without_is_empty)] |
3206 | #[allow (clippy::wrong_self_convention)] |
3207 | pub trait AsChar { |
3208 | /// Makes a char from self |
3209 | /// |
3210 | /// # Example |
3211 | /// |
3212 | /// ``` |
3213 | /// use winnow::stream::AsChar as _; |
3214 | /// |
3215 | /// assert_eq!('a' .as_char(), 'a' ); |
3216 | /// assert_eq!(u8::MAX.as_char(), std::char::from_u32(u8::MAX as u32).unwrap()); |
3217 | /// ``` |
3218 | fn as_char(self) -> char; |
3219 | |
3220 | /// Tests that self is an alphabetic character |
3221 | /// |
3222 | /// **Warning:** for `&str` it recognizes alphabetic |
3223 | /// characters outside of the 52 ASCII letters |
3224 | fn is_alpha(self) -> bool; |
3225 | |
3226 | /// Tests that self is an alphabetic character |
3227 | /// or a decimal digit |
3228 | fn is_alphanum(self) -> bool; |
3229 | /// Tests that self is a decimal digit |
3230 | fn is_dec_digit(self) -> bool; |
3231 | /// Tests that self is an hex digit |
3232 | fn is_hex_digit(self) -> bool; |
3233 | /// Tests that self is an octal digit |
3234 | fn is_oct_digit(self) -> bool; |
3235 | /// Gets the len in bytes for self |
3236 | fn len(self) -> usize; |
3237 | /// Tests that self is ASCII space or tab |
3238 | fn is_space(self) -> bool; |
3239 | /// Tests if byte is ASCII newline: \n |
3240 | fn is_newline(self) -> bool; |
3241 | } |
3242 | |
3243 | impl AsChar for u8 { |
3244 | #[inline (always)] |
3245 | fn as_char(self) -> char { |
3246 | self as char |
3247 | } |
3248 | #[inline ] |
3249 | fn is_alpha(self) -> bool { |
3250 | matches!(self, 0x41..=0x5A | 0x61..=0x7A) |
3251 | } |
3252 | #[inline ] |
3253 | fn is_alphanum(self) -> bool { |
3254 | self.is_alpha() || self.is_dec_digit() |
3255 | } |
3256 | #[inline ] |
3257 | fn is_dec_digit(self) -> bool { |
3258 | matches!(self, 0x30..=0x39) |
3259 | } |
3260 | #[inline ] |
3261 | fn is_hex_digit(self) -> bool { |
3262 | matches!(self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) |
3263 | } |
3264 | #[inline ] |
3265 | fn is_oct_digit(self) -> bool { |
3266 | matches!(self, 0x30..=0x37) |
3267 | } |
3268 | #[inline ] |
3269 | fn len(self) -> usize { |
3270 | 1 |
3271 | } |
3272 | #[inline ] |
3273 | fn is_space(self) -> bool { |
3274 | self == b' ' || self == b' \t' |
3275 | } |
3276 | #[inline ] |
3277 | fn is_newline(self) -> bool { |
3278 | self == b' \n' |
3279 | } |
3280 | } |
3281 | |
3282 | impl<'a> AsChar for &'a u8 { |
3283 | #[inline (always)] |
3284 | fn as_char(self) -> char { |
3285 | *self as char |
3286 | } |
3287 | #[inline ] |
3288 | fn is_alpha(self) -> bool { |
3289 | matches!(*self, 0x41..=0x5A | 0x61..=0x7A) |
3290 | } |
3291 | #[inline ] |
3292 | fn is_alphanum(self) -> bool { |
3293 | self.is_alpha() || self.is_dec_digit() |
3294 | } |
3295 | #[inline ] |
3296 | fn is_dec_digit(self) -> bool { |
3297 | matches!(*self, 0x30..=0x39) |
3298 | } |
3299 | #[inline ] |
3300 | fn is_hex_digit(self) -> bool { |
3301 | matches!(*self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) |
3302 | } |
3303 | #[inline ] |
3304 | fn is_oct_digit(self) -> bool { |
3305 | matches!(*self, 0x30..=0x37) |
3306 | } |
3307 | #[inline ] |
3308 | fn len(self) -> usize { |
3309 | 1 |
3310 | } |
3311 | #[inline ] |
3312 | fn is_space(self) -> bool { |
3313 | *self == b' ' || *self == b' \t' |
3314 | } |
3315 | #[inline ] |
3316 | fn is_newline(self) -> bool { |
3317 | *self == b' \n' |
3318 | } |
3319 | } |
3320 | |
3321 | impl AsChar for char { |
3322 | #[inline (always)] |
3323 | fn as_char(self) -> char { |
3324 | self |
3325 | } |
3326 | #[inline ] |
3327 | fn is_alpha(self) -> bool { |
3328 | self.is_ascii_alphabetic() |
3329 | } |
3330 | #[inline ] |
3331 | fn is_alphanum(self) -> bool { |
3332 | self.is_alpha() || self.is_dec_digit() |
3333 | } |
3334 | #[inline ] |
3335 | fn is_dec_digit(self) -> bool { |
3336 | self.is_ascii_digit() |
3337 | } |
3338 | #[inline ] |
3339 | fn is_hex_digit(self) -> bool { |
3340 | self.is_ascii_hexdigit() |
3341 | } |
3342 | #[inline ] |
3343 | fn is_oct_digit(self) -> bool { |
3344 | self.is_digit(8) |
3345 | } |
3346 | #[inline ] |
3347 | fn len(self) -> usize { |
3348 | self.len_utf8() |
3349 | } |
3350 | #[inline ] |
3351 | fn is_space(self) -> bool { |
3352 | self == ' ' || self == ' \t' |
3353 | } |
3354 | #[inline ] |
3355 | fn is_newline(self) -> bool { |
3356 | self == ' \n' |
3357 | } |
3358 | } |
3359 | |
3360 | impl<'a> AsChar for &'a char { |
3361 | #[inline (always)] |
3362 | fn as_char(self) -> char { |
3363 | *self |
3364 | } |
3365 | #[inline ] |
3366 | fn is_alpha(self) -> bool { |
3367 | self.is_ascii_alphabetic() |
3368 | } |
3369 | #[inline ] |
3370 | fn is_alphanum(self) -> bool { |
3371 | self.is_alpha() || self.is_dec_digit() |
3372 | } |
3373 | #[inline ] |
3374 | fn is_dec_digit(self) -> bool { |
3375 | self.is_ascii_digit() |
3376 | } |
3377 | #[inline ] |
3378 | fn is_hex_digit(self) -> bool { |
3379 | self.is_ascii_hexdigit() |
3380 | } |
3381 | #[inline ] |
3382 | fn is_oct_digit(self) -> bool { |
3383 | self.is_digit(8) |
3384 | } |
3385 | #[inline ] |
3386 | fn len(self) -> usize { |
3387 | self.len_utf8() |
3388 | } |
3389 | #[inline ] |
3390 | fn is_space(self) -> bool { |
3391 | *self == ' ' || *self == ' \t' |
3392 | } |
3393 | #[inline ] |
3394 | fn is_newline(self) -> bool { |
3395 | *self == ' \n' |
3396 | } |
3397 | } |
3398 | |
3399 | /// Check if a token in in a set of possible tokens |
3400 | /// |
3401 | /// This is generally implemented on patterns that a token may match and supports `u8` and `char` |
3402 | /// tokens along with the following patterns |
3403 | /// - `b'c'` and `'c'` |
3404 | /// - `b""` and `""` |
3405 | /// - `|c| true` |
3406 | /// - `b'a'..=b'z'`, `'a'..='z'` (etc for each [range type][std::ops]) |
3407 | /// - `(pattern1, pattern2, ...)` |
3408 | /// |
3409 | /// # Example |
3410 | /// |
3411 | /// For example, you could implement `hex_digit0` as: |
3412 | /// ``` |
3413 | /// # use winnow::prelude::*; |
3414 | /// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; |
3415 | /// # use winnow::token::take_while; |
3416 | /// fn hex_digit1<'s>(input: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> { |
3417 | /// take_while(1.., ('a' ..='f' , 'A' ..='F' , '0' ..='9' )).parse_next(input) |
3418 | /// } |
3419 | /// |
3420 | /// assert_eq!(hex_digit1.parse_peek("21cZ" ), Ok(("Z" , "21c" ))); |
3421 | /// assert_eq!(hex_digit1.parse_peek("H2" ), Err(ErrMode::Backtrack(InputError::new("H2" , ErrorKind::Slice)))); |
3422 | /// assert_eq!(hex_digit1.parse_peek("" ), Err(ErrMode::Backtrack(InputError::new("" , ErrorKind::Slice)))); |
3423 | /// ``` |
3424 | pub trait ContainsToken<T> { |
3425 | /// Returns true if self contains the token |
3426 | fn contains_token(&self, token: T) -> bool; |
3427 | } |
3428 | |
3429 | impl ContainsToken<u8> for u8 { |
3430 | #[inline (always)] |
3431 | fn contains_token(&self, token: u8) -> bool { |
3432 | *self == token |
3433 | } |
3434 | } |
3435 | |
3436 | impl<'a> ContainsToken<&'a u8> for u8 { |
3437 | #[inline (always)] |
3438 | fn contains_token(&self, token: &u8) -> bool { |
3439 | self.contains_token(*token) |
3440 | } |
3441 | } |
3442 | |
3443 | impl ContainsToken<char> for u8 { |
3444 | #[inline (always)] |
3445 | fn contains_token(&self, token: char) -> bool { |
3446 | self.as_char() == token |
3447 | } |
3448 | } |
3449 | |
3450 | impl<'a> ContainsToken<&'a char> for u8 { |
3451 | #[inline (always)] |
3452 | fn contains_token(&self, token: &char) -> bool { |
3453 | self.contains_token(*token) |
3454 | } |
3455 | } |
3456 | |
3457 | impl<C: AsChar> ContainsToken<C> for char { |
3458 | #[inline (always)] |
3459 | fn contains_token(&self, token: C) -> bool { |
3460 | *self == token.as_char() |
3461 | } |
3462 | } |
3463 | |
3464 | impl<C, F: Fn(C) -> bool> ContainsToken<C> for F { |
3465 | #[inline (always)] |
3466 | fn contains_token(&self, token: C) -> bool { |
3467 | self(token) |
3468 | } |
3469 | } |
3470 | |
3471 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for crate::lib::std::ops::Range<C2> { |
3472 | #[inline (always)] |
3473 | fn contains_token(&self, token: C1) -> bool { |
3474 | let start: char = self.start.clone().as_char(); |
3475 | let end: char = self.end.clone().as_char(); |
3476 | (start..end).contains(&token.as_char()) |
3477 | } |
3478 | } |
3479 | |
3480 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> |
3481 | for crate::lib::std::ops::RangeInclusive<C2> |
3482 | { |
3483 | #[inline (always)] |
3484 | fn contains_token(&self, token: C1) -> bool { |
3485 | let start: char = self.start().clone().as_char(); |
3486 | let end: char = self.end().clone().as_char(); |
3487 | (start..=end).contains(&token.as_char()) |
3488 | } |
3489 | } |
3490 | |
3491 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for crate::lib::std::ops::RangeFrom<C2> { |
3492 | #[inline (always)] |
3493 | fn contains_token(&self, token: C1) -> bool { |
3494 | let start: char = self.start.clone().as_char(); |
3495 | (start..).contains(&token.as_char()) |
3496 | } |
3497 | } |
3498 | |
3499 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> for crate::lib::std::ops::RangeTo<C2> { |
3500 | #[inline (always)] |
3501 | fn contains_token(&self, token: C1) -> bool { |
3502 | let end: char = self.end.clone().as_char(); |
3503 | (..end).contains(&token.as_char()) |
3504 | } |
3505 | } |
3506 | |
3507 | impl<C1: AsChar, C2: AsChar + Clone> ContainsToken<C1> |
3508 | for crate::lib::std::ops::RangeToInclusive<C2> |
3509 | { |
3510 | #[inline (always)] |
3511 | fn contains_token(&self, token: C1) -> bool { |
3512 | let end: char = self.end.clone().as_char(); |
3513 | (..=end).contains(&token.as_char()) |
3514 | } |
3515 | } |
3516 | |
3517 | impl<C1: AsChar> ContainsToken<C1> for crate::lib::std::ops::RangeFull { |
3518 | #[inline (always)] |
3519 | fn contains_token(&self, _token: C1) -> bool { |
3520 | true |
3521 | } |
3522 | } |
3523 | |
3524 | impl<C: AsChar> ContainsToken<C> for &'_ [u8] { |
3525 | #[inline ] |
3526 | fn contains_token(&self, token: C) -> bool { |
3527 | let token: char = token.as_char(); |
3528 | self.iter().any(|t: &u8| t.as_char() == token) |
3529 | } |
3530 | } |
3531 | |
3532 | impl<C: AsChar> ContainsToken<C> for &'_ [char] { |
3533 | #[inline ] |
3534 | fn contains_token(&self, token: C) -> bool { |
3535 | let token: char = token.as_char(); |
3536 | self.iter().any(|t: &char| *t == token) |
3537 | } |
3538 | } |
3539 | |
3540 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for &'_ [u8; LEN] { |
3541 | #[inline ] |
3542 | fn contains_token(&self, token: C) -> bool { |
3543 | let token: char = token.as_char(); |
3544 | self.iter().any(|t: &u8| t.as_char() == token) |
3545 | } |
3546 | } |
3547 | |
3548 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for &'_ [char; LEN] { |
3549 | #[inline ] |
3550 | fn contains_token(&self, token: C) -> bool { |
3551 | let token: char = token.as_char(); |
3552 | self.iter().any(|t: &char| *t == token) |
3553 | } |
3554 | } |
3555 | |
3556 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for [u8; LEN] { |
3557 | #[inline ] |
3558 | fn contains_token(&self, token: C) -> bool { |
3559 | let token: char = token.as_char(); |
3560 | self.iter().any(|t: &u8| t.as_char() == token) |
3561 | } |
3562 | } |
3563 | |
3564 | impl<const LEN: usize, C: AsChar> ContainsToken<C> for [char; LEN] { |
3565 | #[inline ] |
3566 | fn contains_token(&self, token: C) -> bool { |
3567 | let token: char = token.as_char(); |
3568 | self.iter().any(|t: &char| *t == token) |
3569 | } |
3570 | } |
3571 | |
3572 | impl<T> ContainsToken<T> for () { |
3573 | #[inline (always)] |
3574 | fn contains_token(&self, _token: T) -> bool { |
3575 | false |
3576 | } |
3577 | } |
3578 | |
3579 | macro_rules! impl_contains_token_for_tuple { |
3580 | ($($haystack:ident),+) => ( |
3581 | #[allow(non_snake_case)] |
3582 | impl<T, $($haystack),+> ContainsToken<T> for ($($haystack),+,) |
3583 | where |
3584 | T: Clone, |
3585 | $($haystack: ContainsToken<T>),+ |
3586 | { |
3587 | #[inline] |
3588 | fn contains_token(&self, token: T) -> bool { |
3589 | let ($(ref $haystack),+,) = *self; |
3590 | $($haystack.contains_token(token.clone()) || )+ false |
3591 | } |
3592 | } |
3593 | ) |
3594 | } |
3595 | |
3596 | macro_rules! impl_contains_token_for_tuples { |
3597 | ($haystack1:ident, $($haystack:ident),+) => { |
3598 | impl_contains_token_for_tuples!(__impl $haystack1; $($haystack),+); |
3599 | }; |
3600 | (__impl $($haystack:ident),+; $haystack1:ident $(,$haystack2:ident)*) => { |
3601 | impl_contains_token_for_tuple!($($haystack),+); |
3602 | impl_contains_token_for_tuples!(__impl $($haystack),+, $haystack1; $($haystack2),*); |
3603 | }; |
3604 | (__impl $($haystack:ident),+;) => { |
3605 | impl_contains_token_for_tuple!($($haystack),+); |
3606 | } |
3607 | } |
3608 | |
3609 | impl_contains_token_for_tuples!( |
3610 | F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21 |
3611 | ); |
3612 | |
3613 | #[cfg (feature = "simd" )] |
3614 | #[inline (always)] |
3615 | fn memchr(token: u8, slice: &[u8]) -> Option<usize> { |
3616 | memchr::memchr(token, slice) |
3617 | } |
3618 | |
3619 | #[cfg (feature = "simd" )] |
3620 | #[inline (always)] |
3621 | fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> { |
3622 | memchr::memchr2(token.0, token.1, slice) |
3623 | } |
3624 | |
3625 | #[cfg (feature = "simd" )] |
3626 | #[inline (always)] |
3627 | fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> { |
3628 | memchr::memchr3(token.0, token.1, token.2, slice) |
3629 | } |
3630 | |
3631 | #[cfg (not(feature = "simd" ))] |
3632 | #[inline (always)] |
3633 | fn memchr(token: u8, slice: &[u8]) -> Option<usize> { |
3634 | slice.iter().position(|t: &u8| *t == token) |
3635 | } |
3636 | |
3637 | #[cfg (not(feature = "simd" ))] |
3638 | #[inline (always)] |
3639 | fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> { |
3640 | slice.iter().position(|t: &u8| *t == token.0 || *t == token.1) |
3641 | } |
3642 | |
3643 | #[cfg (not(feature = "simd" ))] |
3644 | #[inline (always)] |
3645 | fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> { |
3646 | sliceIter<'_, u8> |
3647 | .iter() |
3648 | .position(|t: &u8| *t == token.0 || *t == token.1 || *t == token.2) |
3649 | } |
3650 | |
3651 | #[inline (always)] |
3652 | fn memmem(slice: &[u8], tag: &[u8]) -> Option<usize> { |
3653 | if tag.len() == 1 { |
3654 | memchr(token:tag[0], slice) |
3655 | } else { |
3656 | memmem_(slice, tag) |
3657 | } |
3658 | } |
3659 | |
3660 | #[inline (always)] |
3661 | fn memmem2(slice: &[u8], tag: (&[u8], &[u8])) -> Option<usize> { |
3662 | if tag.0.len() == 1 && tag.1.len() == 1 { |
3663 | memchr2((tag.0[0], tag.1[0]), slice) |
3664 | } else { |
3665 | memmem2_(slice, tag) |
3666 | } |
3667 | } |
3668 | |
3669 | #[inline (always)] |
3670 | fn memmem3(slice: &[u8], tag: (&[u8], &[u8], &[u8])) -> Option<usize> { |
3671 | if tag.0.len() == 1 && tag.1.len() == 1 && tag.2.len() == 1 { |
3672 | memchr3((tag.0[0], tag.1[0], tag.2[0]), slice) |
3673 | } else { |
3674 | memmem3_(slice, tag) |
3675 | } |
3676 | } |
3677 | |
3678 | #[cfg (feature = "simd" )] |
3679 | #[inline (always)] |
3680 | fn memmem_(slice: &[u8], tag: &[u8]) -> Option<usize> { |
3681 | let &prefix = match tag.first() { |
3682 | Some(x) => x, |
3683 | None => return Some(0), |
3684 | }; |
3685 | #[allow (clippy::manual_find)] // faster this way |
3686 | for i in memchr::memchr_iter(prefix, slice) { |
3687 | if slice[i..].starts_with(tag) { |
3688 | return Some(i); |
3689 | } |
3690 | } |
3691 | None |
3692 | } |
3693 | |
3694 | #[cfg (feature = "simd" )] |
3695 | fn memmem2_(slice: &[u8], tag: (&[u8], &[u8])) -> Option<usize> { |
3696 | let prefix = match (tag.0.first(), tag.1.first()) { |
3697 | (Some(&a), Some(&b)) => (a, b), |
3698 | _ => return Some(0), |
3699 | }; |
3700 | #[allow (clippy::manual_find)] // faster this way |
3701 | for i in memchr::memchr2_iter(prefix.0, prefix.1, slice) { |
3702 | let subslice = &slice[i..]; |
3703 | if subslice.starts_with(tag.0) { |
3704 | return Some(i); |
3705 | } |
3706 | if subslice.starts_with(tag.1) { |
3707 | return Some(i); |
3708 | } |
3709 | } |
3710 | None |
3711 | } |
3712 | |
3713 | #[cfg (feature = "simd" )] |
3714 | fn memmem3_(slice: &[u8], tag: (&[u8], &[u8], &[u8])) -> Option<usize> { |
3715 | let prefix = match (tag.0.first(), tag.1.first(), tag.2.first()) { |
3716 | (Some(&a), Some(&b), Some(&c)) => (a, b, c), |
3717 | _ => return Some(0), |
3718 | }; |
3719 | #[allow (clippy::manual_find)] // faster this way |
3720 | for i in memchr::memchr3_iter(prefix.0, prefix.1, prefix.2, slice) { |
3721 | let subslice = &slice[i..]; |
3722 | if subslice.starts_with(tag.0) { |
3723 | return Some(i); |
3724 | } |
3725 | if subslice.starts_with(tag.1) { |
3726 | return Some(i); |
3727 | } |
3728 | if subslice.starts_with(tag.2) { |
3729 | return Some(i); |
3730 | } |
3731 | } |
3732 | None |
3733 | } |
3734 | |
3735 | #[cfg (not(feature = "simd" ))] |
3736 | fn memmem_(slice: &[u8], tag: &[u8]) -> Option<usize> { |
3737 | for i: usize in 0..slice.len() { |
3738 | let subslice: &[u8] = &slice[i..]; |
3739 | if subslice.starts_with(needle:tag) { |
3740 | return Some(i); |
3741 | } |
3742 | } |
3743 | None |
3744 | } |
3745 | |
3746 | #[cfg (not(feature = "simd" ))] |
3747 | fn memmem2_(slice: &[u8], tag: (&[u8], &[u8])) -> Option<usize> { |
3748 | for i: usize in 0..slice.len() { |
3749 | let subslice: &[u8] = &slice[i..]; |
3750 | if subslice.starts_with(needle:tag.0) { |
3751 | return Some(i); |
3752 | } |
3753 | if subslice.starts_with(needle:tag.1) { |
3754 | return Some(i); |
3755 | } |
3756 | } |
3757 | None |
3758 | } |
3759 | |
3760 | #[cfg (not(feature = "simd" ))] |
3761 | fn memmem3_(slice: &[u8], tag: (&[u8], &[u8], &[u8])) -> Option<usize> { |
3762 | for i: usize in 0..slice.len() { |
3763 | let subslice: &[u8] = &slice[i..]; |
3764 | if subslice.starts_with(needle:tag.0) { |
3765 | return Some(i); |
3766 | } |
3767 | if subslice.starts_with(needle:tag.1) { |
3768 | return Some(i); |
3769 | } |
3770 | if subslice.starts_with(needle:tag.2) { |
3771 | return Some(i); |
3772 | } |
3773 | } |
3774 | None |
3775 | } |
3776 | |