1#![cfg(all(feature = "parse", not(feature = "format")))]
7
8use core::{mem, ptr};
9
10use crate::digit::char_is_digit_const;
11use crate::format::NumberFormat;
12use crate::iterator::{DigitsIter, Iter};
13
14pub trait AsBytes<'a> {
19 fn bytes<const __: u128>(&'a self) -> Bytes<'a, __>;
21}
22
23impl<'a> AsBytes<'a> for [u8] {
24 #[inline(always)]
25 fn bytes<const __: u128>(&'a self) -> Bytes<'a, __> {
26 Bytes::new(self)
27 }
28}
29
30#[derive(Clone)]
35pub struct Bytes<'a, const __: u128> {
36 slc: &'a [u8],
38 index: usize,
40}
41
42impl<'a, const __: u128> Bytes<'a, __> {
43 #[inline(always)]
45 pub const fn new(slc: &'a [u8]) -> Self {
46 Self {
47 slc,
48 index: 0,
49 }
50 }
51
52 #[inline(always)]
60 #[allow(clippy::assertions_on_constants)] const unsafe fn from_parts(slc: &'a [u8], index: usize) -> Self {
62 debug_assert!(index <= slc.len());
63 debug_assert!(Self::IS_CONTIGUOUS);
64 Self {
65 slc,
66 index,
67 }
68 }
69
70 #[inline(always)]
72 pub fn integer_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
73 DigitsIterator {
74 byte: self,
75 }
76 }
77
78 #[inline(always)]
80 pub fn fraction_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
81 DigitsIterator {
82 byte: self,
83 }
84 }
85
86 #[inline(always)]
88 pub fn exponent_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
89 DigitsIterator {
90 byte: self,
91 }
92 }
93
94 #[inline(always)]
96 pub fn special_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
97 DigitsIterator {
98 byte: self,
99 }
100 }
101}
102
103unsafe impl<'a, const __: u128> Iter<'a> for Bytes<'a, __> {
104 const IS_CONTIGUOUS: bool = true;
105
106 #[inline(always)]
107 fn get_buffer(&self) -> &'a [u8] {
108 self.slc
109 }
110
111 #[inline(always)]
113 fn cursor(&self) -> usize {
114 self.index
115 }
116
117 #[inline(always)]
123 unsafe fn set_cursor(&mut self, index: usize) {
124 debug_assert!(index <= self.buffer_length());
125 self.index = index;
126 }
127
128 #[inline(always)]
135 fn current_count(&self) -> usize {
136 self.index
137 }
138
139 #[inline(always)]
140 #[allow(clippy::assertions_on_constants)] unsafe fn step_by_unchecked(&mut self, count: usize) {
142 assert!(Self::IS_CONTIGUOUS);
143 debug_assert!(self.as_slice().len() >= count);
144 self.index += count;
145 }
146
147 #[inline(always)]
148 #[allow(clippy::assertions_on_constants)] unsafe fn peek_many_unchecked<V>(&self) -> V {
150 debug_assert!(Self::IS_CONTIGUOUS);
151 debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
152
153 unsafe { ptr::read_unaligned::<V>(self.as_ptr() as *const _) }
155 }
156}
157
158pub struct DigitsIterator<'a: 'b, 'b, const __: u128> {
163 byte: &'b mut Bytes<'a, __>,
165}
166
167impl<'a: 'b, 'b, const __: u128> DigitsIterator<'a, 'b, __> {
168 #[inline(always)]
170 pub fn new(byte: &'b mut Bytes<'a, __>) -> Self {
171 Self {
172 byte,
173 }
174 }
175
176 #[cfg_attr(not(feature = "compact"), inline(always))]
182 #[allow(clippy::assertions_on_constants)] pub fn take_n(&mut self, n: usize) -> Option<Bytes<'a, __>> {
184 debug_assert!(Self::IS_CONTIGUOUS);
185 let end = self.byte.slc.len().min(n + self.cursor());
186 let slc: &[u8] = &self.byte.slc[..end];
188
189 unsafe {
193 let byte: Bytes<'_, __> = Bytes::from_parts(slc, self.cursor());
194 unsafe { self.set_cursor(end) };
195 Some(byte)
196 }
197 }
198}
199
200unsafe impl<'a: 'b, 'b, const __: u128> Iter<'a> for DigitsIterator<'a, 'b, __> {
201 const IS_CONTIGUOUS: bool = Bytes::<'a, __>::IS_CONTIGUOUS;
202
203 #[inline(always)]
204 fn get_buffer(&self) -> &'a [u8] {
205 self.byte.get_buffer()
206 }
207
208 #[inline(always)]
209 fn cursor(&self) -> usize {
210 self.byte.cursor()
211 }
212
213 #[inline(always)]
214 unsafe fn set_cursor(&mut self, index: usize) {
215 debug_assert!(index <= self.buffer_length());
216 unsafe { self.byte.set_cursor(index) };
218 }
219
220 #[inline(always)]
221 fn current_count(&self) -> usize {
222 self.byte.current_count()
223 }
224
225 #[inline(always)]
226 unsafe fn step_by_unchecked(&mut self, count: usize) {
227 debug_assert!(self.as_slice().len() >= count);
228 unsafe { self.byte.step_by_unchecked(count) }
230 }
231
232 #[inline(always)]
233 unsafe fn peek_many_unchecked<V>(&self) -> V {
234 debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
235 unsafe { self.byte.peek_many_unchecked() }
237 }
238}
239
240impl<'a: 'b, 'b, const FORMAT: u128> DigitsIter<'a> for DigitsIterator<'a, 'b, FORMAT> {
241 #[inline(always)]
242 fn is_consumed(&mut self) -> bool {
243 self.is_buffer_empty()
244 }
245
246 #[inline(always)]
248 fn increment_count(&mut self) {
249 }
250
251 #[inline(always)]
252 fn peek(&mut self) -> Option<<Self as Iterator>::Item> {
253 self.byte.slc.get(self.byte.index)
254 }
255
256 #[inline(always)]
258 fn is_digit(&self, value: u8) -> bool {
259 let format = NumberFormat::<{ FORMAT }> {};
260 char_is_digit_const(value, format.mantissa_radix())
261 }
262}
263
264impl<'a: 'b, 'b, const __: u128> Iterator for DigitsIterator<'a, 'b, __> {
265 type Item = &'a u8;
266
267 #[inline(always)]
268 fn next(&mut self) -> Option<Self::Item> {
269 let value = self.byte.slc.get(self.byte.index)?;
270 self.byte.index += 1;
271 Some(value)
272 }
273}
274
275impl<'a: 'b, 'b, const __: u128> ExactSizeIterator for DigitsIterator<'a, 'b, __> {
276 #[inline(always)]
277 fn len(&self) -> usize {
278 self.buffer_length() - self.cursor()
279 }
280}