diff options
Diffstat (limited to 'vendor/winnow/src/stream/mod.rs')
-rw-r--r-- | vendor/winnow/src/stream/mod.rs | 621 |
1 files changed, 372 insertions, 249 deletions
diff --git a/vendor/winnow/src/stream/mod.rs b/vendor/winnow/src/stream/mod.rs index 3d7a41e09..fcacbd78f 100644 --- a/vendor/winnow/src/stream/mod.rs +++ b/vendor/winnow/src/stream/mod.rs @@ -11,13 +11,16 @@ use core::num::NonZeroUsize; -use crate::error::{ErrMode, ErrorKind, Needed, ParseError}; +use crate::error::Needed; use crate::lib::std::iter::{Cloned, Enumerate}; use crate::lib::std::slice::Iter; use crate::lib::std::str::from_utf8; use crate::lib::std::str::CharIndices; use crate::lib::std::str::FromStr; -use crate::IResult; + +#[allow(unused_imports)] +#[cfg(feature = "unstable-doc")] +use crate::error::ErrMode; #[cfg(feature = "alloc")] use crate::lib::std::collections::BTreeMap; @@ -103,7 +106,7 @@ where } fn location(&self) -> usize { - self.initial.offset_to(&self.input) + self.input.offset_from(&self.initial) } } @@ -156,9 +159,9 @@ impl<I: crate::lib::std::fmt::Display> crate::lib::std::fmt::Display for Located /// /// type Stream<'is> = Stateful<&'is str, State<'is>>; /// -/// fn word(i: Stream<'_>) -> IResult<Stream<'_>, &str> { +/// fn word<'s>(i: &mut Stream<'s>) -> PResult<&'s str> { /// i.state.count(); -/// alpha1(i) +/// alpha1.parse_next(i) /// } /// /// let data = "Hello"; @@ -218,48 +221,48 @@ impl<I: crate::lib::std::fmt::Display, S> crate::lib::std::fmt::Display for Stat /// Here is how it works in practice: /// /// ```rust -/// # use winnow::{IResult, error::ErrMode, error::Needed, error::{Error, ErrorKind}, token, ascii, stream::Partial}; +/// # use winnow::{PResult, error::ErrMode, error::Needed, error::{InputError, ErrorKind}, token, ascii, stream::Partial}; /// # use winnow::prelude::*; /// -/// fn take_partial(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> { +/// fn take_partial<'s>(i: &mut Partial<&'s [u8]>) -> PResult<&'s [u8], InputError<Partial<&'s [u8]>>> { /// token::take(4u8).parse_next(i) /// } /// -/// fn take_complete(i: &[u8]) -> IResult<&[u8], &[u8]> { +/// fn take_complete<'s>(i: &mut &'s [u8]) -> PResult<&'s [u8], InputError<&'s [u8]>> { /// token::take(4u8).parse_next(i) /// } /// /// // both parsers will take 4 bytes as expected -/// assert_eq!(take_partial(Partial::new(&b"abcde"[..])), Ok((Partial::new(&b"e"[..]), &b"abcd"[..]))); -/// assert_eq!(take_complete(&b"abcde"[..]), Ok((&b"e"[..], &b"abcd"[..]))); +/// assert_eq!(take_partial.parse_peek(Partial::new(&b"abcde"[..])), Ok((Partial::new(&b"e"[..]), &b"abcd"[..]))); +/// assert_eq!(take_complete.parse_peek(&b"abcde"[..]), Ok((&b"e"[..], &b"abcd"[..]))); /// /// // if the input is smaller than 4 bytes, the partial parser /// // will return `Incomplete` to indicate that we need more data -/// assert_eq!(take_partial(Partial::new(&b"abc"[..])), Err(ErrMode::Incomplete(Needed::new(1)))); +/// assert_eq!(take_partial.parse_peek(Partial::new(&b"abc"[..])), Err(ErrMode::Incomplete(Needed::new(1)))); /// /// // but the complete parser will return an error -/// assert_eq!(take_complete(&b"abc"[..]), Err(ErrMode::Backtrack(Error::new(&b"abc"[..], ErrorKind::Slice)))); +/// assert_eq!(take_complete.parse_peek(&b"abc"[..]), Err(ErrMode::Backtrack(InputError::new(&b"abc"[..], ErrorKind::Slice)))); /// /// // the alpha0 function recognizes 0 or more alphabetic characters -/// fn alpha0_partial(i: Partial<&str>) -> IResult<Partial<&str>, &str> { -/// ascii::alpha0(i) +/// fn alpha0_partial<'s>(i: &mut Partial<&'s str>) -> PResult<&'s str, InputError<Partial<&'s str>>> { +/// ascii::alpha0.parse_next(i) /// } /// -/// fn alpha0_complete(i: &str) -> IResult<&str, &str> { -/// ascii::alpha0(i) +/// fn alpha0_complete<'s>(i: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> { +/// ascii::alpha0.parse_next(i) /// } /// /// // if there's a clear limit to the recognized characters, both parsers work the same way -/// assert_eq!(alpha0_partial(Partial::new("abcd;")), Ok((Partial::new(";"), "abcd"))); -/// assert_eq!(alpha0_complete("abcd;"), Ok((";", "abcd"))); +/// assert_eq!(alpha0_partial.parse_peek(Partial::new("abcd;")), Ok((Partial::new(";"), "abcd"))); +/// assert_eq!(alpha0_complete.parse_peek("abcd;"), Ok((";", "abcd"))); /// /// // but when there's no limit, the partial version returns `Incomplete`, because it cannot /// // know if more input data should be recognized. The whole input could be "abcd;", or /// // "abcde;" -/// assert_eq!(alpha0_partial(Partial::new("abcd")), Err(ErrMode::Incomplete(Needed::new(1)))); +/// assert_eq!(alpha0_partial.parse_peek(Partial::new("abcd")), Err(ErrMode::Incomplete(Needed::new(1)))); /// /// // while the complete version knows that all of the data is there -/// assert_eq!(alpha0_complete("abcd"), Ok(("", "abcd"))); +/// assert_eq!(alpha0_complete.parse_peek("abcd"), Ok(("", "abcd"))); /// ``` #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Partial<I> { @@ -402,7 +405,7 @@ where } /// Core definition for parser input state -pub trait Stream: Offset + Clone + crate::lib::std::fmt::Debug { +pub trait Stream: Offset<<Self as Stream>::Checkpoint> + crate::lib::std::fmt::Debug { /// The smallest unit being parsed /// /// Example: `u8` for `&[u8]` or `char` for `&str` @@ -415,13 +418,26 @@ pub trait Stream: Offset + Clone + crate::lib::std::fmt::Debug { /// Iterate with the offset from the current location type IterOffsets: Iterator<Item = (usize, Self::Token)>; + /// A parse location within the stream + type Checkpoint: Offset + Clone + crate::lib::std::fmt::Debug; + /// Iterate with the offset from the current location fn iter_offsets(&self) -> Self::IterOffsets; /// Returns the offaet to the end of the input fn eof_offset(&self) -> usize; /// Split off the next token from the input - fn next_token(&self) -> Option<(Self, Self::Token)>; + fn next_token(&mut self) -> Option<Self::Token>; + /// Split off the next token from the input + #[inline(always)] + fn peek_token(&self) -> Option<(Self, Self::Token)> + where + Self: Clone, + { + let mut peek = self.clone(); + let token = peek.next_token()?; + Some((peek, token)) + } /// Finds the offset of the next matching token fn offset_for<P>(&self, predicate: P) -> Option<usize> @@ -448,7 +464,45 @@ pub trait Stream: Offset + Clone + crate::lib::std::fmt::Debug { /// * Indexes must uphold invariants of the stream, like for `str` they must lie on UTF-8 /// sequence boundaries. /// - fn next_slice(&self, offset: usize) -> (Self, Self::Slice); + fn next_slice(&mut self, offset: usize) -> Self::Slice; + /// Split off a slice of tokens from the input + #[inline(always)] + fn peek_slice(&self, offset: usize) -> (Self, Self::Slice) + where + Self: Clone, + { + let mut peek = self.clone(); + let slice = peek.next_slice(offset); + (peek, slice) + } + + /// Advance to the end of the stream + #[inline(always)] + fn finish(&mut self) -> Self::Slice { + self.next_slice(self.eof_offset()) + } + /// Advance to the end of the stream + #[inline(always)] + fn peek_finish(&self) -> (Self, Self::Slice) + where + Self: Clone, + { + let mut peek = self.clone(); + let slice = peek.finish(); + (peek, slice) + } + + /// Save the current parse location within the stream + fn checkpoint(&self) -> Self::Checkpoint; + /// Revert the stream to a prior [`Self::Checkpoint`] + /// + /// # Panic + /// + /// May panic if an invalid [`Self::Checkpoint`] is provided + fn reset(&mut self, checkpoint: Self::Checkpoint); + + /// Return the inner-most stream + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug; } impl<'i, T> Stream for &'i [T] @@ -460,6 +514,8 @@ where type IterOffsets = Enumerate<Cloned<Iter<'i, T>>>; + type Checkpoint = Checkpoint<Self>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { self.iter().cloned().enumerate() @@ -470,9 +526,10 @@ where } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - self.split_first() - .map(|(token, next)| (next, token.clone())) + fn next_token(&mut self) -> Option<Self::Token> { + let (token, next) = self.split_first()?; + *self = next; + Some(token.clone()) } #[inline(always)] @@ -491,9 +548,24 @@ where } } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + fn next_slice(&mut self, offset: usize) -> Self::Slice { let (slice, next) = self.split_at(offset); - (next, slice) + *self = next; + slice + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint(*self) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + *self = checkpoint.0; + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + self } } @@ -503,6 +575,8 @@ impl<'i> Stream for &'i str { type IterOffsets = CharIndices<'i>; + type Checkpoint = Checkpoint<Self>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { self.char_indices() @@ -513,10 +587,11 @@ impl<'i> Stream for &'i str { } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { + fn next_token(&mut self) -> Option<Self::Token> { let c = self.chars().next()?; let offset = c.len(); - Some((&self[offset..], c)) + *self = &self[offset..]; + Some(c) } #[inline(always)] @@ -548,9 +623,24 @@ impl<'i> Stream for &'i str { } } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + fn next_slice(&mut self, offset: usize) -> Self::Slice { let (slice, next) = self.split_at(offset); - (next, slice) + *self = next; + slice + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint(*self) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + *self = checkpoint.0; + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + self } } @@ -560,6 +650,8 @@ impl<'i> Stream for &'i Bytes { type IterOffsets = Enumerate<Cloned<Iter<'i, u8>>>; + type Checkpoint = Checkpoint<Self>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { self.iter().cloned().enumerate() @@ -570,11 +662,13 @@ impl<'i> Stream for &'i Bytes { } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { + fn next_token(&mut self) -> Option<Self::Token> { if self.is_empty() { None } else { - Some((Bytes::from_bytes(&self[1..]), self[0])) + let token = self[0]; + *self = &self[1..]; + Some(token) } } @@ -594,9 +688,24 @@ impl<'i> Stream for &'i Bytes { } } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = (&self.0).next_slice(offset); - (Bytes::from_bytes(next), slice) + fn next_slice(&mut self, offset: usize) -> Self::Slice { + let (slice, next) = self.0.split_at(offset); + *self = Bytes::from_bytes(next); + slice + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint(*self) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + *self = checkpoint.0; + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + self } } @@ -606,6 +715,8 @@ impl<'i> Stream for &'i BStr { type IterOffsets = Enumerate<Cloned<Iter<'i, u8>>>; + type Checkpoint = Checkpoint<Self>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { self.iter().cloned().enumerate() @@ -616,11 +727,13 @@ impl<'i> Stream for &'i BStr { } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { + fn next_token(&mut self) -> Option<Self::Token> { if self.is_empty() { None } else { - Some((BStr::from_bytes(&self[1..]), self[0])) + let token = self[0]; + *self = &self[1..]; + Some(token) } } @@ -640,21 +753,38 @@ impl<'i> Stream for &'i BStr { } } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = (&self.0).next_slice(offset); - (BStr::from_bytes(next), slice) + fn next_slice(&mut self, offset: usize) -> Self::Slice { + let (slice, next) = self.0.split_at(offset); + *self = BStr::from_bytes(next); + slice + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint(*self) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + *self = checkpoint.0; + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + self } } impl<I> Stream for (I, usize) where - I: Stream<Token = u8>, + I: Stream<Token = u8> + Clone, { type Token = bool; type Slice = (I::Slice, usize, usize); type IterOffsets = BitOffsets<I>; + type Checkpoint = Checkpoint<(I::Checkpoint, usize)>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { BitOffsets { @@ -673,7 +803,7 @@ where } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { + fn next_token(&mut self) -> Option<Self::Token> { next_bit(self) } @@ -683,7 +813,7 @@ where P: Fn(Self::Token) -> bool, { self.iter_offsets() - .find_map(|(o, b)| predicate(b).then(|| o)) + .find_map(|(o, b)| predicate(b).then_some(o)) } #[inline(always)] fn offset_at(&self, tokens: usize) -> Result<usize, Needed> { @@ -697,11 +827,28 @@ where } } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + fn next_slice(&mut self, offset: usize) -> Self::Slice { let byte_offset = (offset + self.1) / 8; let end_offset = (offset + self.1) % 8; - let (i, s) = self.0.next_slice(byte_offset); - ((i, end_offset), (s, self.1, end_offset)) + let s = self.0.next_slice(byte_offset); + let start_offset = self.1; + self.1 = end_offset; + (s, start_offset, end_offset) + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint((self.0.checkpoint(), self.1)) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + self.0.reset(checkpoint.0 .0); + self.1 = checkpoint.0 .1; + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + &self.0 } } @@ -713,37 +860,40 @@ pub struct BitOffsets<I> { impl<I> Iterator for BitOffsets<I> where - I: Stream<Token = u8>, + I: Stream<Token = u8> + Clone, { type Item = (usize, bool); fn next(&mut self) -> Option<Self::Item> { - let (next, b) = next_bit(&self.i)?; + let b = next_bit(&mut self.i)?; let o = self.o; - self.i = next; self.o += 1; Some((o, b)) } } -fn next_bit<I>(i: &(I, usize)) -> Option<((I, usize), bool)> +fn next_bit<I>(i: &mut (I, usize)) -> Option<bool> where - I: Stream<Token = u8>, + I: Stream<Token = u8> + Clone, { if i.eof_offset() == 0 { return None; } + let offset = i.1; - let i = i.clone(); - let (next_i, byte) = i.0.next_token()?; - let bit = (byte >> i.1) & 0x1 == 0x1; + let mut next_i = i.0.clone(); + let byte = next_i.next_token()?; + let bit = (byte >> offset) & 0x1 == 0x1; - let next_offset = i.1 + 1; + let next_offset = offset + 1; if next_offset == 8 { - Some(((next_i, 0), bit)) + i.0 = next_i; + i.1 = 0; + Some(bit) } else { - Some(((i.0, next_offset), bit)) + i.1 = next_offset; + Some(bit) } } @@ -753,6 +903,8 @@ impl<I: Stream> Stream for Located<I> { type IterOffsets = <I as Stream>::IterOffsets; + type Checkpoint = Checkpoint<I::Checkpoint>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { self.input.iter_offsets() @@ -763,15 +915,8 @@ impl<I: Stream> Stream for Located<I> { } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - let (next, token) = self.input.next_token()?; - Some(( - Self { - initial: self.initial.clone(), - input: next, - }, - token, - )) + fn next_token(&mut self) -> Option<Self::Token> { + self.input.next_token() } #[inline(always)] @@ -786,15 +931,22 @@ impl<I: Stream> Stream for Located<I> { self.input.offset_at(tokens) } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = self.input.next_slice(offset); - ( - Self { - initial: self.initial.clone(), - input: next, - }, - slice, - ) + fn next_slice(&mut self, offset: usize) -> Self::Slice { + self.input.next_slice(offset) + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint(self.input.checkpoint()) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + self.input.reset(checkpoint.0); + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + &self.input } } @@ -804,6 +956,8 @@ impl<I: Stream, S: Clone + crate::lib::std::fmt::Debug> Stream for Stateful<I, S type IterOffsets = <I as Stream>::IterOffsets; + type Checkpoint = Checkpoint<I::Checkpoint>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { self.input.iter_offsets() @@ -814,15 +968,8 @@ impl<I: Stream, S: Clone + crate::lib::std::fmt::Debug> Stream for Stateful<I, S } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - let (next, token) = self.input.next_token()?; - Some(( - Self { - input: next, - state: self.state.clone(), - }, - token, - )) + fn next_token(&mut self) -> Option<Self::Token> { + self.input.next_token() } #[inline(always)] @@ -837,15 +984,22 @@ impl<I: Stream, S: Clone + crate::lib::std::fmt::Debug> Stream for Stateful<I, S self.input.offset_at(tokens) } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = self.input.next_slice(offset); - ( - Self { - input: next, - state: self.state.clone(), - }, - slice, - ) + fn next_slice(&mut self, offset: usize) -> Self::Slice { + self.input.next_slice(offset) + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint(self.input.checkpoint()) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + self.input.reset(checkpoint.0); + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + &self.input } } @@ -855,6 +1009,8 @@ impl<I: Stream> Stream for Partial<I> { type IterOffsets = <I as Stream>::IterOffsets; + type Checkpoint = Checkpoint<I::Checkpoint>; + #[inline(always)] fn iter_offsets(&self) -> Self::IterOffsets { self.input.iter_offsets() @@ -865,15 +1021,8 @@ impl<I: Stream> Stream for Partial<I> { } #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - let (next, token) = self.input.next_token()?; - Some(( - Partial { - input: next, - partial: self.partial, - }, - token, - )) + fn next_token(&mut self) -> Option<Self::Token> { + self.input.next_token() } #[inline(always)] @@ -888,15 +1037,22 @@ impl<I: Stream> Stream for Partial<I> { self.input.offset_at(tokens) } #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = self.input.next_slice(offset); - ( - Partial { - input: next, - partial: self.partial, - }, - slice, - ) + fn next_slice(&mut self, offset: usize) -> Self::Slice { + self.input.next_slice(offset) + } + + #[inline(always)] + fn checkpoint(&self) -> Self::Checkpoint { + Checkpoint(self.input.checkpoint()) + } + #[inline(always)] + fn reset(&mut self, checkpoint: Self::Checkpoint) { + self.input.reset(checkpoint.0); + } + + #[inline(always)] + fn raw(&self) -> &dyn crate::lib::std::fmt::Debug { + &self.input } } @@ -1119,24 +1275,16 @@ where } /// Useful functions to calculate the offset between slices and show a hexdump of a slice -pub trait Offset { - /// Offset between the first byte of self and the first byte of the argument - fn offset_to(&self, second: &Self) -> usize; +pub trait Offset<Start = Self> { + /// Offset between the first byte of `start` and the first byte of `self` + fn offset_from(&self, start: &Start) -> usize; } impl<'a, T> Offset for &'a [T] { - #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - (*self).offset_to(*second) - } -} - -/// Convenience implementation to accept `&[T]` instead of `&&[T]` as above -impl<T> Offset for [T] { #[inline] - fn offset_to(&self, second: &Self) -> usize { - let fst = self.as_ptr(); - let snd = second.as_ptr(); + fn offset_from(&self, start: &Self) -> usize { + let fst = (*start).as_ptr(); + let snd = (*self).as_ptr(); debug_assert!( fst <= snd, @@ -1146,46 +1294,55 @@ impl<T> Offset for [T] { } } -impl<'a> Offset for &'a str { +impl<'a, T> Offset<<&'a [T] as Stream>::Checkpoint> for &'a [T] +where + T: Clone + crate::lib::std::fmt::Debug, +{ #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.as_bytes().offset_to(second.as_bytes()) + fn offset_from(&self, other: &<&'a [T] as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) } } -/// Convenience implementation to accept `&str` instead of `&&str` as above -impl Offset for str { +impl<'a> Offset for &'a str { #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.as_bytes().offset_to(second.as_bytes()) + fn offset_from(&self, start: &Self) -> usize { + self.as_bytes().offset_from(&start.as_bytes()) } } -impl Offset for Bytes { +impl<'a> Offset<<&'a str as Stream>::Checkpoint> for &'a str { #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.as_bytes().offset_to(second.as_bytes()) + fn offset_from(&self, other: &<&'a str as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) } } impl<'a> Offset for &'a Bytes { #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.as_bytes().offset_to(second.as_bytes()) + fn offset_from(&self, start: &Self) -> usize { + self.as_bytes().offset_from(&start.as_bytes()) } } -impl Offset for BStr { +impl<'a> Offset<<&'a Bytes as Stream>::Checkpoint> for &'a Bytes { #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.as_bytes().offset_to(second.as_bytes()) + fn offset_from(&self, other: &<&'a Bytes as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) } } impl<'a> Offset for &'a BStr { #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.as_bytes().offset_to(second.as_bytes()) + fn offset_from(&self, start: &Self) -> usize { + self.as_bytes().offset_from(&start.as_bytes()) + } +} + +impl<'a> Offset<<&'a BStr as Stream>::Checkpoint> for &'a BStr { + #[inline(always)] + fn offset_from(&self, other: &<&'a BStr as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) } } @@ -1194,38 +1351,90 @@ where I: Offset, { #[inline(always)] - fn offset_to(&self, other: &Self) -> usize { - self.0.offset_to(&other.0) * 8 + other.1 - self.1 + fn offset_from(&self, start: &Self) -> usize { + self.0.offset_from(&start.0) * 8 + self.1 - start.1 + } +} + +impl<I> Offset<<(I, usize) as Stream>::Checkpoint> for (I, usize) +where + I: Stream<Token = u8> + Clone, +{ + #[inline(always)] + fn offset_from(&self, other: &<(I, usize) as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) } } impl<I> Offset for Located<I> where - I: Offset, + I: Stream, { #[inline(always)] - fn offset_to(&self, other: &Self) -> usize { - self.input.offset_to(&other.input) + fn offset_from(&self, other: &Self) -> usize { + self.offset_from(&other.checkpoint()) + } +} + +impl<I> Offset<<Located<I> as Stream>::Checkpoint> for Located<I> +where + I: Stream, +{ + #[inline(always)] + fn offset_from(&self, other: &<Located<I> as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) } } impl<I, S> Offset for Stateful<I, S> where - I: Offset, + I: Stream, + S: Clone + crate::lib::std::fmt::Debug, +{ + #[inline(always)] + fn offset_from(&self, start: &Self) -> usize { + self.offset_from(&start.checkpoint()) + } +} + +impl<I, S> Offset<<Stateful<I, S> as Stream>::Checkpoint> for Stateful<I, S> +where + I: Stream, + S: Clone + crate::lib::std::fmt::Debug, { #[inline(always)] - fn offset_to(&self, other: &Self) -> usize { - self.input.offset_to(&other.input) + fn offset_from(&self, other: &<Stateful<I, S> as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) } } impl<I> Offset for Partial<I> where + I: Stream, +{ + #[inline(always)] + fn offset_from(&self, start: &Self) -> usize { + self.offset_from(&start.checkpoint()) + } +} + +impl<I> Offset<<Partial<I> as Stream>::Checkpoint> for Partial<I> +where + I: Stream, +{ + #[inline(always)] + fn offset_from(&self, other: &<Partial<I> as Stream>::Checkpoint) -> usize { + self.checkpoint().offset_from(other) + } +} + +impl<I> Offset for Checkpoint<I> +where I: Offset, { #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.input.offset_to(&second.input) + fn offset_from(&self, start: &Self) -> usize { + self.0.offset_from(&start.0) } } @@ -1744,6 +1953,10 @@ where } } +/// Ensure checkpoint details are kept privazte +#[derive(Copy, Clone, Debug)] +pub struct Checkpoint<T>(T); + /// A range bounded inclusively for counting parses performed #[derive(PartialEq, Eq)] pub struct Range { @@ -2257,15 +2470,15 @@ impl<'a> AsChar for &'a char { /// For example, you could implement `hex_digit0` as: /// ``` /// # use winnow::prelude::*; -/// # use winnow::{error::ErrMode, error::ErrorKind, error::Error}; +/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError}; /// # use winnow::token::take_while; -/// fn hex_digit1(input: &str) -> IResult<&str, &str> { +/// fn hex_digit1<'s>(input: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> { /// take_while(1.., ('a'..='f', 'A'..='F', '0'..='9')).parse_next(input) /// } /// -/// assert_eq!(hex_digit1("21cZ"), Ok(("Z", "21c"))); -/// assert_eq!(hex_digit1("H2"), Err(ErrMode::Backtrack(Error::new("H2", ErrorKind::Slice)))); -/// assert_eq!(hex_digit1(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice)))); +/// assert_eq!(hex_digit1.parse_peek("21cZ"), Ok(("Z", "21c"))); +/// assert_eq!(hex_digit1.parse_peek("H2"), Err(ErrMode::Backtrack(InputError::new("H2", ErrorKind::Slice)))); +/// assert_eq!(hex_digit1.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice)))); /// ``` pub trait ContainsToken<T> { /// Returns true if self contains the token @@ -2415,14 +2628,6 @@ impl<const LEN: usize, C: AsChar> ContainsToken<C> for [char; LEN] { } } -impl<C: AsChar> ContainsToken<C> for &'_ str { - #[inline(always)] - fn contains_token(&self, token: C) -> bool { - let token = token.as_char(); - self.chars().any(|i| i == token) - } -} - impl<T> ContainsToken<T> for () { #[inline(always)] fn contains_token(&self, _token: T) -> bool { @@ -2464,88 +2669,6 @@ impl_contains_token_for_tuples!( F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21 ); -/// Looks for the first element of the input type for which the condition returns true, -/// and returns the input up to this position. -/// -/// *Partial version*: If no element is found matching the condition, this will return `Incomplete` -pub(crate) fn split_at_offset_partial<P, I: Stream, E: ParseError<I>>( - input: &I, - predicate: P, -) -> IResult<I, <I as Stream>::Slice, E> -where - P: Fn(I::Token) -> bool, -{ - let offset = input - .offset_for(predicate) - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - Ok(input.next_slice(offset)) -} - -/// Looks for the first element of the input type for which the condition returns true -/// and returns the input up to this position. -/// -/// Fails if the produced slice is empty. -/// -/// *Partial version*: If no element is found matching the condition, this will return `Incomplete` -pub(crate) fn split_at_offset1_partial<P, I: Stream, E: ParseError<I>>( - input: &I, - predicate: P, - e: ErrorKind, -) -> IResult<I, <I as Stream>::Slice, E> -where - P: Fn(I::Token) -> bool, -{ - let offset = input - .offset_for(predicate) - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - if offset == 0 { - Err(ErrMode::from_error_kind(input.clone(), e)) - } else { - Ok(input.next_slice(offset)) - } -} - -/// Looks for the first element of the input type for which the condition returns true, -/// and returns the input up to this position. -/// -/// *Complete version*: If no element is found matching the condition, this will return the whole input -pub(crate) fn split_at_offset_complete<P, I: Stream, E: ParseError<I>>( - input: &I, - predicate: P, -) -> IResult<I, <I as Stream>::Slice, E> -where - P: Fn(I::Token) -> bool, -{ - let offset = input - .offset_for(predicate) - .unwrap_or_else(|| input.eof_offset()); - Ok(input.next_slice(offset)) -} - -/// Looks for the first element of the input type for which the condition returns true -/// and returns the input up to this position. -/// -/// Fails if the produced slice is empty. -/// -/// *Complete version*: If no element is found matching the condition, this will return the whole input -pub(crate) fn split_at_offset1_complete<P, I: Stream, E: ParseError<I>>( - input: &I, - predicate: P, - e: ErrorKind, -) -> IResult<I, <I as Stream>::Slice, E> -where - P: Fn(I::Token) -> bool, -{ - let offset = input - .offset_for(predicate) - .unwrap_or_else(|| input.eof_offset()); - if offset == 0 { - Err(ErrMode::from_error_kind(input.clone(), e)) - } else { - Ok(input.next_slice(offset)) - } -} - #[cfg(feature = "simd")] #[inline(always)] fn memchr(token: u8, slice: &[u8]) -> Option<usize> { |