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}