lexical_util/skip.rs
1//! An iterator that skips values equal to a provided value.
2//!
3//! Iterators over a contiguous slice, returning all values
4//! except for those matching the provided skip value.
5//!
6//! # Complexity
7//!
8//! Although superficially quite simple, the level of complexity
9//! introduced by digit separators can be quite complex, due
10//! the number of permutations during parsing.
11//!
12//! We can consume any combinations of of \[0,3\] items from the following set:
13//! - \[l\]eading digit separators, where digit separators occur before digits.
14//! - \[i\]nternal digit separators, where digit separators occur between digits.
15//! - \[t\]railing digit separators, where digit separators occur after digits.
16//!
17//! In addition to those combinations, we can also have:
18//! - \[c\]onsecutive digit separators, which allows two digit separators to be adjacent.
19//!
20//! # Shorthand
21//!
22//! We will use the term consumer to denote a function that consumes digits,
23//! splitting an input buffer at an index, where the leading section contains
24//! valid input digits, and the trailing section contains invalid characters.
25//! Due to the number of combinations for consumers, we use the following
26//! shorthand to denote consumers:
27//! - `no`, does not use a digit separator.
28//! - `l`, consumes leading digit separators.
29//! - `i`, consumes internal digit separators.
30//! - `t`, consumes trailing digit separators.
31//! - `c`, consumes consecutive digit separators.
32//!
33//! The `next`/`iter` algorithms are therefore named `next_x`, where `x`
34//! represents the shorthand name of the consumer, in sorted order.
35//! For example, `next_ilt` means that consumer can skip internal,
36//! leading, and trailing digit separators, but not consecutive ones.
37
38#![cfg(all(feature = "format", feature = "parse"))]
39
40use crate::digit::char_is_digit_const;
41use crate::format::NumberFormat;
42use crate::format_flags as flags;
43use crate::iterator::BytesIter;
44use core::{mem, ptr};
45
46// PEEK
47// ----
48
49/// Determine if the digit separator is internal.
50///
51/// Preconditions: Assumes `slc[index]` is a digit separator.
52/// The compiler optimizes this pretty well: it's almost as efficient as
53/// optimized assembly without bounds checking.
54macro_rules! is_i {
55 ($self:ident) => {
56 !is_l!($self) && !is_t!($self)
57 };
58}
59
60/// Determine if the digit separator is leading.
61///
62/// Preconditions: Assumes `slc[index]` is a digit separator.
63/// The compiler optimizes this pretty well: it's almost as efficient as
64/// optimized assembly without bounds checking.
65macro_rules! is_l {
66 ($self:ident) => {{
67 // Consume any digit separators before the current one.
68 let mut index = $self.byte.index;
69 while index > 0
70 && $self.byte.slc.get(index - 1).map_or(false, |&x| $self.is_digit_separator(x))
71 {
72 index -= 1;
73 }
74
75 // True if there are no items before the digit separator, or character
76 // before the digit separators is not a digit.
77 index == 0 || !$self.byte.slc.get(index - 1).map_or(false, |&x| $self.is_digit(x))
78 }};
79}
80
81/// Determine if the digit separator is trailing.
82///
83/// Preconditions: Assumes `slc[index]` is a digit separator.
84/// The compiler optimizes this pretty well: it's almost as efficient as
85/// optimized assembly without bounds checking.
86macro_rules! is_t {
87 ($self:ident) => {{
88 // Consume any digit separators after the current one.
89 let mut index = $self.byte.index;
90 while index < $self.byte.slc.len()
91 && $self.byte.slc.get(index + 1).map_or(false, |&x| $self.is_digit_separator(x))
92 {
93 index += 1;
94 }
95
96 index == $self.byte.slc.len()
97 || !$self.byte.slc.get(index + 1).map_or(false, |&x| $self.is_digit(x))
98 }};
99}
100
101/// Determine if the digit separator is leading or internal.
102///
103/// Preconditions: Assumes `slc[index]` is a digit separator.
104macro_rules! is_il {
105 ($self:ident) => {
106 is_l!($self) || !is_t!($self)
107 };
108}
109
110/// Determine if the digit separator is internal or trailing.
111///
112/// Preconditions: Assumes `slc[index]` is a digit separator.
113macro_rules! is_it {
114 ($self:ident) => {
115 is_t!($self) || !is_l!($self)
116 };
117}
118
119/// Determine if the digit separator is leading or trailing.
120///
121/// Preconditions: Assumes `slc[index]` is a digit separator.
122macro_rules! is_lt {
123 ($self:ident) => {
124 is_l!($self) || is_t!($self)
125 };
126}
127
128/// Determine if the digit separator is internal, leading, or trailing.
129macro_rules! is_ilt {
130 ($self:ident) => {
131 true
132 };
133}
134
135/// Consumes 1 or more digit separators.
136/// Peeks the next token that's not a digit separator.
137macro_rules! peek_1 {
138 ($self:ident, $is_skip:ident) => {{
139 // This will consume consecutive digit separators.
140 let value = $self.byte.slc.get($self.byte.index)?;
141 let is_digit_separator = $self.is_digit_separator(*value);
142 if is_digit_separator && $is_skip!($self) {
143 // Have a skippable digit separator: keep incrementing until we find
144 // a non-digit separator character. Don't need any complex checks
145 // here, since we've already done them above.
146 let mut index = $self.byte.index + 1;
147 while index < $self.length()
148 && $self.byte.slc.get(index).map_or(false, |&x| $self.is_digit_separator(x))
149 {
150 index += 1;
151 }
152 $self.byte.index = index;
153 $self.byte.slc.get($self.byte.index)
154 } else {
155 // Have 1 of 2 conditions:
156 // 1. A non-digit separator character.
157 // 2. A digit separator that is not valid in the context.
158 Some(value)
159 }
160 }};
161}
162
163/// Consumes 1 or more digit separators.
164/// Peeks the next token that's not a digit separator.
165macro_rules! peek_n {
166 ($self:ident, $is_skip:ident) => {{
167 // This will consume consecutive digit separators.
168 let value = $self.byte.slc.get($self.byte.index)?;
169 let is_digit_separator = $self.is_digit_separator(*value);
170 if is_digit_separator && $is_skip!($self) {
171 // Have a skippable digit separator: keep incrementing until we find
172 // a non-digit separator character. Don't need any complex checks
173 // here, since we've already done them above.
174 let mut index = $self.byte.index + 1;
175 while index < $self.byte.slc.len()
176 && $self.byte.slc.get(index).map_or(false, |&x| $self.is_digit_separator(x))
177 {
178 index += 1;
179 }
180 $self.byte.index = index;
181 $self.byte.slc.get($self.byte.index)
182 } else {
183 // Have 1 of 2 conditions:
184 // 1. A non-digit separator character.
185 // 2. A digit separator that is not valid in the context.
186 Some(value)
187 }
188 }};
189}
190
191/// Consumes no digit separators and peeks the next value.
192macro_rules! peek_noskip {
193 ($self:ident) => {
194 $self.byte.slc.get($self.byte.index)
195 };
196}
197
198/// Consumes at most 1 leading digit separator and peeks the next value.
199macro_rules! peek_l {
200 ($self:ident) => {
201 peek_1!($self, is_l)
202 };
203}
204
205/// Consumes at most 1 internal digit separator and peeks the next value.
206macro_rules! peek_i {
207 ($self:ident) => {
208 peek_1!($self, is_i)
209 };
210}
211
212/// Consumes at most 1 trailing digit separator and peeks the next value.
213macro_rules! peek_t {
214 ($self:ident) => {
215 peek_1!($self, is_t)
216 };
217}
218
219/// Consumes at most 1 internal/leading digit separator and peeks the next value.
220macro_rules! peek_il {
221 ($self:ident) => {
222 peek_1!($self, is_il)
223 };
224}
225
226/// Consumes at most 1 internal/trailing digit separator and peeks the next value.
227macro_rules! peek_it {
228 ($self:ident) => {
229 peek_1!($self, is_it)
230 };
231}
232
233/// Consumes at most 1 leading/trailing digit separator and peeks the next value.
234macro_rules! peek_lt {
235 ($self:ident) => {
236 peek_1!($self, is_lt)
237 };
238}
239
240/// Consumes at most 1 digit separator and peeks the next value.
241macro_rules! peek_ilt {
242 ($self:ident) => {
243 peek_1!($self, is_ilt)
244 };
245}
246
247/// Consumes 1 or more leading digit separators and peeks the next value.
248macro_rules! peek_lc {
249 ($self:ident) => {
250 peek_n!($self, is_l)
251 };
252}
253
254/// Consumes 1 or more internal digit separators and peeks the next value.
255macro_rules! peek_ic {
256 ($self:ident) => {
257 peek_n!($self, is_i)
258 };
259}
260
261/// Consumes 1 or more trailing digit separators and peeks the next value.
262macro_rules! peek_tc {
263 ($self:ident) => {
264 peek_n!($self, is_t)
265 };
266}
267
268/// Consumes 1 or more internal/leading digit separators and peeks the next value.
269macro_rules! peek_ilc {
270 ($self:ident) => {
271 peek_n!($self, is_il)
272 };
273}
274
275/// Consumes 1 or more internal/trailing digit separators and peeks the next value.
276macro_rules! peek_itc {
277 ($self:ident) => {
278 peek_n!($self, is_it)
279 };
280}
281
282/// Consumes 1 or more leading/trailing digit separators and peeks the next value.
283macro_rules! peek_ltc {
284 ($self:ident) => {
285 peek_n!($self, is_lt)
286 };
287}
288
289/// Consumes 1 or more digit separators and peeks the next value.
290macro_rules! peek_iltc {
291 ($self:ident) => {{
292 loop {
293 let value = $self.byte.slc.get($self.byte.index)?;
294 if !$self.is_digit_separator(*value) {
295 return Some(value);
296 }
297 $self.byte.index += 1;
298 }
299 }};
300}
301
302// AS DIGITS
303// ---------
304
305/// Trait to simplify creation of a `Bytes` object.
306pub trait AsBytes<'a> {
307 /// Create `Bytes` from object.
308 fn bytes<const FORMAT: u128>(&'a self) -> Bytes<'a, FORMAT>;
309}
310
311impl<'a> AsBytes<'a> for [u8] {
312 #[inline]
313 fn bytes<const FORMAT: u128>(&'a self) -> Bytes<'a, FORMAT> {
314 Bytes::new(self)
315 }
316}
317
318// DIGITS
319// ------
320
321/// Slice iterator that skips characters matching a given value.
322///
323/// This wraps an iterator over a contiguous block of memory,
324/// and only returns values that are not equal to skip.
325///
326/// The format allows us to dictate the actual behavior of
327/// the iterator: in what contexts does it skip digit separators.
328///
329/// `FORMAT` is required to tell us what the digit separator is, and where
330/// the digit separators are allowed, as well tell us the radix.
331/// The radix is required to allow us to differentiate digit from
332/// non-digit characters (see [DigitSeparators](/docs/DigitSeparators.md)
333/// for a detailed explanation on why).
334#[derive(Clone)]
335pub struct Bytes<'a, const FORMAT: u128> {
336 /// The raw slice for the iterator.
337 slc: &'a [u8],
338 /// Current index of the iterator in the slice.
339 index: usize,
340 /// The current count of values returned by the iterator.
341 /// This is only used if the iterator is not contiguous.
342 count: usize,
343}
344
345impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> {
346 /// If each yielded value is adjacent in memory.
347 pub const IS_CONTIGUOUS: bool = NumberFormat::<{ FORMAT }>::DIGIT_SEPARATOR == 0;
348
349 /// Create new byte object.
350 #[inline]
351 pub fn new(slc: &'a [u8]) -> Self {
352 Self {
353 slc,
354 index: 0,
355 count: 0,
356 }
357 }
358
359 /// Get a ptr to the current start of the iterator.
360 #[inline]
361 pub fn as_ptr(&self) -> *const u8 {
362 self.as_slice().as_ptr()
363 }
364
365 /// Get a slice to the current start of the iterator.
366 #[inline]
367 pub fn as_slice(&self) -> &'a [u8] {
368 // SAFETY: safe since index must be in range
369 unsafe { self.slc.get_unchecked(self.index..) }
370 }
371
372 /// Get the total number of elements in the underlying slice.
373 #[inline]
374 pub fn length(&self) -> usize {
375 self.slc.len()
376 }
377
378 /// Get the current index of the iterator in the slice.
379 #[inline]
380 pub fn cursor(&self) -> usize {
381 self.index
382 }
383
384 /// Set the current index of the iterator in the slice.
385 ///
386 /// # Safety
387 ///
388 /// Safe if `index <= self.length()`.
389 #[inline]
390 pub unsafe fn set_cursor(&mut self, index: usize) {
391 debug_assert!(index <= self.length());
392 self.index = index
393 }
394
395 /// Get the current number of values returned by the iterator.
396 #[inline]
397 pub fn current_count(&self) -> usize {
398 // If the buffer is contiguous, then we don't need to track the
399 // number of values: the current index is enough.
400 if Self::IS_CONTIGUOUS {
401 self.index
402 } else {
403 self.count
404 }
405 }
406
407 /// Get if the buffer underlying the iterator is empty.
408 ///
409 /// This might not be the same thing as `is_consumed`: `is_consumed`
410 /// checks if any more elements may be returned, which may require
411 /// peeking the next value. Consumed merely checks if the
412 /// iterator has an empty slice. It is effectively a cheaper,
413 /// but weaker variant of `is_consumed()`.
414 #[inline]
415 pub fn is_done(&self) -> bool {
416 self.index >= self.slc.len()
417 }
418
419 // Determine if the abstraction is contiguous.
420 #[inline]
421 pub fn is_contiguous(&self) -> bool {
422 Self::IS_CONTIGUOUS
423 }
424
425 /// Read a value of a difference type from the iterator.
426 /// This advances the internal state of the iterator.
427 ///
428 /// # Safety
429 ///
430 /// Safe as long as the number of the buffer is contains as least as
431 /// many bytes as the size of V.
432 #[inline]
433 pub unsafe fn read_unchecked<V>(&self) -> V {
434 debug_assert!(Self::IS_CONTIGUOUS);
435 debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
436
437 let slc = self.as_slice();
438 // SAFETY: safe as long as the slice has at least count elements.
439 unsafe { ptr::read_unaligned::<V>(slc.as_ptr() as *const _) }
440 }
441
442 /// Try to read a value of a different type from the iterator.
443 /// This advances the internal state of the iterator.
444 #[inline]
445 pub fn read<V>(&self) -> Option<V> {
446 if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<V>() {
447 // SAFETY: safe since we've guaranteed the buffer is greater than
448 // the number of elements read.
449 unsafe { Some(self.read_unchecked()) }
450 } else {
451 None
452 }
453 }
454
455 /// Check if the next element is a given value.
456 #[inline]
457 pub fn first_is(&mut self, value: u8) -> bool {
458 // Don't assert not a digit separator, since this can occur when
459 // a different component does not allow digit separators there.
460 if let Some(&c) = self.slc.get(self.index) {
461 c == value
462 } else {
463 false
464 }
465 }
466
467 /// Check if the next element is a given value without case sensitivity.
468 #[inline]
469 pub fn case_insensitive_first_is(&mut self, value: u8) -> bool {
470 // Don't assert not a digit separator, since this can occur when
471 // a different component does not allow digit separators there.
472 if let Some(&c) = self.slc.get(self.index) {
473 c.to_ascii_lowercase() == value.to_ascii_lowercase()
474 } else {
475 false
476 }
477 }
478
479 /// Get iterator over integer digits.
480 #[inline]
481 pub fn integer_iter<'b>(&'b mut self) -> IntegerBytesIterator<'a, 'b, FORMAT> {
482 IntegerBytesIterator {
483 byte: self,
484 }
485 }
486
487 /// Get iterator over fraction digits.
488 #[inline]
489 pub fn fraction_iter<'b>(&'b mut self) -> FractionBytesIterator<'a, 'b, FORMAT> {
490 FractionBytesIterator {
491 byte: self,
492 }
493 }
494
495 /// Get iterator over exponent digits.
496 #[inline]
497 pub fn exponent_iter<'b>(&'b mut self) -> ExponentBytesIterator<'a, 'b, FORMAT> {
498 ExponentBytesIterator {
499 byte: self,
500 }
501 }
502
503 /// Get iterator over special floating point values.
504 #[inline]
505 pub fn special_iter<'b>(&'b mut self) -> SpecialBytesIterator<'a, 'b, FORMAT> {
506 SpecialBytesIterator {
507 byte: self,
508 }
509 }
510
511 /// Advance the byte by `N` elements.
512 ///
513 /// # Safety
514 ///
515 /// As long as the iterator is at least `N` elements, this
516 /// is safe.
517 #[inline]
518 pub unsafe fn step_by_unchecked(&mut self, count: usize) {
519 if Self::IS_CONTIGUOUS {
520 // Contiguous, can skip most of these checks.
521 debug_assert!(self.as_slice().len() >= count);
522 } else {
523 // Since this isn't contiguous, it only works
524 // if the value is in the range `[0, 1]`.
525 // We also need to make sure the **current** value
526 // isn't a digit separator.
527 let format = NumberFormat::<{ FORMAT }> {};
528 debug_assert!(self.as_slice().len() >= count);
529 debug_assert!(count == 0 || count == 1);
530 debug_assert!(
531 count == 0 || self.slc.get(self.index) != Some(&format.digit_separator())
532 );
533 }
534 self.index += count;
535 if !Self::IS_CONTIGUOUS {
536 // Only increment the count if it's not contiguous, otherwise,
537 // this is an unnecessary performance penalty.
538 self.count += count;
539 }
540 }
541
542 /// Advance the byte by 1 element.
543 ///
544 /// # Safety
545 ///
546 /// Safe as long as the iterator is not empty.
547 #[inline]
548 pub unsafe fn step_unchecked(&mut self) {
549 debug_assert!(!self.as_slice().is_empty());
550 // SAFETY: safe if `self.index < self.length()`.
551 unsafe { self.step_by_unchecked(1) };
552 }
553}
554
555// ITERATOR HELPERS
556// ----------------
557
558/// Create skip iterator definition.
559macro_rules! skip_iterator {
560 ($iterator:ident, $doc:literal) => {
561 #[doc = $doc]
562 pub struct $iterator<'a: 'b, 'b, const FORMAT: u128> {
563 /// The internal byte object for the skip iterator.
564 byte: &'b mut Bytes<'a, FORMAT>,
565 }
566 };
567}
568
569macro_rules! is_digit_separator {
570 ($format:ident) => {
571 /// Determine if the character is a digit separator.
572 pub const fn is_digit_separator(&self, value: u8) -> bool {
573 let format = NumberFormat::<{ $format }> {};
574 let digit_separator = format.digit_separator();
575 if digit_separator == 0 {
576 // Check at compile time if we have an invalid digit separator.
577 // b'\x00', or the NUL character, is this invalid value.
578 false
579 } else {
580 value == digit_separator
581 }
582 }
583 };
584}
585
586/// Create impl block for skip iterator.
587macro_rules! skip_iterator_impl {
588 ($iterator:ident, $radix_cb:ident) => {
589 impl<'a: 'b, 'b, const FORMAT: u128> $iterator<'a, 'b, FORMAT> {
590 is_digit_separator!(FORMAT);
591
592 /// Determine if the character is a digit.
593 pub const fn is_digit(&self, value: u8) -> bool {
594 let format = NumberFormat::<{ FORMAT }> {};
595 char_is_digit_const(value, format.$radix_cb())
596 }
597 }
598 };
599}
600
601/// Create impl Iterator block for skip iterator.
602macro_rules! skip_iterator_iterator_impl {
603 ($iterator:ident) => {
604 impl<'a: 'b, 'b, const FORMAT: u128> Iterator for $iterator<'a, 'b, FORMAT> {
605 type Item = &'a u8;
606
607 #[inline]
608 fn next(&mut self) -> Option<Self::Item> {
609 // Peek will handle everything properly internally.
610 let value = self.peek()?;
611 // Increment the index so we know not to re-fetch it.
612 self.byte.index += 1;
613 if !Self::IS_CONTIGUOUS {
614 // Only increment the count if it's not contiguous, otherwise,
615 // this is an unnecessary performance penalty.
616 self.byte.count += 1;
617 }
618 Some(value)
619 }
620 }
621 };
622}
623
624/// Create base methods for the ByteIter block of a skip iterator.
625macro_rules! skip_iterator_byteiter_base {
626 ($format:ident, $mask:ident) => {
627 // It's contiguous if we don't skip over any values.
628 // IE, the digit separator flags for the iterator over
629 // the digits doesn't skip any values.
630 const IS_CONTIGUOUS: bool = $format & flags::$mask == 0;
631
632 #[inline]
633 fn as_ptr(&self) -> *const u8 {
634 self.byte.as_ptr()
635 }
636
637 #[inline]
638 fn as_slice(&self) -> &'a [u8] {
639 self.byte.as_slice()
640 }
641
642 #[inline]
643 fn length(&self) -> usize {
644 self.byte.length()
645 }
646
647 #[inline]
648 fn cursor(&self) -> usize {
649 self.byte.cursor()
650 }
651
652 #[inline]
653 unsafe fn set_cursor(&mut self, index: usize) {
654 debug_assert!(index <= self.length());
655 // SAFETY: safe if `index <= self.length()`.
656 unsafe { self.byte.set_cursor(index) };
657 }
658
659 #[inline]
660 fn current_count(&self) -> usize {
661 self.byte.current_count()
662 }
663
664 #[inline]
665 fn is_consumed(&mut self) -> bool {
666 self.peek().is_none()
667 }
668
669 #[inline]
670 fn is_done(&self) -> bool {
671 self.byte.is_done()
672 }
673
674 #[inline]
675 fn is_contiguous(&self) -> bool {
676 Self::IS_CONTIGUOUS
677 }
678
679 #[inline]
680 unsafe fn peek_unchecked(&mut self) -> <Self as Iterator>::Item {
681 self.peek().unwrap()
682 }
683
684 #[inline]
685 unsafe fn read_unchecked<V>(&self) -> V {
686 debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
687 // SAFETY: safe as long as the slice has at least count elements.
688 unsafe { self.byte.read_unchecked() }
689 }
690
691 #[inline]
692 fn read<V>(&self) -> Option<V> {
693 self.byte.read()
694 }
695
696 #[inline]
697 unsafe fn step_by_unchecked(&mut self, count: usize) {
698 debug_assert!(self.as_slice().len() >= count);
699 // SAFETY: safe as long as `slc.len() >= count`.
700 unsafe { self.byte.step_by_unchecked(count) }
701 }
702 };
703}
704
705/// Create impl ByteIter block for skip iterator.
706macro_rules! skip_iterator_byteiter_impl {
707 ($iterator:ident, $mask:ident, $i:ident, $l:ident, $t:ident, $c:ident) => {
708 impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for $iterator<'a, 'b, FORMAT> {
709 skip_iterator_byteiter_base!(FORMAT, $mask);
710
711 /// Peek the next value of the iterator, without consuming it.
712 #[inline]
713 fn peek(&mut self) -> Option<<Self as Iterator>::Item> {
714 let format = NumberFormat::<{ FORMAT }> {};
715 const IL: u128 = flags::$i | flags::$l;
716 const IT: u128 = flags::$i | flags::$t;
717 const LT: u128 = flags::$l | flags::$t;
718 const ILT: u128 = flags::$i | flags::$l | flags::$t;
719 const IC: u128 = flags::$i | flags::$c;
720 const LC: u128 = flags::$l | flags::$c;
721 const TC: u128 = flags::$t | flags::$c;
722 const ILC: u128 = IL | flags::$c;
723 const ITC: u128 = IT | flags::$c;
724 const LTC: u128 = LT | flags::$c;
725 const ILTC: u128 = ILT | flags::$c;
726
727 match format.digit_separator_flags() & flags::$mask {
728 0 => peek_noskip!(self),
729 flags::$i => peek_i!(self),
730 flags::$l => peek_l!(self),
731 flags::$t => peek_t!(self),
732 IL => peek_il!(self),
733 IT => peek_it!(self),
734 LT => peek_lt!(self),
735 ILT => peek_ilt!(self),
736 IC => peek_ic!(self),
737 LC => peek_lc!(self),
738 TC => peek_tc!(self),
739 ILC => peek_ilc!(self),
740 ITC => peek_itc!(self),
741 LTC => peek_ltc!(self),
742 ILTC => peek_iltc!(self),
743 _ => unreachable!(),
744 }
745 }
746 }
747 };
748}
749
750// INTEGER DIGITS ITERATOR
751// -----------------------
752
753skip_iterator!(IntegerBytesIterator, "Iterator that skips over digit separators in the integer.");
754skip_iterator_impl!(IntegerBytesIterator, mantissa_radix);
755skip_iterator_iterator_impl!(IntegerBytesIterator);
756skip_iterator_byteiter_impl!(
757 IntegerBytesIterator,
758 INTEGER_DIGIT_SEPARATOR_FLAG_MASK,
759 INTEGER_INTERNAL_DIGIT_SEPARATOR,
760 INTEGER_LEADING_DIGIT_SEPARATOR,
761 INTEGER_TRAILING_DIGIT_SEPARATOR,
762 INTEGER_CONSECUTIVE_DIGIT_SEPARATOR
763);
764
765// FRACTION DIGITS ITERATOR
766// ------------------------
767
768skip_iterator!(FractionBytesIterator, "Iterator that skips over digit separators in the fraction.");
769skip_iterator_impl!(FractionBytesIterator, mantissa_radix);
770skip_iterator_iterator_impl!(FractionBytesIterator);
771skip_iterator_byteiter_impl!(
772 FractionBytesIterator,
773 FRACTION_DIGIT_SEPARATOR_FLAG_MASK,
774 FRACTION_INTERNAL_DIGIT_SEPARATOR,
775 FRACTION_LEADING_DIGIT_SEPARATOR,
776 FRACTION_TRAILING_DIGIT_SEPARATOR,
777 FRACTION_CONSECUTIVE_DIGIT_SEPARATOR
778);
779
780// EXPONENT DIGITS ITERATOR
781// ------------------------
782
783skip_iterator!(ExponentBytesIterator, "Iterator that skips over digit separators in the exponent.");
784skip_iterator_impl!(ExponentBytesIterator, exponent_radix);
785skip_iterator_iterator_impl!(ExponentBytesIterator);
786skip_iterator_byteiter_impl!(
787 ExponentBytesIterator,
788 EXPONENT_DIGIT_SEPARATOR_FLAG_MASK,
789 EXPONENT_INTERNAL_DIGIT_SEPARATOR,
790 EXPONENT_LEADING_DIGIT_SEPARATOR,
791 EXPONENT_TRAILING_DIGIT_SEPARATOR,
792 EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR
793);
794
795// SPECIAL DIGITS ITERATOR
796// -----------------------
797
798skip_iterator!(
799 SpecialBytesIterator,
800 "Iterator that skips over digit separators in special floats."
801);
802skip_iterator_iterator_impl!(SpecialBytesIterator);
803
804impl<'a: 'b, 'b, const FORMAT: u128> SpecialBytesIterator<'a, 'b, FORMAT> {
805 is_digit_separator!(FORMAT);
806}
807
808impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for SpecialBytesIterator<'a, 'b, FORMAT> {
809 skip_iterator_byteiter_base!(FORMAT, SPECIAL_DIGIT_SEPARATOR);
810
811 /// Peek the next value of the iterator, without consuming it.
812 #[inline]
813 fn peek(&mut self) -> Option<<Self as Iterator>::Item> {
814 let format = NumberFormat::<{ FORMAT }> {};
815 if format.special_digit_separator() {
816 peek_iltc!(self)
817 } else {
818 peek_noskip!(self)
819 }
820 }
821}