Skip to content

Commit 788bf99

Browse files
authored
Merge pull request #103 from Manishearth/read-soundness
Remove read(), add read_u32() and read_u64() and use everywhere.
2 parents ec7edaf + 2680d09 commit 788bf99

File tree

5 files changed

+52
-18
lines changed

5 files changed

+52
-18
lines changed

lexical-parse-float/src/slow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ macro_rules! round_up_nonzero {
335335

336336
// First try reading 8-digits at a time.
337337
if iter.is_contiguous() {
338-
while let Some(value) = iter.read::<u64>() {
338+
while let Some(value) = iter.read_u64() {
339339
// SAFETY: safe since we have at least 8 bytes in the buffer.
340340
unsafe { iter.step_by_unchecked(8) };
341341
if value != 0x3030_3030_3030_3030 {

lexical-parse-integer/src/algorithm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ where
217217
debug_assert!(Iter::IS_CONTIGUOUS);
218218

219219
// Read our digits, validate the input, and check from there.
220-
let bytes = u32::from_le(iter.read::<u32>()?);
220+
let bytes = u32::from_le(iter.read_u32()?);
221221
if is_4digits::<FORMAT>(bytes) {
222222
// SAFETY: safe since we have at least 4 bytes in the buffer.
223223
unsafe { iter.step_by_unchecked(4) };
@@ -289,7 +289,7 @@ where
289289
debug_assert!(Iter::IS_CONTIGUOUS);
290290

291291
// Read our digits, validate the input, and check from there.
292-
let bytes = u64::from_le(iter.read::<u64>()?);
292+
let bytes = u64::from_le(iter.read_u64()?);
293293
if is_8digits::<FORMAT>(bytes) {
294294
// SAFETY: safe since we have at least 8 bytes in the buffer.
295295
unsafe { iter.step_by_unchecked(8) };

lexical-util/src/iterator.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,14 @@ pub trait BytesIter<'a>: Iterator<Item = &'a u8> {
120120
/// many bytes as the size of V.
121121
unsafe fn read_unchecked<V>(&self) -> V;
122122

123-
/// Try to read a value of a different type from the iterator.
123+
/// Try to read a the next four bytes as a u32.
124124
/// This advances the internal state of the iterator.
125-
fn read<V>(&self) -> Option<V>;
125+
fn read_u32(&self) -> Option<u32>;
126+
127+
128+
/// Try to read the next eight bytes as a u64
129+
/// This advances the internal state of the iterator.
130+
fn read_u64(&self) -> Option<u64>;
126131

127132
/// Advance the internal slice by `N` elements.
128133
///

lexical-util/src/noskip.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl<'a, const __: u128> Bytes<'a, __> {
105105
/// # Safety
106106
///
107107
/// Safe as long as the number of the buffer is contains as least as
108-
/// many bytes as the size of V.
108+
/// many bytes as the size of V, and V is valid for all bit patterns.
109109
#[inline]
110110
#[allow(clippy::assertions_on_constants)]
111111
pub unsafe fn read_unchecked<V>(&self) -> V {
@@ -117,13 +117,26 @@ impl<'a, const __: u128> Bytes<'a, __> {
117117
unsafe { ptr::read_unaligned::<V>(slc.as_ptr() as *const _) }
118118
}
119119

120-
/// Try to read a value of a different type from the iterator.
120+
/// Try to read a the next four bytes as a u32.
121121
/// This advances the internal state of the iterator.
122122
#[inline]
123-
pub fn read<V>(&self) -> Option<V> {
124-
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<V>() {
123+
pub fn read_u32(&self) -> Option<u32> {
124+
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<u32>() {
125125
// SAFETY: safe since we've guaranteed the buffer is greater than
126-
// the number of elements read.
126+
// the number of elements read. u32 is valid for all bit patterns
127+
unsafe { Some(self.read_unchecked()) }
128+
} else {
129+
None
130+
}
131+
}
132+
133+
/// Try to read the next eight bytes as a u64
134+
/// This advances the internal state of the iterator.
135+
#[inline]
136+
pub fn read_u64(&self) -> Option<u64> {
137+
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<u64>() {
138+
// SAFETY: safe since we've guaranteed the buffer is greater than
139+
// the number of elements read. u64 is valid for all bit patterns
127140
unsafe { Some(self.read_unchecked()) }
128141
} else {
129142
None
@@ -288,8 +301,13 @@ impl<'a: 'b, 'b, const __: u128> BytesIter<'a> for BytesIterator<'a, 'b, __> {
288301
}
289302

290303
#[inline]
291-
fn read<V>(&self) -> Option<V> {
292-
self.byte.read()
304+
fn read_u32(&self) -> Option<u32> {
305+
self.byte.read_u32()
306+
}
307+
308+
#[inline]
309+
fn read_u64(&self) -> Option<u64> {
310+
self.byte.read_u64()
293311
}
294312

295313
#[inline]

lexical-util/src/skip.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> {
428428
/// # Safety
429429
///
430430
/// Safe as long as the number of the buffer is contains as least as
431-
/// many bytes as the size of V.
431+
/// many bytes as the size of V, and V is valid for all bit patterns.
432432
#[inline]
433433
pub unsafe fn read_unchecked<V>(&self) -> V {
434434
debug_assert!(Self::IS_CONTIGUOUS);
@@ -439,19 +439,30 @@ impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> {
439439
unsafe { ptr::read_unaligned::<V>(slc.as_ptr() as *const _) }
440440
}
441441

442-
/// Try to read a value of a different type from the iterator.
442+
/// Try to read a the next four bytes as a u32.
443443
/// This advances the internal state of the iterator.
444444
#[inline]
445-
pub fn read<V>(&self) -> Option<V> {
446-
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<V>() {
445+
unsafe fn read_u32(&self) -> Option<u32> {
446+
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<u32>() {
447447
// SAFETY: safe since we've guaranteed the buffer is greater than
448-
// the number of elements read.
448+
// the number of elements read. u32 is valid for all bit patterns
449+
unsafe { Some(self.read_unchecked()) }
450+
} else {
451+
None
452+
}
453+
}
454+
/// Try to read a the next four bytes as a u32.
455+
/// This advances the internal state of the iterator.
456+
#[inline]
457+
unsafe fn read_u64(&self) -> Option<u64> {
458+
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<u64>() {
459+
// SAFETY: safe since we've guaranteed the buffer is greater than
460+
// the number of elements read. u64 is valid for all bit patterns
449461
unsafe { Some(self.read_unchecked()) }
450462
} else {
451463
None
452464
}
453465
}
454-
455466
/// Check if the next element is a given value.
456467
#[inline]
457468
pub fn first_is(&mut self, value: u8) -> bool {

0 commit comments

Comments
 (0)