Skip to content

Commit 5ebd3d5

Browse files
committed
Dummy commit.
1 parent 52cc113 commit 5ebd3d5

File tree

4 files changed

+169
-87
lines changed

4 files changed

+169
-87
lines changed

src/common.rs

Lines changed: 124 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
105167
pub 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]
182250
pub 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
}

src/decimal.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ pub fn parse_decimal(mut s: &[u8]) -> Decimal {
191191
// can't fail since it follows a call to parse_number
192192
let mut d = Decimal::default();
193193
let start = s;
194-
let c = s.get_first();
194+
// TODO: Fix this does not need to be here
195+
let c = unsafe { s.get_first_unchecked() };
195196
d.negative = c == b'-';
196197
if c == b'-' || c == b'+' {
197198
s = s.advance(1);
@@ -205,11 +206,15 @@ pub fn parse_decimal(mut s: &[u8]) -> Decimal {
205206
s = s.skip_chars(b'0');
206207
}
207208
while s.len() >= 8 && d.num_digits + 8 < Decimal::MAX_DIGITS {
208-
let v = s.read_u64();
209+
// SAFETY: Safe since `s.len() >= 8`
210+
// TODO: Make safe
211+
let v = unsafe { s.read_u64() };
209212
if !is_8digits(v) {
210213
break;
211214
}
212-
d.digits[d.num_digits..].write_u64(v - 0x3030_3030_3030_3030);
215+
// SAFETY: Safe since `num_digits + 8 < Decimal::MAX_DIGITS``
216+
// TODO: Make safe
217+
unsafe { d.digits[d.num_digits..].write_u64(v - 0x3030_3030_3030_3030) };
213218
d.num_digits += 8;
214219
s = s.advance(8);
215220
}

0 commit comments

Comments
 (0)