diff --git a/src/input.rs b/src/input.rs index 471230b2..2f6041d0 100644 --- a/src/input.rs +++ b/src/input.rs @@ -74,33 +74,31 @@ impl<'a, T> InputLength for &'a [T] { } } -impl<'a> InputLength for &'a str { +impl InputLength for [u8; LEN] { #[inline] fn input_len(&self) -> usize { self.len() } } -impl<'a> InputLength for (&'a [u8], usize) { +impl<'a, const LEN: usize> InputLength for &'a [u8; LEN] { #[inline] fn input_len(&self) -> usize { - //println!("bit input length for ({:?}, {}):", self.0, self.1); - //println!("-> {}", self.0.len() * 8 - self.1); - self.0.len() * 8 - self.1 + self.len() } } -impl InputLength for [u8; LEN] { +impl<'a> InputLength for &'a str { #[inline] fn input_len(&self) -> usize { self.len() } } -impl<'a, const LEN: usize> InputLength for &'a [u8; LEN] { +impl<'a> InputLength for (&'a [u8], usize) { #[inline] fn input_len(&self) -> usize { - self.len() + self.0.len() * 8 - self.1 } } @@ -152,17 +150,10 @@ pub trait AsBytes { fn as_bytes(&self) -> &[u8]; } -impl<'a> AsBytes for &'a str { - #[inline(always)] - fn as_bytes(&self) -> &[u8] { - (*self).as_bytes() - } -} - -impl AsBytes for str { +impl AsBytes for [u8] { #[inline(always)] fn as_bytes(&self) -> &[u8] { - self.as_ref() + self } } @@ -173,7 +164,7 @@ impl<'a> AsBytes for &'a [u8] { } } -impl AsBytes for [u8] { +impl AsBytes for [u8; LEN] { #[inline(always)] fn as_bytes(&self) -> &[u8] { self @@ -187,10 +178,17 @@ impl<'a, const LEN: usize> AsBytes for &'a [u8; LEN] { } } -impl AsBytes for [u8; LEN] { +impl<'a> AsBytes for &'a str { #[inline(always)] fn as_bytes(&self) -> &[u8] { - self + (*self).as_bytes() + } +} + +impl AsBytes for str { + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self.as_ref() } } @@ -403,14 +401,6 @@ pub trait InputIter { fn slice_index(&self, count: usize) -> Result; } -/// Abstracts slicing operations -pub trait InputTake: Sized { - /// Returns a slice of `count` bytes. panics if count > length - fn take(&self, count: usize) -> Self; - /// Split the stream at the `count` byte offset. panics if count > length - fn take_split(&self, count: usize) -> (Self, Self); -} - impl<'a> InputIter for &'a [u8] { type Item = u8; type Iter = Enumerate; @@ -441,15 +431,28 @@ impl<'a> InputIter for &'a [u8] { } } -impl<'a> InputTake for &'a [u8] { - #[inline] - fn take(&self, count: usize) -> Self { - &self[0..count] +impl<'a, const LEN: usize> InputIter for &'a [u8; LEN] { + type Item = u8; + type Iter = Enumerate; + type IterElem = Copied>; + + fn iter_indices(&self) -> Self::Iter { + (&self[..]).iter_indices() } - #[inline] - fn take_split(&self, count: usize) -> (Self, Self) { - let (prefix, suffix) = self.split_at(count); - (suffix, prefix) + + fn iter_elements(&self) -> Self::IterElem { + (&self[..]).iter_elements() + } + + fn position

(&self, predicate: P) -> Option + where + P: Fn(Self::Item) -> bool, + { + (&self[..]).position(predicate) + } + + fn slice_index(&self, count: usize) -> Result { + (&self[..]).slice_index(count) } } @@ -492,13 +495,19 @@ impl<'a> InputIter for &'a str { } } -impl<'a> InputTake for &'a str { +/// Abstracts slicing operations +pub trait InputTake: Sized { + /// Returns a slice of `count` bytes. panics if count > length + fn take(&self, count: usize) -> Self; + /// Split the stream at the `count` byte offset. panics if count > length + fn take_split(&self, count: usize) -> (Self, Self); +} + +impl<'a> InputTake for &'a [u8] { #[inline] fn take(&self, count: usize) -> Self { - &self[..count] + &self[0..count] } - - // return byte index #[inline] fn take_split(&self, count: usize) -> (Self, Self) { let (prefix, suffix) = self.split_at(count); @@ -506,28 +515,17 @@ impl<'a> InputTake for &'a str { } } -impl<'a, const LEN: usize> InputIter for &'a [u8; LEN] { - type Item = u8; - type Iter = Enumerate; - type IterElem = Copied>; - - fn iter_indices(&self) -> Self::Iter { - (&self[..]).iter_indices() - } - - fn iter_elements(&self) -> Self::IterElem { - (&self[..]).iter_elements() - } - - fn position

(&self, predicate: P) -> Option - where - P: Fn(Self::Item) -> bool, - { - (&self[..]).position(predicate) +impl<'a> InputTake for &'a str { + #[inline] + fn take(&self, count: usize) -> Self { + &self[..count] } - fn slice_index(&self, count: usize) -> Result { - (&self[..]).slice_index(count) + // return byte index + #[inline] + fn take_split(&self, count: usize) -> (Self, Self) { + let (prefix, suffix) = self.split_at(count); + (suffix, prefix) } } @@ -577,38 +575,6 @@ pub trait InputTakeAtPositionStreaming: Sized { P: Fn(Self::Item) -> bool; } -/// Methods to take as much input as possible until the provided function returns true for the current element. -/// -/// A large part of nom's basic parsers are built using this trait. -pub trait InputTakeAtPosition: Sized { - /// The current input type is a sequence of that `Item` type. - /// - /// Example: `u8` for `&[u8]` or `char` for `&str` - type Item; - - /// 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 - fn split_at_position>(&self, predicate: P) -> IResult - where - P: Fn(Self::Item) -> bool; - - /// 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 - fn split_at_position1>( - &self, - predicate: P, - e: ErrorKind, - ) -> IResult - where - P: Fn(Self::Item) -> bool; -} - impl InputTakeAtPositionStreaming for T { @@ -643,22 +609,23 @@ impl } } -impl InputTakeAtPosition - for T -{ - type Item = ::Item; +impl<'a> InputTakeAtPositionStreaming for &'a [u8] { + type Item = u8; - fn split_at_position>(&self, predicate: P) -> IResult + fn split_at_position_streaming>( + &self, + predicate: P, + ) -> IResult where P: Fn(Self::Item) -> bool, { - match self.position(predicate) { - Some(n) => Ok(self.take_split(n)), - None => Ok(self.take_split(self.input_len())), + match self.iter().position(|c| predicate(*c)) { + Some(i) => Ok(self.take_split(i)), + None => Err(Err::Incomplete(Needed::new(1))), } } - fn split_at_position1>( + fn split_at_position1_streaming>( &self, predicate: P, e: ErrorKind, @@ -666,22 +633,16 @@ impl InputT where P: Fn(Self::Item) -> bool, { - match self.position(predicate) { - Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))), - Some(n) => Ok(self.take_split(n)), - None => { - if self.input_len() == 0 { - Err(Err::Error(E::from_error_kind(self.clone(), e))) - } else { - Ok(self.take_split(self.input_len())) - } - } + match self.iter().position(|c| predicate(*c)) { + Some(0) => Err(Err::Error(E::from_error_kind(self, e))), + Some(i) => Ok(self.take_split(i)), + None => Err(Err::Incomplete(Needed::new(1))), } } } -impl<'a> InputTakeAtPositionStreaming for &'a [u8] { - type Item = u8; +impl<'a> InputTakeAtPositionStreaming for &'a str { + type Item = char; fn split_at_position_streaming>( &self, @@ -690,8 +651,9 @@ impl<'a> InputTakeAtPositionStreaming for &'a [u8] { where P: Fn(Self::Item) -> bool, { - match self.iter().position(|c| predicate(*c)) { - Some(i) => Ok(self.take_split(i)), + match self.find(predicate) { + // find() returns a byte index that is already in the slice at a char boundary + Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, None => Err(Err::Incomplete(Needed::new(1))), } } @@ -704,23 +666,58 @@ impl<'a> InputTakeAtPositionStreaming for &'a [u8] { where P: Fn(Self::Item) -> bool, { - match self.iter().position(|c| predicate(*c)) { + match self.find(predicate) { Some(0) => Err(Err::Error(E::from_error_kind(self, e))), - Some(i) => Ok(self.take_split(i)), + // find() returns a byte index that is already in the slice at a char boundary + Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, None => Err(Err::Incomplete(Needed::new(1))), } } } -impl<'a> InputTakeAtPosition for &'a [u8] { - type Item = u8; +/// Methods to take as much input as possible until the provided function returns true for the current element. +/// +/// A large part of nom's basic parsers are built using this trait. +pub trait InputTakeAtPosition: Sized { + /// The current input type is a sequence of that `Item` type. + /// + /// Example: `u8` for `&[u8]` or `char` for `&str` + type Item; + + /// 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 + fn split_at_position>(&self, predicate: P) -> IResult + where + P: Fn(Self::Item) -> bool; + + /// 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 + fn split_at_position1>( + &self, + predicate: P, + e: ErrorKind, + ) -> IResult + where + P: Fn(Self::Item) -> bool; +} + +impl InputTakeAtPosition + for T +{ + type Item = ::Item; fn split_at_position>(&self, predicate: P) -> IResult where P: Fn(Self::Item) -> bool, { - match self.iter().position(|c| predicate(*c)) { - Some(i) => Ok(self.take_split(i)), + match self.position(predicate) { + Some(n) => Ok(self.take_split(n)), None => Ok(self.take_split(self.input_len())), } } @@ -733,12 +730,12 @@ impl<'a> InputTakeAtPosition for &'a [u8] { where P: Fn(Self::Item) -> bool, { - match self.iter().position(|c| predicate(*c)) { - Some(0) => Err(Err::Error(E::from_error_kind(self, e))), - Some(i) => Ok(self.take_split(i)), + match self.position(predicate) { + Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))), + Some(n) => Ok(self.take_split(n)), None => { - if self.is_empty() { - Err(Err::Error(E::from_error_kind(self, e))) + if self.input_len() == 0 { + Err(Err::Error(E::from_error_kind(self.clone(), e))) } else { Ok(self.take_split(self.input_len())) } @@ -747,24 +744,20 @@ impl<'a> InputTakeAtPosition for &'a [u8] { } } -impl<'a> InputTakeAtPositionStreaming for &'a str { - type Item = char; +impl<'a> InputTakeAtPosition for &'a [u8] { + type Item = u8; - fn split_at_position_streaming>( - &self, - predicate: P, - ) -> IResult + fn split_at_position>(&self, predicate: P) -> IResult where P: Fn(Self::Item) -> bool, { - match self.find(predicate) { - // find() returns a byte index that is already in the slice at a char boundary - Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, - None => Err(Err::Incomplete(Needed::new(1))), + match self.iter().position(|c| predicate(*c)) { + Some(i) => Ok(self.take_split(i)), + None => Ok(self.take_split(self.input_len())), } } - fn split_at_position1_streaming>( + fn split_at_position1>( &self, predicate: P, e: ErrorKind, @@ -772,11 +765,16 @@ impl<'a> InputTakeAtPositionStreaming for &'a str { where P: Fn(Self::Item) -> bool, { - match self.find(predicate) { + match self.iter().position(|c| predicate(*c)) { Some(0) => Err(Err::Error(E::from_error_kind(self, e))), - // find() returns a byte index that is already in the slice at a char boundary - Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, - None => Err(Err::Incomplete(Needed::new(1))), + Some(i) => Ok(self.take_split(i)), + None => { + if self.is_empty() { + Err(Err::Error(E::from_error_kind(self, e))) + } else { + Ok(self.take_split(self.input_len())) + } + } } } } @@ -878,22 +876,6 @@ impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { } } } - - /* - let len = self.len(); - let blen = t.len(); - let m = if len < blen { len } else { blen }; - let reduced = &self[..m]; - let b = &t[..m]; - - if reduced != b { - CompareResult::Error - } else if m < blen { - CompareResult::Incomplete - } else { - CompareResult::Ok - } - */ } #[inline(always)] @@ -912,6 +894,18 @@ impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { } } +impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] { + #[inline(always)] + fn compare(&self, t: &'b [u8; LEN]) -> CompareResult { + self.compare(&t[..]) + } + + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8; LEN]) -> CompareResult { + self.compare_no_case(&t[..]) + } +} + impl< T: InputLength + InputIter + InputTake + UnspecializedInput, O: InputLength + InputIter + InputTake, @@ -1013,18 +1007,6 @@ impl<'a, const LEN: usize> Compare<[u8; LEN]> for &'a [u8] { } } -impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] { - #[inline(always)] - fn compare(&self, t: &'b [u8; LEN]) -> CompareResult { - self.compare(&t[..]) - } - - #[inline(always)] - fn compare_no_case(&self, t: &'b [u8; LEN]) -> CompareResult { - self.compare_no_case(&t[..]) - } -} - /// Look for a token in self pub trait FindToken { /// Returns true if self contains the token @@ -1037,27 +1019,39 @@ impl<'a> FindToken for &'a [u8] { } } -impl<'a> FindToken for &'a str { +impl<'a, 'b> FindToken<&'a u8> for &'b [u8] { + fn find_token(&self, token: &u8) -> bool { + self.find_token(*token) + } +} + +impl<'a> FindToken for &'a [u8] { + fn find_token(&self, token: char) -> bool { + self.iter().any(|i| *i == token as u8) + } +} + +impl FindToken for [u8; LEN] { fn find_token(&self, token: u8) -> bool { - self.as_bytes().find_token(token) + memchr::memchr(token, &self[..]).is_some() } } -impl<'a, 'b> FindToken<&'a u8> for &'b [u8] { +impl<'a, const LEN: usize> FindToken<&'a u8> for [u8; LEN] { fn find_token(&self, token: &u8) -> bool { self.find_token(*token) } } -impl<'a, 'b> FindToken<&'a u8> for &'b str { - fn find_token(&self, token: &u8) -> bool { +impl<'a> FindToken for &'a str { + fn find_token(&self, token: u8) -> bool { self.as_bytes().find_token(token) } } -impl<'a> FindToken for &'a [u8] { - fn find_token(&self, token: char) -> bool { - self.iter().any(|i| *i == token as u8) +impl<'a, 'b> FindToken<&'a u8> for &'b str { + fn find_token(&self, token: &u8) -> bool { + self.as_bytes().find_token(token) } } @@ -1079,18 +1073,6 @@ impl<'a, 'b> FindToken<&'a char> for &'b [char] { } } -impl FindToken for [u8; LEN] { - fn find_token(&self, token: u8) -> bool { - memchr::memchr(token, &self[..]).is_some() - } -} - -impl<'a, const LEN: usize> FindToken<&'a u8> for [u8; LEN] { - fn find_token(&self, token: &u8) -> bool { - self.find_token(*token) - } -} - /// Look for a substring in self pub trait FindSubstring { /// Returns the byte position of the substring if it is found @@ -1209,8 +1191,8 @@ macro_rules! slice_ranges_impl { }; } -slice_ranges_impl! {str} slice_ranges_impl! {[T]} +slice_ranges_impl! {str} /// Abstracts something which can extend an `Extend`. /// Used to build modified input slices in `escaped_transform`