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
        }
    }
}