@@ -18,116 +18,185 @@ impl<'a> AsciiStr<'a> {
1818 }
1919 }
2020
21+ pub fn len ( & self ) -> usize {
22+ self . end as usize - self . ptr as usize
23+ }
24+
25+ /// # Safety
26+ ///
27+ /// Safe if `n <= self.len()`
2128 #[ inline]
22- pub fn step_by ( & mut self , n : usize ) -> & mut Self {
29+ pub unsafe fn step_by ( & mut self , n : usize ) -> & mut Self {
30+ debug_assert ! ( n <= self . len( ) , "buffer overflow: stepping by greater than our buffer length." ) ;
31+ // SAFETY: Safe if `n <= self.len()`
2332 unsafe { self . ptr = self . ptr . add ( n) } ;
2433 self
2534 }
2635
36+ /// # Safety
37+ ///
38+ /// Safe if `!self.is_empty()`
39+ #[ inline]
40+ pub unsafe fn step ( & mut self ) -> & mut Self {
41+ debug_assert ! ( !self . is_empty( ) , "buffer overflow: buffer is empty." ) ;
42+ // SAFETY: Safe if the buffer is not empty, that is, `self.len() >= 1`
43+ unsafe { self . step_by ( 1 ) }
44+ }
45+
2746 #[ inline]
28- pub fn step ( & mut self ) -> & mut Self {
29- self . step_by ( 1 )
47+ pub fn step_if ( & mut self , c : u8 ) -> bool {
48+ let stepped = self . first_is ( c) ;
49+ if stepped {
50+ // SAFETY: safe since we have at least 1 character in the buffer
51+ unsafe { self . step ( ) } ;
52+ }
53+ stepped
54+ }
55+
56+ // TODO: Remove this...
57+ /// # Safety
58+ ///
59+ /// Safe if `!self.is_empty()`
60+ // TODO: Unsafe, remove this
61+ #[ inline]
62+ pub fn step_unsafe ( & mut self ) -> & mut Self {
63+ unsafe { self . step ( ) }
3064 }
3165
3266 #[ inline]
3367 pub fn is_empty ( & self ) -> bool {
3468 self . ptr == self . end
3569 }
3670
71+ /// # Safety
72+ ///
73+ /// Safe if `!self.is_empty()`
3774 #[ inline]
38- pub fn first ( & self ) -> u8 {
75+ pub unsafe fn first_unchecked ( & self ) -> u8 {
76+ debug_assert ! ( !self . is_empty( ) , "attempting to get first value of empty buffer." ) ;
3977 unsafe { * self . ptr }
4078 }
4179
4280 #[ inline]
43- pub fn first_is ( & self , c : u8 ) -> bool {
44- self . first ( ) == c
81+ pub fn first ( & self ) -> Option < u8 > {
82+ if !self . is_empty ( ) {
83+ // SAFETY: safe since `!self.is_empty()`
84+ Some ( unsafe { self . first_unchecked ( ) } )
85+ } else {
86+ None
87+ }
4588 }
4689
4790 #[ inline]
48- pub fn first_either ( & self , c1 : u8 , c2 : u8 ) -> bool {
49- let c = self . first ( ) ;
50- c == c1 || c == c2
91+ pub fn first_is ( & self , c : u8 ) -> bool {
92+ self . first ( ) == Some ( c)
5193 }
5294
5395 #[ inline]
54- pub fn check_first ( & self , c : u8 ) -> bool {
55- !self . is_empty ( ) && self . first ( ) == c
96+ pub fn first_is2 ( & self , c1 : u8 , c2 : u8 ) -> bool {
97+ if let Some ( c) = self . first ( ) {
98+ c == c1 || c == c2
99+ } else {
100+ false
101+ }
56102 }
57103
58104 #[ inline]
59- pub fn check_first_either ( & self , c1 : u8 , c2 : u8 ) -> bool {
60- !self . is_empty ( ) && ( self . first ( ) == c1 || self . first ( ) == c2)
105+ pub fn first_is_digit ( & self ) -> bool {
106+ if let Some ( c) = self . first ( ) {
107+ c. is_ascii_digit ( )
108+ } else {
109+ false
110+ }
61111 }
62112
63113 #[ inline]
64- pub fn check_first_digit ( & self ) -> bool {
65- !self . is_empty ( ) && self . first ( ) . is_ascii_digit ( )
114+ pub fn first_digit ( & self ) -> Option < u8 > {
115+ self . first ( ) . and_then ( |x| if x. is_ascii_digit ( ) {
116+ Some ( x - b'0' )
117+ } else {
118+ None
119+ } )
66120 }
67121
68122 #[ inline]
69- pub fn parse_digits ( & mut self , mut func : impl FnMut ( u8 ) ) {
70- while !self . is_empty ( ) && self . first ( ) . is_ascii_digit ( ) {
71- func ( self . first ( ) - b'0' ) ;
72- self . step ( ) ;
123+ pub fn try_read_digit ( & mut self ) -> Option < u8 > {
124+ if let Some ( digit) = self . first_digit ( ) {
125+ // SAFETY: Safe since `first_digit` means the buffer is not empty
126+ unsafe { self . step ( ) } ;
127+ Some ( digit)
128+ } else {
129+ None
73130 }
74131 }
75132
76133 #[ inline]
77- pub fn check_len ( & self , n : usize ) -> bool {
78- let len = self . end as usize - self . ptr as usize ;
79- n <= len
134+ pub fn parse_digits ( & mut self , mut func : impl FnMut ( u8 ) ) {
135+ while let Some ( digit) = self . try_read_digit ( ) {
136+ func ( digit) ;
137+ }
80138 }
81139
82140 #[ inline]
83141 pub fn try_read_u64 ( & self ) -> Option < u64 > {
84- if self . check_len ( 8 ) {
85- Some ( self . read_u64 ( ) )
142+ if self . len ( ) >= 8 {
143+ Some ( unsafe { self . read_u64_unchecked ( ) } )
86144 } else {
87145 None
88146 }
89147 }
90148
149+ /// # Safety
150+ ///
151+ /// Safe if `self.len() >= 8`
91152 #[ inline]
92- pub fn read_u64 ( & self ) -> u64 {
93- debug_assert ! ( self . check_len ( 8 ) ) ;
153+ pub unsafe fn read_u64_unchecked ( & self ) -> u64 {
154+ debug_assert ! ( self . len ( ) >= 8 , "overflowing buffer: buffer is not 8 bytes long" ) ;
94155 let src = self . ptr as * const u64 ;
156+ // SAFETY: Safe if `self.len() >= 8`
95157 u64:: from_le ( unsafe { ptr:: read_unaligned ( src) } )
96158 }
97159
98160 #[ inline]
99161 pub fn offset_from ( & self , other : & Self ) -> isize {
100- isize:: wrapping_sub ( self . ptr as _ , other. ptr as _ ) // assuming the same end
162+ isize:: wrapping_sub ( self . ptr as isize , other. ptr as isize ) // assuming the same end
101163 }
102164}
103165
104166// Most of these are inherently unsafe; we assume we know what we're calling and when.
105167pub trait ByteSlice : AsRef < [ u8 ] > + AsMut < [ u8 ] > {
168+ /// # Safety
169+ ///
170+ /// Safe if `!self.is_empty()`.
106171 #[ inline]
107- fn get_at ( & self , i : usize ) -> u8 {
108- unsafe { * self . as_ref ( ) . get_unchecked ( i) }
109- }
110-
111- #[ inline]
112- fn get_first ( & self ) -> u8 {
113- debug_assert ! ( !self . as_ref( ) . is_empty( ) ) ;
114- self . get_at ( 0 )
172+ unsafe fn get_first_unchecked ( & self ) -> u8 {
173+ let s = self . as_ref ( ) ;
174+ debug_assert ! ( !s. is_empty( ) ) ;
175+ // SAFETY: safe if `s.is_empty()`
176+ unsafe { * s. get_unchecked ( 0 ) }
115177 }
116178
117179 #[ inline]
118180 fn check_first ( & self , c : u8 ) -> bool {
119- ! self . as_ref ( ) . is_empty ( ) && self . get_first ( ) == c
181+ self . as_ref ( ) . first ( ) == Some ( & c )
120182 }
121183
122184 #[ inline]
123185 fn check_first2 ( & self , c1 : u8 , c2 : u8 ) -> bool {
124- !self . as_ref ( ) . is_empty ( ) && ( self . get_first ( ) == c1 || self . get_first ( ) == c2)
186+ if let Some ( & c) = self . as_ref ( ) . first ( ) {
187+ c == c1 || c == c2
188+ } else {
189+ false
190+ }
125191 }
126192
127193 #[ inline]
128194 fn eq_ignore_case ( & self , u : & [ u8 ] ) -> bool {
129- debug_assert ! ( self . as_ref( ) . len( ) >= u. len( ) ) ;
130- let d = ( 0 ..u. len ( ) ) . fold ( 0 , |d, i| d | self . get_at ( i) ^ u. get_at ( i) ) ;
195+ let s = self . as_ref ( ) ;
196+ if s. len ( ) < u. len ( ) {
197+ return false ;
198+ }
199+ let d = ( 0 ..u. len ( ) ) . fold ( 0 , |d, i| d | s[ i] ^ u[ i] ) ;
131200 d == 0 || d == 32
132201 }
133202
@@ -145,26 +214,25 @@ pub trait ByteSlice: AsRef<[u8]> + AsMut<[u8]> {
145214 s
146215 }
147216
217+ /// # Safety
218+ ///
219+ /// Safe if `self.len() >= 8`.
148220 #[ inline]
149- fn skip_chars2 ( & self , c1 : u8 , c2 : u8 ) -> & [ u8 ] {
150- let mut s = self . as_ref ( ) ;
151- while !s. is_empty ( ) && ( s. get_first ( ) == c1 || s. get_first ( ) == c2) {
152- s = s. advance ( 1 ) ;
153- }
154- s
155- }
156-
157- #[ inline]
158- fn read_u64 ( & self ) -> u64 {
221+ unsafe fn read_u64 ( & self ) -> u64 {
159222 debug_assert ! ( self . as_ref( ) . len( ) >= 8 ) ;
160223 let src = self . as_ref ( ) . as_ptr ( ) as * const u64 ;
224+ // SAFETY: safe if `self.len() >= 8`.
161225 u64:: from_le ( unsafe { ptr:: read_unaligned ( src) } )
162226 }
163227
228+ /// # Safety
229+ ///
230+ /// Safe if `self.len() >= 8`.
164231 #[ inline]
165- fn write_u64 ( & mut self , value : u64 ) {
232+ unsafe fn write_u64 ( & mut self , value : u64 ) {
166233 debug_assert ! ( self . as_ref( ) . len( ) >= 8 ) ;
167234 let dst = self . as_mut ( ) . as_mut_ptr ( ) as * mut u64 ;
235+ // SAFETY: safe if `self.len() >= 8`.
168236 unsafe { ptr:: write_unaligned ( dst, u64:: to_le ( value) ) } ;
169237 }
170238}
@@ -180,8 +248,8 @@ pub fn is_8digits(v: u64) -> bool {
180248
181249#[ inline]
182250pub fn parse_digits ( s : & mut & [ u8 ] , mut f : impl FnMut ( u8 ) ) {
183- while !s . is_empty ( ) {
184- let c = s . get_first ( ) . wrapping_sub ( b'0' ) ;
251+ while let Some ( & ch ) = s . first ( ) {
252+ let c = ch . wrapping_sub ( b'0' ) ;
185253 if c < 10 {
186254 f ( c) ;
187255 * s = s. advance ( 1 ) ;
@@ -215,14 +283,14 @@ mod tests {
215283 fn test_read_write_u64 ( ) {
216284 let bytes = b"01234567" ;
217285 let string = AsciiStr :: new ( bytes) ;
218- let int = string. read_u64 ( ) ;
219- assert_eq ! ( int, 0x3736353433323130 ) ;
286+ let int = string. try_read_u64 ( ) ;
287+ assert_eq ! ( int, Some ( 0x3736353433323130 ) ) ;
220288
221- let int = bytes. read_u64 ( ) ;
289+ let int = unsafe { bytes. read_u64 ( ) } ;
222290 assert_eq ! ( int, 0x3736353433323130 ) ;
223291
224292 let mut slc = [ 0u8 ; 8 ] ;
225- slc. write_u64 ( 0x3736353433323130 ) ;
293+ unsafe { slc. write_u64 ( 0x3736353433323130 ) } ;
226294 assert_eq ! ( & slc, bytes) ;
227295 }
228296}
0 commit comments