diff --git a/lexical-util/src/iterator.rs b/lexical-util/src/iterator.rs index 149ab92e..34211aca 100644 --- a/lexical-util/src/iterator.rs +++ b/lexical-util/src/iterator.rs @@ -20,7 +20,13 @@ pub use crate::skip::{AsBytes, Bytes}; /// A default implementation is provided for slice iterators. /// This trait **should never** return `null` from `as_ptr`, or be /// implemented for non-contiguous data. -pub trait BytesIter<'a>: Iterator { +/// +/// # Safety +/// The safe methods are sound as long as the caller ensures that +/// the methods for `read_32`, `read_64`, etc. check the bounds +/// of the underlying contiguous buffer and is only called on +/// contiguous buffers. +pub unsafe trait BytesIter<'a>: Iterator { /// Determine if each yielded value is adjacent in memory. const IS_CONTIGUOUS: bool; diff --git a/lexical-util/src/noskip.rs b/lexical-util/src/noskip.rs index 8abd9137..8c93557f 100644 --- a/lexical-util/src/noskip.rs +++ b/lexical-util/src/noskip.rs @@ -232,7 +232,7 @@ pub struct BytesIterator<'a: 'b, 'b, const __: u128> { byte: &'b mut Bytes<'a, __>, } -impl<'a: 'b, 'b, const __: u128> BytesIter<'a> for BytesIterator<'a, 'b, __> { +unsafe impl<'a: 'b, 'b, const __: u128> BytesIter<'a> for BytesIterator<'a, 'b, __> { const IS_CONTIGUOUS: bool = Bytes::<'a, __>::IS_CONTIGUOUS; #[inline(always)] diff --git a/lexical-util/src/skip.rs b/lexical-util/src/skip.rs index 591d9ca7..d663a94c 100644 --- a/lexical-util/src/skip.rs +++ b/lexical-util/src/skip.rs @@ -442,7 +442,7 @@ impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> { /// Try to read a the next four bytes as a u32. /// This advances the internal state of the iterator. #[inline(always)] - unsafe fn read_u32(&self) -> Option { + fn read_u32(&self) -> Option { if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::() { // SAFETY: safe since we've guaranteed the buffer is greater than // the number of elements read. u32 is valid for all bit patterns @@ -454,7 +454,7 @@ impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> { /// Try to read a the next four bytes as a u32. /// This advances the internal state of the iterator. #[inline(always)] - unsafe fn read_u64(&self) -> Option { + fn read_u64(&self) -> Option { if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::() { // SAFETY: safe since we've guaranteed the buffer is greater than // the number of elements read. u64 is valid for all bit patterns @@ -721,7 +721,7 @@ macro_rules! skip_iterator_byteiter_base { /// Create impl ByteIter block for skip iterator. macro_rules! skip_iterator_byteiter_impl { ($iterator:ident, $mask:ident, $i:ident, $l:ident, $t:ident, $c:ident) => { - impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for $iterator<'a, 'b, FORMAT> { + unsafe impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for $iterator<'a, 'b, FORMAT> { skip_iterator_byteiter_base!(FORMAT, $mask); /// Peek the next value of the iterator, without consuming it. @@ -821,7 +821,7 @@ impl<'a: 'b, 'b, const FORMAT: u128> SpecialBytesIterator<'a, 'b, FORMAT> { is_digit_separator!(FORMAT); } -impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for SpecialBytesIterator<'a, 'b, FORMAT> { +unsafe impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for SpecialBytesIterator<'a, 'b, FORMAT> { skip_iterator_byteiter_base!(FORMAT, SPECIAL_DIGIT_SEPARATOR); /// Peek the next value of the iterator, without consuming it.