@@ -5,6 +5,7 @@ use core::convert::TryFrom;
5
5
pub struct Bytes < ' a > {
6
6
start : * const u8 ,
7
7
end : * const u8 ,
8
+ /// INVARIANT: start <= cursor && cursor <= end
8
9
cursor : * const u8 ,
9
10
phantom : core:: marker:: PhantomData < & ' a ( ) > ,
10
11
}
@@ -14,6 +15,7 @@ impl<'a> Bytes<'a> {
14
15
#[ inline]
15
16
pub fn new ( slice : & ' a [ u8 ] ) -> Bytes < ' a > {
16
17
let start = slice. as_ptr ( ) ;
18
+ // SAFETY: obtain pointer to slice end; start points to slice start.
17
19
let end = unsafe { start. add ( slice. len ( ) ) } ;
18
20
let cursor = start;
19
21
Bytes {
@@ -32,7 +34,7 @@ impl<'a> Bytes<'a> {
32
34
#[ inline]
33
35
pub fn peek ( & self ) -> Option < u8 > {
34
36
if self . cursor < self . end {
35
- // SAFETY: bounds checked
37
+ // SAFETY: bounds checked
36
38
Some ( unsafe { * self . cursor } )
37
39
} else {
38
40
None
@@ -41,9 +43,11 @@ impl<'a> Bytes<'a> {
41
43
42
44
#[ inline]
43
45
pub fn peek_ahead ( & self , n : usize ) -> Option < u8 > {
46
+ // SAFETY: obtain a potentially OOB pointer that is later compared against the `self.end`
47
+ // pointer.
44
48
let ptr = unsafe { self . cursor . add ( n) } ;
45
49
if ptr < self . end {
46
- // SAFETY: bounds checked
50
+ // SAFETY: bounds checked pointer dereference is safe
47
51
Some ( unsafe { * ptr } )
48
52
} else {
49
53
None
@@ -58,11 +62,21 @@ impl<'a> Bytes<'a> {
58
62
self . as_ref ( ) . get ( ..n) ?. try_into ( ) . ok ( )
59
63
}
60
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()`].
61
70
#[ inline]
62
71
pub unsafe fn bump ( & mut self ) {
63
72
self . advance ( 1 )
64
73
}
65
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()`].
66
80
#[ inline]
67
81
pub unsafe fn advance ( & mut self , n : usize ) {
68
82
self . cursor = self . cursor . add ( n) ;
@@ -74,15 +88,25 @@ impl<'a> Bytes<'a> {
74
88
self . end as usize - self . cursor as usize
75
89
}
76
90
91
+ #[ inline]
92
+ pub fn is_empty ( & self ) -> bool {
93
+ self . len ( ) == 0
94
+ }
95
+
77
96
#[ inline]
78
97
pub fn slice ( & mut self ) -> & ' a [ u8 ] {
79
- // not moving position at all, so it's safe
98
+ // SAFETY: not moving position at all, so it's safe
80
99
let slice = unsafe { slice_from_ptr_range ( self . start , self . cursor ) } ;
81
100
self . commit ( ) ;
82
101
slice
83
102
}
84
103
85
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).
86
110
#[ inline]
87
111
pub unsafe fn slice_skip ( & mut self , skip : usize ) -> & ' a [ u8 ] {
88
112
debug_assert ! ( self . cursor. sub( skip) >= self . start) ;
@@ -96,6 +120,9 @@ impl<'a> Bytes<'a> {
96
120
self . start = self . cursor
97
121
}
98
122
123
+ /// # Safety
124
+ ///
125
+ /// see [`Bytes::advance`] safety comment.
99
126
#[ inline]
100
127
pub unsafe fn advance_and_commit ( & mut self , n : usize ) {
101
128
self . advance ( n) ;
@@ -117,6 +144,9 @@ impl<'a> Bytes<'a> {
117
144
self . end
118
145
}
119
146
147
+ /// # Safety
148
+ ///
149
+ /// Must ensure invariant `bytes.start() <= ptr && ptr <= bytes.end()`.
120
150
#[ inline]
121
151
pub unsafe fn set_cursor ( & mut self , ptr : * const u8 ) {
122
152
debug_assert ! ( ptr >= self . start) ;
@@ -128,10 +158,14 @@ impl<'a> Bytes<'a> {
128
158
impl < ' a > AsRef < [ u8 ] > for Bytes < ' a > {
129
159
#[ inline]
130
160
fn as_ref ( & self ) -> & [ u8 ] {
161
+ // SAFETY: not moving position at all, so it's safe
131
162
unsafe { slice_from_ptr_range ( self . cursor , self . end ) }
132
163
}
133
164
}
134
165
166
+ /// # Safety
167
+ ///
168
+ /// Must ensure start and end point to the same memory object to uphold memory safety.
135
169
#[ inline]
136
170
unsafe fn slice_from_ptr_range < ' a > ( start : * const u8 , end : * const u8 ) -> & ' a [ u8 ] {
137
171
debug_assert ! ( start <= end) ;
@@ -144,7 +178,7 @@ impl<'a> Iterator for Bytes<'a> {
144
178
#[ inline]
145
179
fn next ( & mut self ) -> Option < u8 > {
146
180
if self . cursor < self . end {
147
- // SAFETY: bounds checked
181
+ // SAFETY: bounds checked dereference
148
182
unsafe {
149
183
let b = * self . cursor ;
150
184
self . bump ( ) ;
0 commit comments