1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
//! Specialized buffer traits.
//!
//! The traits are for iterables containing bytes, and provide optimizations
//! which then can be used for contiguous or non-contiguous iterables,
//! including containers or iterators of any kind.
/// A trait for working with iterables of bytes.
///
/// These buffers can either be contiguous or not contiguous and provide
/// methods for reading data and accessing underlying data. The readers
/// can either be contiguous or non-contiguous, although performance and
/// some API methods may not be available for both.
///
/// # Safety
///
/// This trait is effectively safe but the implementor must guarantee that
/// `is_empty` is implemented correctly. For most implementations, this can
/// be `self.as_slice().is_empty()`, where `as_slice` is implemented as
/// `&self.bytes[self.index..]`.
#[cfg(feature = "parse")]
pub unsafe trait Buffer<'a> {
/// Determine if the buffer is contiguous in memory.
const IS_CONTIGUOUS: bool;
/// Get a ptr to the current start of the buffer.
fn as_ptr(&self) -> *const u8;
/// Get a slice to the current start of the buffer.
fn as_slice(&self) -> &'a [u8];
/// Get if no bytes are available in the buffer.
///
/// This operators on the underlying buffer: that is,
/// it returns if [as_slice] would return an empty slice.
///
/// [as_slice]: Buffer::as_slice
#[inline(always)]
fn is_empty(&self) -> bool {
self.as_slice().is_empty()
}
/// Determine if the buffer is contiguous.
#[inline(always)]
fn is_contiguous(&self) -> bool {
Self::IS_CONTIGUOUS
}
/// Peek the next value of the buffer, without checking bounds.
///
/// # Safety
///
/// Safe as long as there is at least a single valid value left in
/// the buffer. Note that the behavior of this may lead to out-of-bounds
/// access (for contiguous buffers) or panics (for non-contiguous
/// buffers).
unsafe fn first_unchecked(&self) -> &'a u8;
/// Get the next value available without consuming it.
///
/// # Safety
///
/// An implementor must implement `is_empty` correctly in
/// order to guarantee the traitt is safe: `is_empty` **MUST**
/// ensure that one value remains, if the iterator is non-
/// contiguous this means advancing the iterator to the next
/// position.
#[inline(always)]
fn first(&self) -> Option<&'a u8> {
if !self.is_empty() {
// SAFETY: safe since the buffer cannot be empty as validated before.
unsafe { Some(self.first_unchecked()) }
} else {
None
}
}
/// Check if the next element is a given value.
#[inline(always)]
fn first_is(&self, value: u8) -> bool {
if let Some(&c) = self.first() {
c == value
} else {
false
}
}
/// Check if the next element is a given value without case sensitivity.
#[inline(always)]
fn case_insensitive_first_is(&self, value: u8) -> bool {
if let Some(&c) = self.first() {
c.to_ascii_lowercase() == value.to_ascii_lowercase()
} else {
false
}
}
}