lexical_util/
iterator.rs

1//! Specialized iterator traits.
2//!
3//! The traits are iterable, and provide optimizations for contiguous
4//! iterators, while still working for non-contiguous data.
5
6#![cfg(feature = "parse")]
7
8// Re-export our digit iterators.
9#[cfg(not(feature = "format"))]
10pub use crate::noskip::{AsBytes, Bytes};
11
12#[cfg(feature = "format")]
13pub use crate::skip::{AsBytes, Bytes};
14
15/// Iterator over a contiguous block of bytes.
16///
17/// This allows us to convert to-and-from-slices, raw pointers, and
18/// peek/query the data from either end cheaply.
19///
20/// A default implementation is provided for slice iterators.
21/// This trait **should never** return `null` from `as_ptr`, or be
22/// implemented for non-contiguous data.
23pub trait BytesIter<'a>: Iterator<Item = &'a u8> {
24    /// Determine if each yielded value is adjacent in memory.
25    const IS_CONTIGUOUS: bool;
26
27    /// Get a ptr to the current start of the iterator.
28    fn as_ptr(&self) -> *const u8;
29
30    /// Get a slice to the current start of the iterator.
31    fn as_slice(&self) -> &'a [u8];
32
33    /// Get the total number of elements in the underlying slice.
34    fn length(&self) -> usize;
35
36    /// Get the current index of the iterator in the slice.
37    fn cursor(&self) -> usize;
38
39    /// Set the current index of the iterator in the slice.
40    ///
41    /// # Safety
42    ///
43    /// Safe if `index <= self.length()`.
44    unsafe fn set_cursor(&mut self, index: usize);
45
46    /// Get the current number of values returned by the iterator.
47    fn current_count(&self) -> usize;
48
49    /// Get if the iterator cannot return any more elements.
50    ///
51    /// This may advance the internal iterator state, but not
52    /// modify the next returned value.
53    #[allow(clippy::wrong_self_convention)]
54    fn is_consumed(&mut self) -> bool;
55
56    /// Get if the buffer underlying the iterator is empty.
57    ///
58    /// This might not be the same thing as `is_consumed`: `is_consumed`
59    /// checks if any more elements may be returned, which may require
60    /// peeking the next value. Consumed merely checks if the
61    /// iterator has an empty slice. It is effectively a cheaper,
62    /// but weaker variant of `is_consumed()`.
63    fn is_done(&self) -> bool;
64
65    /// Determine if the iterator is contiguous.
66    #[inline]
67    fn is_contiguous(&self) -> bool {
68        Self::IS_CONTIGUOUS
69    }
70
71    /// Peek the next value of the iterator, without checking bounds.
72    ///
73    /// # Safety
74    ///
75    /// Safe as long as there is at least a single valid value left in
76    /// the iterator. Note that the behavior of this may lead to out-of-bounds
77    /// access (for contiguous iterators) or panics (for non-contiguous
78    /// iterators).
79    unsafe fn peek_unchecked(&mut self) -> Self::Item;
80
81    /// Peek the next value of the iterator, without consuming it.
82    fn peek(&mut self) -> Option<Self::Item>;
83
84    /// Check if the next element is a given value.
85    #[inline]
86    fn peek_is(&mut self, value: u8) -> bool {
87        if let Some(&c) = self.peek() {
88            c == value
89        } else {
90            false
91        }
92    }
93
94    /// Check if the next element is a given value without case sensitivity.
95    #[inline]
96    fn case_insensitive_peek_is(&mut self, value: u8) -> bool {
97        if let Some(&c) = self.peek() {
98            c.to_ascii_lowercase() == value.to_ascii_lowercase()
99        } else {
100            false
101        }
102    }
103
104    /// Skip zeros from the start of the iterator
105    #[inline]
106    fn skip_zeros(&mut self) -> usize {
107        let start = self.cursor();
108        while let Some(&b'0') = self.peek() {
109            self.next();
110        }
111        self.cursor() - start
112    }
113
114    /// Read a value of a difference type from the iterator.
115    /// This advances the internal state of the iterator.
116    ///
117    /// # Safety
118    ///
119    /// Safe as long as the number of the buffer is contains as least as
120    /// many bytes as the size of V.
121    unsafe fn read_unchecked<V>(&self) -> V;
122
123    /// Try to read a value of a different type from the iterator.
124    /// This advances the internal state of the iterator.
125    fn read<V>(&self) -> Option<V>;
126
127    /// Advance the internal slice by `N` elements.
128    ///
129    /// # Safety
130    ///
131    /// As long as the iterator is at least `N` elements, this
132    /// is safe.
133    unsafe fn step_by_unchecked(&mut self, count: usize);
134
135    /// Advance the internal slice by 1 element.
136    ///
137    /// # Safety
138    ///
139    /// Safe as long as the iterator is not empty.
140    #[inline]
141    unsafe fn step_unchecked(&mut self) {
142        unsafe { self.step_by_unchecked(1) };
143    }
144}