1//! An iterator over a slice.
2//!
3//! This iterator has both the length of the original slice, as
4//! well as the current position of the iterator in the buffer.
56#![cfg(all(feature = "parse", not(feature = "format")))]
78use core::{mem, ptr};
910use crate::digit::char_is_digit_const;
11use crate::format::NumberFormat;
12use crate::iterator::{DigitsIter, Iter};
1314// AS DIGITS
15// ---------
1617/// Trait to simplify creation of a `Bytes` object.
18pub trait AsBytes<'a> {
19/// Create `Bytes` from object.
20fn bytes<const __: u128>(&'a self) -> Bytes<'a, __>;
21}
2223impl<'a> AsBytes<'a> for [u8] {
24#[inline(always)]
25fn bytes<const __: u128>(&'a self) -> Bytes<'a, __> {
26 Bytes::new(self)
27 }
28}
2930// DIGITS
31// ------
3233/// Slice iterator that stores the original length of the slice.
34#[derive(Clone)]
35pub struct Bytes<'a, const __: u128> {
36/// The raw slice for the iterator.
37slc: &'a [u8],
38/// Current index of the iterator in the slice.
39index: usize,
40}
4142impl<'a, const __: u128> Bytes<'a, __> {
43/// Create new byte object.
44#[inline(always)]
45pub const fn new(slc: &'a [u8]) -> Self {
46Self {
47 slc,
48 index: 0,
49 }
50 }
5152/// Initialize the slice from raw parts.
53 ///
54 /// # Safety
55 ///
56 /// This is safe if and only if the index is <= `slc.len()`.
57 /// For this reason, since it's easy to get wrong, we only
58 /// expose it to `DigitsIterator` and nothing else.
59#[inline(always)]
60 #[allow(clippy::assertions_on_constants)] // reason="ensuring safety invariants are valid"
61const unsafe fn from_parts(slc: &'a [u8], index: usize) -> Self {
62debug_assert!(index <= slc.len());
63debug_assert!(Self::IS_CONTIGUOUS);
64Self {
65 slc,
66 index,
67 }
68 }
6970/// Get iterator over integer digits.
71#[inline(always)]
72pub fn integer_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
73 DigitsIterator {
74 byte: self,
75 }
76 }
7778/// Get iterator over fraction digits.
79#[inline(always)]
80pub fn fraction_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
81 DigitsIterator {
82 byte: self,
83 }
84 }
8586/// Get iterator over exponent digits.
87#[inline(always)]
88pub fn exponent_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
89 DigitsIterator {
90 byte: self,
91 }
92 }
9394/// Get iterator over special floating point values.
95#[inline(always)]
96pub fn special_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
97 DigitsIterator {
98 byte: self,
99 }
100 }
101}
102103unsafe impl<'a, const __: u128> Iter<'a> for Bytes<'a, __> {
104const IS_CONTIGUOUS: bool = true;
105106#[inline(always)]
107fn get_buffer(&self) -> &'a [u8] {
108self.slc
109 }
110111/// Get the current index of the iterator in the slice.
112#[inline(always)]
113fn cursor(&self) -> usize {
114self.index
115 }
116117/// Set the current index of the iterator in the slice.
118 ///
119 /// # Safety
120 ///
121 /// Safe if `index <= self.buffer_length()`.
122#[inline(always)]
123unsafe fn set_cursor(&mut self, index: usize) {
124debug_assert!(index <= self.buffer_length());
125self.index = index;
126 }
127128/// Get the current number of digits returned by the iterator.
129 ///
130 /// For contiguous iterators, this can include the sign character, decimal
131 /// point, and the exponent sign (that is, it is always the cursor). For
132 /// non-contiguous iterators, this must always be the only the number of
133 /// digits returned.
134#[inline(always)]
135fn current_count(&self) -> usize {
136self.index
137 }
138139#[inline(always)]
140 #[allow(clippy::assertions_on_constants)] // reason="ensuring safety invariants are valid"
141unsafe fn step_by_unchecked(&mut self, count: usize) {
142assert!(Self::IS_CONTIGUOUS);
143debug_assert!(self.as_slice().len() >= count);
144self.index += count;
145 }
146147#[inline(always)]
148 #[allow(clippy::assertions_on_constants)] // reason="ensuring safety invariants are valid"
149unsafe fn peek_many_unchecked<V>(&self) -> V {
150debug_assert!(Self::IS_CONTIGUOUS);
151debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
152153// SAFETY: safe as long as the slice has at least count elements.
154unsafe { ptr::read_unaligned::<V>(self.as_ptr() as *const _) }
155 }
156}
157158// DIGITS ITERATOR
159// ---------------
160161/// Slice iterator that stores the original length of the slice.
162pub struct DigitsIterator<'a: 'b, 'b, const __: u128> {
163/// The internal byte object for the no-skip iterator.
164byte: &'b mut Bytes<'a, __>,
165}
166167impl<'a: 'b, 'b, const __: u128> DigitsIterator<'a, 'b, __> {
168/// Create a new digits iterator from the bytes underlying item.
169#[inline(always)]
170pub fn new(byte: &'b mut Bytes<'a, __>) -> Self {
171Self {
172 byte,
173 }
174 }
175176/// Take the first N digits from the iterator.
177 ///
178 /// This only takes the digits if we have a contiguous iterator.
179 /// It takes the digits, validating the bounds, and then advanced
180 /// the iterators state.
181#[cfg_attr(not(feature = "compact"), inline(always))]
182 #[allow(clippy::assertions_on_constants)] // reason="ensuring safety invariants are valid"
183pub fn take_n(&mut self, n: usize) -> Option<Bytes<'a, __>> {
184debug_assert!(Self::IS_CONTIGUOUS);
185let end = self.byte.slc.len().min(n + self.cursor());
186// NOTE: The compiler should be able to optimize this out.
187let slc: &[u8] = &self.byte.slc[..end];
188189// SAFETY: Safe since we just ensured the underlying slice has that count
190 // elements, so both the underlying slice for this and this **MUST**
191 // have at least count elements. We do static checking on the bounds for this.
192unsafe {
193let byte: Bytes<'_, __> = Bytes::from_parts(slc, self.cursor());
194unsafe { self.set_cursor(end) };
195Some(byte)
196 }
197 }
198}
199200unsafe impl<'a: 'b, 'b, const __: u128> Iter<'a> for DigitsIterator<'a, 'b, __> {
201const IS_CONTIGUOUS: bool = Bytes::<'a, __>::IS_CONTIGUOUS;
202203#[inline(always)]
204fn get_buffer(&self) -> &'a [u8] {
205self.byte.get_buffer()
206 }
207208#[inline(always)]
209fn cursor(&self) -> usize {
210self.byte.cursor()
211 }
212213#[inline(always)]
214unsafe fn set_cursor(&mut self, index: usize) {
215debug_assert!(index <= self.buffer_length());
216// SAFETY: safe if `index <= self.buffer_length()`.
217unsafe { self.byte.set_cursor(index) };
218 }
219220#[inline(always)]
221fn current_count(&self) -> usize {
222self.byte.current_count()
223 }
224225#[inline(always)]
226unsafe fn step_by_unchecked(&mut self, count: usize) {
227debug_assert!(self.as_slice().len() >= count);
228// SAFETY: safe as long as `slc.len() >= count`.
229unsafe { self.byte.step_by_unchecked(count) }
230 }
231232#[inline(always)]
233unsafe fn peek_many_unchecked<V>(&self) -> V {
234debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
235// SAFETY: safe as long as the slice has at least count elements.
236unsafe { self.byte.peek_many_unchecked() }
237 }
238}
239240impl<'a: 'b, 'b, const FORMAT: u128> DigitsIter<'a> for DigitsIterator<'a, 'b, FORMAT> {
241#[inline(always)]
242fn is_consumed(&mut self) -> bool {
243self.is_buffer_empty()
244 }
245246// Always a no-op
247#[inline(always)]
248fn increment_count(&mut self) {
249 }
250251#[inline(always)]
252fn peek(&mut self) -> Option<<Self as Iterator>::Item> {
253self.byte.slc.get(self.byte.index)
254 }
255256/// Determine if the character is a digit.
257#[inline(always)]
258fn is_digit(&self, value: u8) -> bool {
259let format = NumberFormat::<{ FORMAT }> {};
260 char_is_digit_const(value, format.mantissa_radix())
261 }
262}
263264impl<'a: 'b, 'b, const __: u128> Iterator for DigitsIterator<'a, 'b, __> {
265type Item = &'a u8;
266267#[inline(always)]
268fn next(&mut self) -> Option<Self::Item> {
269let value = self.byte.slc.get(self.byte.index)?;
270self.byte.index += 1;
271Some(value)
272 }
273}
274275impl<'a: 'b, 'b, const __: u128> ExactSizeIterator for DigitsIterator<'a, 'b, __> {
276#[inline(always)]
277fn len(&self) -> usize {
278self.buffer_length() - self.cursor()
279 }
280}