//! Traits input types have to implement to work with nom combinators usecrate::error::{ErrorKind, ParseError}; usecrate::internal::{Err, IResult, Needed}; usecrate::lib::std::iter::{Copied, Enumerate}; usecrate::lib::std::ops::{Range, RangeFrom, RangeFull, RangeTo}; usecrate::lib::std::slice::Iter; usecrate::lib::std::str::from_utf8; usecrate::lib::std::str::CharIndices; usecrate::lib::std::str::Chars; usecrate::lib::std::str::FromStr;
/// Abstract method to calculate the input length pubtrait InputLength { /// Calculates the input length, as indicated by its name, /// and the name of the trait itself fn input_len(&self) -> usize;
}
/// Useful functions to calculate the offset between slices and show a hexdump of a slice pubtrait Offset { /// Offset between the first byte of self and the first byte of the argument fn offset(&self, second: &Self) -> usize;
}
impl Offset for [u8] { fn offset(&self, second: &Self) -> usize { let fst = self.as_ptr(); let snd = second.as_ptr();
snd as usize - fst as usize
}
}
impl<'a> Offset for &'a [u8] { fn offset(&self, second: &Self) -> usize { let fst = self.as_ptr(); let snd = second.as_ptr();
snd as usize - fst as usize
}
}
impl Offset for str { fn offset(&self, second: &Self) -> usize { let fst = self.as_ptr(); let snd = second.as_ptr();
snd as usize - fst as usize
}
}
impl<'a> Offset for &'a str { fn offset(&self, second: &Self) -> usize { let fst = self.as_ptr(); let snd = second.as_ptr();
snd as usize - fst as usize
}
}
/// Helper trait for types that can be viewed as a byte slice pubtrait AsBytes { /// Casts the input type to a byte slice fn as_bytes(&self) -> &[u8];
}
/// Transforms common types to a char for basic token parsing pubtrait AsChar { /// makes a char from self fn as_char(self) -> char;
/// Tests that self is an alphabetic character /// /// Warning: for `&str` it recognizes alphabetic /// characters outside of the 52 ASCII letters fn is_alpha(self) -> bool;
/// Tests that self is an alphabetic character /// or a decimal digit fn is_alphanum(self) -> bool; /// Tests that self is a decimal digit fn is_dec_digit(self) -> bool; /// Tests that self is an hex digit fn is_hex_digit(self) -> bool; /// Tests that self is an octal digit fn is_oct_digit(self) -> bool; /// Gets the len in bytes for self fn len(self) -> usize;
}
/// Abstracts common iteration operations on the input type pubtrait InputIter { /// The current input type is a sequence of that `Item` type. /// /// Example: `u8` for `&[u8]` or `char` for `&str` type Item; /// An iterator over the input type, producing the item and its position /// for use with [Slice]. If we're iterating over `&str`, the position /// corresponds to the byte index of the character type Iter: Iterator<Item = (usize, Self::Item)>;
/// An iterator over the input type, producing the item type IterElem: Iterator<Item = Self::Item>;
/// Returns an iterator over the elements and their byte offsets fn iter_indices(&self) -> Self::Iter; /// Returns an iterator over the elements fn iter_elements(&self) -> Self::IterElem; /// Finds the byte position of the element fn position<P>(&self, predicate: P) -> Option<usize> where
P: Fn(Self::Item) -> bool; /// Get the byte offset from the element's position in the stream fn slice_index(&self, count: usize) -> Result<usize, Needed>;
}
/// Abstracts slicing operations pubtrait 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<Self::IterElem>; type IterElem = Copied<Iter<'a, u8>>;
/// Dummy trait used for default implementations (currently only used for `InputTakeAtPosition` and `Compare`). /// /// When implementing a custom input type, it is possible to use directly the /// default implementation: If the input type implements `InputLength`, `InputIter`, /// `InputTake` and `Clone`, you can implement `UnspecializedInput` and get /// a default version of `InputTakeAtPosition` and `Compare`. /// /// For performance reasons, you might want to write a custom implementation of /// `InputTakeAtPosition` (like the one for `&[u8]`). pubtrait UnspecializedInput {}
/// 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. pubtrait 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. /// /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E> 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. /// /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` fn split_at_position1<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind,
) -> IResult<Self, Self, E> 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. /// /// *complete version*: If no element is found matching the condition, this will return the whole input fn split_at_position_complete<P, E: ParseError<Self>>(
&self,
predicate: P,
) -> IResult<Self, Self, E> 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_complete<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind,
) -> IResult<Self, Self, E> where
P: Fn(Self::Item) -> bool;
}
impl<T: InputLength + InputIter + InputTake + Clone + UnspecializedInput> InputTakeAtPosition for T
{ type Item = <T as InputIter>::Item;
impl<'a> InputTakeAtPosition for &'a str { type Item = char;
fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E> where
P: Fn(Self::Item) -> bool,
{ matchself.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))),
}
}
fn split_at_position1<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind,
) -> IResult<Self, Self, E> where
P: Fn(Self::Item) -> bool,
{ matchself.find(predicate) {
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))),
}
}
fn split_at_position_complete<P, E: ParseError<Self>>(
&self,
predicate: P,
) -> IResult<Self, Self, E> where
P: Fn(Self::Item) -> bool,
{ matchself.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))) }, // the end of slice is a char boundary
None => unsafe {
Ok(( self.get_unchecked(self.len()..), self.get_unchecked(..self.len()),
))
},
}
}
fn split_at_position1_complete<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind,
) -> IResult<Self, Self, E> where
P: Fn(Self::Item) -> bool,
{ matchself.find(predicate) {
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 => { ifself.is_empty() {
Err(Err::Error(E::from_error_kind(self, e)))
} else { // the end of slice is a char boundary unsafe {
Ok(( self.get_unchecked(self.len()..), self.get_unchecked(..self.len()),
))
}
}
}
}
}
}
/// Indicates whether a comparison was successful, an error, or /// if more data was needed #[derive(Debug, PartialEq)] pubenum CompareResult { /// Comparison was successful
Ok, /// We need more data to be sure
Incomplete, /// Comparison failed
Error,
}
/// Abstracts comparison operations pubtrait Compare<T> { /// Compares self to another value for equality fn compare(&self, t: T) -> CompareResult; /// Compares self to another value for equality /// independently of the case. /// /// Warning: for `&str`, the comparison is done /// by lowercasing both strings and comparing /// the result. This is a temporary solution until /// a better one appears fn compare_no_case(&self, t: T) -> CompareResult;
}
fn lowercase_byte(c: u8) -> u8 { match c {
b'A'..=b'Z' => c - b'A' + b'a',
_ => c,
}
}
impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { #[inline(always)] fn compare(&self, t: &'b [u8]) -> CompareResult { let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b);
//FIXME: this version is too simple and does not use the current locale #[inline(always)] fn compare_no_case(&self, t: &'b str) -> CompareResult { let pos = self
.chars()
.zip(t.chars())
.position(|(a, b)| a.to_lowercase().ne(b.to_lowercase()));
/// Look for a substring in self pubtrait FindSubstring<T> { /// Returns the byte position of the substring if it is found fn find_substring(&self, substr: T) -> Option<usize>;
}
let (&substr_first, substr_rest) = match substr.split_first() {
Some(split) => split, // an empty substring is found at position 0 // This matches the behavior of str.find("").
None => return Some(0),
};
if substr_rest.is_empty() { return memchr::memchr(substr_first, self);
}
letmut offset = 0; let haystack = &self[..self.len() - substr_rest.len()];
/// Used to integrate `str`'s `parse()` method pubtrait ParseTo<R> { /// Succeeds if `parse()` succeeded. The byte slice implementation /// will first convert it to a `&str`, then apply the `parse()` function fn parse_to(&self) -> Option<R>;
}
/// Slicing operations using ranges. /// /// This trait is loosely based on /// `Index`, but can actually return /// something else than a `&[T]` or `&str` pubtrait Slice<R> { /// Slices self according to the range argument fn slice(&self, range: R) -> Self;
}
/// Abstracts something which can extend an `Extend`. /// Used to build modified input slices in `escaped_transform` pubtrait ExtendInto { /// The current input type is a sequence of that `Item` type. /// /// Example: `u8` for `&[u8]` or `char` for `&str` type Item;
/// The type that will be produced type Extender;
/// Create a new `Extend` of the correct type fn new_builder(&self) -> Self::Extender; /// Accumulate the input into an accumulator fn extend_into(&self, acc: &mutSelf::Extender);
}
#[cfg(feature = "alloc")] impl ExtendInto for [u8] { type Item = u8; type Extender = Vec<u8>;
/// Helper trait to convert numbers to usize. /// /// By default, usize implements `From<u8>` and `From<u16>` but not /// `From<u32>` and `From<u64>` because that would be invalid on some /// platforms. This trait implements the conversion for platforms /// with 32 and 64 bits pointer platforms pubtrait ToUsize { /// converts self to usize fn to_usize(&self) -> usize;
}
/// Equivalent From implementation to avoid orphan rules in bits parsers pubtrait ErrorConvert<E> { /// Transform to another error type fn convert(self) -> E;
}
impl ErrorConvert<()> for () { fn convert(self) {}
}
#[cfg(feature = "std")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "std")))] /// Helper trait to show a byte slice as a hex dump pubtrait HexDisplay { /// Converts the value of `self` to a hex dump, returning the owned /// `String`. fn to_hex(&self, chunk_size: usize) -> String;
/// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned /// `String`. fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
}
#[test] fn test_offset_u8() { let s = b"abcd123"; let a = &s[..]; let b = &a[2..]; let c = &a[..4]; let d = &a[3..5];
assert_eq!(a.offset(b), 2);
assert_eq!(a.offset(c), 0);
assert_eq!(a.offset(d), 3);
}
#[test] fn test_offset_str() { let s = "abcřèÂßÇd123"; let a = &s[..]; let b = &a[7..]; let c = &a[..5]; let d = &a[5..9];
assert_eq!(a.offset(b), 7);
assert_eq!(a.offset(c), 0);
assert_eq!(a.offset(d), 5);
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.5 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.