Coverage Report

Created: 2025-02-21 07:11

/rust/registry/src/index.crates.io-6f17d22bba15001f/httparse-1.10.0/src/iter.rs
Line
Count
Source (jump to first uncovered line)
1
use core::convert::TryFrom;
2
use core::convert::TryInto;
3
4
#[allow(missing_docs)]
5
pub struct Bytes<'a> {
6
    start: *const u8,
7
    end: *const u8,
8
    /// INVARIANT: start <= cursor && cursor <= end
9
    cursor: *const u8,
10
    phantom: core::marker::PhantomData<&'a ()>,
11
}
12
13
#[allow(missing_docs)]
14
impl<'a> Bytes<'a> {
15
    #[inline]
16
0
    pub fn new(slice: &'a [u8]) -> Bytes<'a> {
17
0
        let start = slice.as_ptr();
18
0
        // SAFETY: obtain pointer to slice end; start points to slice start.
19
0
        let end = unsafe { start.add(slice.len()) };
20
0
        let cursor = start;
21
0
        Bytes {
22
0
            start,
23
0
            end,
24
0
            cursor,
25
0
            phantom: core::marker::PhantomData,
26
0
        }
27
0
    }
28
29
    #[inline]
30
0
    pub fn pos(&self) -> usize {
31
0
        self.cursor as usize - self.start as usize
32
0
    }
33
34
    #[inline]
35
0
    pub fn peek(&self) -> Option<u8> {
36
0
        if self.cursor < self.end {
37
            // SAFETY:  bounds checked
38
0
            Some(unsafe { *self.cursor })
39
        } else {
40
0
            None
41
        }
42
0
    }
43
44
    /// Peek at byte `n` ahead of cursor
45
    ///
46
    /// # Safety
47
    ///
48
    /// Caller must ensure that `n <= self.len()`, otherwise `self.cursor.add(n)` is UB.
49
    /// That means there are at least `n-1` bytes between `self.cursor` and `self.end`
50
    /// and `self.cursor.add(n)` is either `self.end` or points to a valid byte.
51
    #[inline]
52
0
    pub unsafe fn peek_ahead(&self, n: usize) -> Option<u8> {
53
0
        debug_assert!(n <= self.len());
54
        // SAFETY: by preconditions
55
0
        let p = unsafe { self.cursor.add(n) };
56
0
        if p < self.end {
57
            // SAFETY: by preconditions, if this is not `self.end`,
58
            // then it is safe to dereference
59
0
            Some(unsafe { *p })
60
        } else {
61
0
            None
62
        }
63
0
    }
64
65
    #[inline]
66
0
    pub fn peek_n<'b: 'a, U: TryFrom<&'a [u8]>>(&'b self, n: usize) -> Option<U> {
67
0
        // TODO: once we bump MSRC, use const generics to allow only [u8; N] reads
68
0
        // TODO: drop `n` arg in favour of const
69
0
        // let n = core::mem::size_of::<U>();
70
0
        self.as_ref().get(..n)?.try_into().ok()
71
0
    }
Unexecuted instantiation: <httparse::iter::Bytes>::peek_n::<[u8; 4]>
Unexecuted instantiation: <httparse::iter::Bytes>::peek_n::<[u8; 8]>
72
73
    /// Advance by 1, equivalent to calling `advance(1)`.
74
    ///
75
    /// # Safety
76
    ///
77
    /// Caller must ensure that Bytes hasn't been advanced/bumped by more than [`Bytes::len()`].
78
    #[inline]
79
0
    pub unsafe fn bump(&mut self) {
80
0
        self.advance(1)
81
0
    }
82
83
    /// Advance cursor by `n`
84
    ///
85
    /// # Safety
86
    ///
87
    /// Caller must ensure that Bytes hasn't been advanced/bumped by more than [`Bytes::len()`].
88
    #[inline]
89
0
    pub unsafe fn advance(&mut self, n: usize) {
90
0
        self.cursor = self.cursor.add(n);
91
0
        debug_assert!(self.cursor <= self.end, "overflow");
92
0
    }
93
94
    #[inline]
95
0
    pub fn len(&self) -> usize {
96
0
        self.end as usize - self.cursor as usize
97
0
    }
98
99
    #[inline]
100
0
    pub fn is_empty(&self) -> bool {
101
0
        self.len() == 0
102
0
    }
103
104
    #[inline]
105
0
    pub fn slice(&mut self) -> &'a [u8] {
106
0
        // SAFETY: not moving position at all, so it's safe
107
0
        let slice = unsafe { slice_from_ptr_range(self.start, self.cursor) };
108
0
        self.commit();
109
0
        slice
110
0
    }
111
112
    // TODO: this is an anti-pattern, should be removed
113
    /// Deprecated. Do not use!
114
    /// # Safety
115
    ///
116
    /// Caller must ensure that `skip` is at most the number of advances (i.e., `bytes.advance(3)`
117
    /// implies a skip of at most 3).
118
    #[inline]
119
0
    pub unsafe fn slice_skip(&mut self, skip: usize) -> &'a [u8] {
120
0
        debug_assert!(skip <= self.cursor.offset_from(self.start) as usize);
121
0
        let head = slice_from_ptr_range(self.start, self.cursor.sub(skip));
122
0
        self.commit();
123
0
        head
124
0
    }
125
126
    #[inline]
127
0
    pub fn commit(&mut self) {
128
0
        self.start = self.cursor
129
0
    }
130
131
    /// # Safety
132
    ///
133
    /// see [`Bytes::advance`] safety comment.
134
    #[inline]
135
0
    pub unsafe fn advance_and_commit(&mut self, n: usize) {
136
0
        self.advance(n);
137
0
        self.commit();
138
0
    }
139
140
    #[inline]
141
0
    pub fn as_ptr(&self) -> *const u8 {
142
0
        self.cursor
143
0
    }
144
145
    #[inline]
146
0
    pub fn start(&self) -> *const u8 {
147
0
        self.start
148
0
    }
149
150
    #[inline]
151
0
    pub fn end(&self) -> *const u8 {
152
0
        self.end
153
0
    }
154
155
    /// # Safety
156
    ///
157
    /// Must ensure invariant `bytes.start() <= ptr && ptr <= bytes.end()`.
158
    #[inline]
159
0
    pub unsafe fn set_cursor(&mut self, ptr: *const u8) {
160
0
        debug_assert!(ptr >= self.start);
161
0
        debug_assert!(ptr <= self.end);
162
0
        self.cursor = ptr;
163
0
    }
164
}
165
166
impl AsRef<[u8]> for Bytes<'_> {
167
    #[inline]
168
0
    fn as_ref(&self) -> &[u8] {
169
0
        // SAFETY: not moving position at all, so it's safe
170
0
        unsafe { slice_from_ptr_range(self.cursor, self.end) }
171
0
    }
172
}
173
174
/// # Safety
175
///
176
/// Must ensure start and end point to the same memory object to uphold memory safety.
177
#[inline]
178
0
unsafe fn slice_from_ptr_range<'a>(start: *const u8, end: *const u8) -> &'a [u8] {
179
0
    debug_assert!(start <= end);
180
0
    core::slice::from_raw_parts(start, end as usize - start as usize)
181
0
}
182
183
impl Iterator for Bytes<'_> {
184
    type Item = u8;
185
186
    #[inline]
187
0
    fn next(&mut self) -> Option<u8> {
188
0
        if self.cursor < self.end {
189
            // SAFETY: bounds checked dereference
190
            unsafe {
191
0
                let b = *self.cursor;
192
0
                self.bump();
193
0
                Some(b)
194
            }
195
        } else {
196
0
            None
197
        }
198
0
    }
199
}