Coverage Report

Created: 2024-12-17 06:15

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