#![cfg(all(feature = "format", any(feature = "parse-floats", feature = "parse-integers")))]
use core::{mem, ptr};
use crate::digit::char_is_digit_const;
use crate::format::NumberFormat;
use crate::format_flags as flags;
use crate::iterator::{DigitsIter, Iter};
macro_rules! indexing {
(@next $self:ident, $index:expr) => {
$index.wrapping_add(1)
};
(@nextc $self:ident, $index:expr) => {{
let mut index = $index;
let slc = $self.byte.slc;
while slc.get(index.wrapping_add(1)).map_or(false, |&x| $self.is_digit_separator(x)) {
index = index.wrapping_add(1);
}
index.wrapping_add(1)
}};
(@prev $self:ident, $index:expr) => {
$index.wrapping_sub(1)
};
(@prevc $self:ident, $index:expr) => {{
let mut index = $index;
let slc = $self.byte.slc;
while slc.get(index.wrapping_sub(1)).map_or(false, |&x| $self.is_digit_separator(x)) {
index = index.wrapping_sub(1);
}
index.wrapping_sub(1)
}};
}
macro_rules! is_i {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prev $self, $index);
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(prev).map_or(false, |&x| $self.is_digit(x)) &&
slc.get(next).map_or(false, |&x| $self.is_digit(x))
}};
(@first $self:ident) => {
is_i!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(false, |&x| $self.is_digit(x))
}};
(@internal $self:ident) => {
is_i!(@internal $self, $self.byte.index)
};
}
macro_rules! is_ic {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prevc $self, $index);
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
slc.get(prev).map_or(false, |&x| $self.is_digit(x)) &&
slc.get(next).map_or(false, |&x| $self.is_digit(x))
}};
(@first $self:ident) => {
is_ic!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(false, |&x| $self.is_digit(x))
}};
(@internal $self:ident) => {
is_ic!(@internal $self, $self.byte.index)
};
}
macro_rules! is_l {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prev $self, $index);
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(prev).map_or(true, |&x| !$self.is_digit(x) && !$self.is_digit_separator(x)) &&
slc.get(next).map_or(true, |&x| !$self.is_digit_separator(x))
}};
(@first $self:ident) => {
is_l!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
false
}};
(@internal $self:ident) => {
is_l!(@internal $self, $self.byte.index)
};
}
macro_rules! is_lc {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prevc $self, $index);
let slc = $self.byte.slc;
slc.get(prev).map_or(true, |&x| !$self.is_digit(x))
}};
(@first $self:ident) => {
is_lc!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
false
}};
(@internal $self:ident) => {
is_lc!(@internal $self, $self.byte.index)
};
}
macro_rules! is_t {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prev $self, $index);
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| !$self.is_digit(x) && !$self.is_digit_separator(x)) &&
slc.get(prev).map_or(true, |&x| !$self.is_digit_separator(x))
}};
(@first $self:ident) => {
is_t!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| !$self.is_digit(x) && !$self.is_digit_separator(x))
}};
(@internal $self:ident) => {
is_t!(@internal $self, $self.byte.index)
};
}
macro_rules! is_tc {
(@first $self:ident, $index:expr) => {{
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| !$self.is_digit(x))
}};
(@first $self:ident) => {
is_tc!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {
is_tc!(@first $self, $index)
};
(@internal $self:ident) => {
is_tc!(@internal $self, $self.byte.index)
};
}
macro_rules! is_il {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prev $self, $index);
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
if slc.get(prev).map_or(false, |&x| $self.is_digit(x)) {
slc.get(next).map_or(false, |&x| $self.is_digit(x))
} else {
slc.get(prev).map_or(true, |&x| !$self.is_digit_separator(x))
}
}};
(@first $self:ident) => {
is_il!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(false, |&x| $self.is_digit(x))
}};
(@internal $self:ident) => {
is_il!(@internal $self, $self.byte.index)
};
}
macro_rules! is_ilc {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prevc $self, $index);
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(false, |&x| $self.is_digit(x)) ||
slc.get(prev).map_or(true, |&x| !$self.is_digit(x))
}};
(@first $self:ident) => {
is_ilc!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| $self.is_digit(x))
}};
(@internal $self:ident) => {
is_ilc!(@internal $self, $self.byte.index)
};
}
macro_rules! is_it {
(@first$self:ident, $index:expr) => {{
let prev = indexing!(@prev $self, $index);
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
if slc.get(prev).map_or(false, |&x| $self.is_digit(x)) {
slc.get(next).map_or(true, |&x| !$self.is_digit_separator(x))
} else {
slc.get(next).map_or(true, |&x| !$self.is_digit(x) && !$self.is_digit_separator(x))
}
}};
(@first$self:ident) => {
is_it!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| !$self.is_digit_separator(x))
}};
(@internal $self:ident) => {
is_it!(@internal $self, $self.byte.index)
};
}
macro_rules! is_itc {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prevc $self, $index);
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
slc.get(prev).map_or(false, |&x| !$self.is_digit(x)) ||
slc.get(next).map_or(true, |&x| !$self.is_digit(x))
}};
(@first $self:ident) => {
is_itc!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {
true
};
(@internal $self:ident) => {
is_itc!(@internal $self, $self.byte.index)
};
}
macro_rules! is_lt {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prev $self, $index);
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
let prev_value = slc.get(prev);
let next_value = slc.get(next);
let is_prev_sep = prev_value.map_or(false, |&x| $self.is_digit_separator(x));
let is_prev_dig = prev_value.map_or(false, |&x| $self.is_digit(x));
let is_next_sep = next_value.map_or(false, |&x| $self.is_digit_separator(x));
let is_next_dig = next_value.map_or(false, |&x| $self.is_digit(x));
!is_prev_sep && !is_next_sep && !(is_prev_dig && is_next_dig)
}};
(@first $self:ident) => {
is_lt!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| !$self.is_digit(x) && !$self.is_digit_separator(x))
}};
(@internal $self:ident) => {
is_lt!(@internal $self, $self.byte.index)
};
}
macro_rules! is_ltc {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prevc $self, $index);
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
!(slc.get(prev).map_or(false, |&x| $self.is_digit(x)) && slc.get(next).map_or(false, |&x| $self.is_digit(x)))
}};
(@first $self:ident) => {
is_ltc!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@nextc $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| !$self.is_digit(x))
}};
(@internal $self:ident) => {
is_ltc!(@internal $self, $self.byte.index)
};
}
macro_rules! is_ilt {
(@first $self:ident, $index:expr) => {{
let prev = indexing!(@prev $self, $index);
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
!slc.get(next).map_or(false, |&x| $self.is_digit_separator(x)) &&
!slc.get(prev).map_or(false, |&x| $self.is_digit_separator(x))
}};
(@first $self:ident) => {
is_ilt!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {{
let next = indexing!(@next $self, $index);
let slc = $self.byte.slc;
slc.get(next).map_or(true, |&x| !$self.is_digit_separator(x))
}};
(@internal $self:ident) => {
is_ilt!(@internal $self, $self.byte.index)
};
}
macro_rules! is_iltc {
(@first $self:ident, $index:expr) => {
true
};
(@first $self:ident) => {
is_iltc!(@first $self, $self.byte.index)
};
(@internal $self:ident, $index:expr) => {
true
};
(@internal $self:ident) => {
is_iltc!(@internal $self, $self.byte.index)
};
}
macro_rules! peek_1 {
($self:ident, $is_skip:ident) => {{
let index = $self.cursor();
let buffer = $self.get_buffer();
let value = buffer.get(index)?;
let is_digit_separator = $self.is_digit_separator(*value);
if is_digit_separator {
let is_skip = if $self.current_count() == 0 {
$is_skip!(@first $self)
} else {
$is_skip!(@internal $self)
};
if is_skip {
unsafe { $self.set_cursor(index + 1) };
buffer.get(index + 1)
} else {
Some(value)
}
} else {
Some(value)
}
}};
}
macro_rules! peek_n {
($self:ident, $is_skip:ident) => {{
let mut index = $self.cursor();
let buffer = $self.get_buffer();
let value = buffer.get(index)?;
let is_digit_separator = $self.is_digit_separator(*value);
if is_digit_separator {
let is_skip = if $self.current_count() == 0 {
$is_skip!(@first $self)
} else {
$is_skip!(@internal $self)
};
if is_skip {
index += 1;
while index < buffer.len()
&& buffer.get(index).map_or(false, |&x| $self.is_digit_separator(x))
{
index += 1;
}
unsafe { $self.set_cursor(index) };
buffer.get(index)
} else {
Some(value)
}
} else {
Some(value)
}
}};
}
macro_rules! peek_noskip {
($self:ident) => {
$self.byte.slc.get($self.byte.index)
};
}
macro_rules! peek_l {
($self:ident) => {
peek_1!($self, is_l)
};
}
macro_rules! peek_i {
($self:ident) => {
peek_1!($self, is_i)
};
}
macro_rules! peek_t {
($self:ident) => {
peek_1!($self, is_t)
};
}
macro_rules! peek_il {
($self:ident) => {
peek_1!($self, is_il)
};
}
macro_rules! peek_it {
($self:ident) => {
peek_1!($self, is_it)
};
}
macro_rules! peek_lt {
($self:ident) => {
peek_1!($self, is_lt)
};
}
macro_rules! peek_ilt {
($self:ident) => {
peek_1!($self, is_ilt)
};
}
macro_rules! peek_lc {
($self:ident) => {
peek_n!($self, is_lc)
};
}
macro_rules! peek_ic {
($self:ident) => {
peek_n!($self, is_ic)
};
}
macro_rules! peek_tc {
($self:ident) => {
peek_n!($self, is_tc)
};
}
macro_rules! peek_ilc {
($self:ident) => {
peek_n!($self, is_ilc)
};
}
macro_rules! peek_itc {
($self:ident) => {
peek_n!($self, is_itc)
};
}
macro_rules! peek_ltc {
($self:ident) => {
peek_n!($self, is_ltc)
};
}
macro_rules! peek_iltc {
($self:ident) => {
peek_n!($self, is_iltc)
};
}
pub trait AsBytes<'a> {
fn bytes<const FORMAT: u128>(&'a self) -> Bytes<'a, FORMAT>;
}
impl<'a> AsBytes<'a> for [u8] {
#[inline(always)]
fn bytes<const FORMAT: u128>(&'a self) -> Bytes<'a, FORMAT> {
Bytes::new(self)
}
}
#[derive(Clone)]
pub struct Bytes<'a, const FORMAT: u128> {
slc: &'a [u8],
index: usize,
integer_count: usize,
fraction_count: usize,
exponent_count: usize,
}
impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> {
#[inline(always)]
pub const fn new(slc: &'a [u8]) -> Self {
Self {
slc,
index: 0,
integer_count: 0,
fraction_count: 0,
exponent_count: 0,
}
}
#[inline(always)]
const unsafe fn from_parts(slc: &'a [u8], index: usize) -> Self {
debug_assert!(index <= slc.len());
Self {
slc,
index,
integer_count: 0,
fraction_count: 0,
exponent_count: 0,
}
}
#[inline(always)]
pub fn integer_iter<'b>(&'b mut self) -> IntegerDigitsIterator<'a, 'b, FORMAT> {
IntegerDigitsIterator {
byte: self,
}
}
#[inline(always)]
pub fn fraction_iter<'b>(&'b mut self) -> FractionDigitsIterator<'a, 'b, FORMAT> {
FractionDigitsIterator {
byte: self,
}
}
#[inline(always)]
pub fn exponent_iter<'b>(&'b mut self) -> ExponentDigitsIterator<'a, 'b, FORMAT> {
ExponentDigitsIterator {
byte: self,
}
}
#[inline(always)]
pub fn special_iter<'b>(&'b mut self) -> SpecialDigitsIterator<'a, 'b, FORMAT> {
SpecialDigitsIterator {
byte: self,
}
}
#[inline(always)]
unsafe fn step_by_unchecked_impl(&mut self, count: usize, is_contiguous: bool) {
if is_contiguous {
debug_assert!(self.as_slice().len() >= count);
} else {
let format = NumberFormat::<{ FORMAT }> {};
debug_assert!(self.as_slice().len() >= count);
debug_assert!(count == 0 || count == 1);
debug_assert!(
count == 0 || self.slc.get(self.index) != Some(&format.digit_separator())
);
}
self.index += count;
}
#[inline(always)]
unsafe fn peek_many_unchecked_impl<V>(&self, is_contiguous: bool) -> V {
debug_assert!(is_contiguous);
debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
let slc = self.as_slice();
unsafe { ptr::read_unaligned::<V>(slc.as_ptr() as *const _) }
}
}
unsafe impl<'a, const FORMAT: u128> Iter<'a> for Bytes<'a, FORMAT> {
const IS_CONTIGUOUS: bool = NumberFormat::<{ FORMAT }>::DIGIT_SEPARATOR == 0;
#[inline(always)]
fn get_buffer(&self) -> &'a [u8] {
self.slc
}
#[inline(always)]
fn cursor(&self) -> usize {
self.index
}
#[inline(always)]
unsafe fn set_cursor(&mut self, index: usize) {
debug_assert!(index <= self.buffer_length());
self.index = index;
}
#[inline(always)]
fn current_count(&self) -> usize {
if Self::IS_CONTIGUOUS {
self.index
} else {
self.integer_count + self.fraction_count + self.exponent_count
}
}
#[inline(always)]
unsafe fn step_by_unchecked(&mut self, count: usize) {
unsafe { self.step_by_unchecked_impl(count, Self::IS_CONTIGUOUS) }
}
#[inline(always)]
unsafe fn peek_many_unchecked<V>(&self) -> V {
unsafe { self.peek_many_unchecked_impl(Self::IS_CONTIGUOUS) }
}
}
macro_rules! skip_iterator {
($iterator:ident, $doc:literal) => {
#[doc = $doc]
pub struct $iterator<'a: 'b, 'b, const FORMAT: u128> {
byte: &'b mut Bytes<'a, FORMAT>,
}
};
}
macro_rules! is_sign {
() => {
pub const fn is_sign(&self, value: u8) -> bool {
matches!(value, b'+' | b'-')
}
};
}
macro_rules! is_digit_separator {
($format:ident) => {
pub const fn is_digit_separator(&self, value: u8) -> bool {
let format = NumberFormat::<{ $format }> {};
let digit_separator = format.digit_separator();
if digit_separator == 0 {
false
} else {
value == digit_separator
}
}
};
}
macro_rules! skip_iterator_impl {
($iterator:ident, $radix_cb:ident) => {
impl<'a: 'b, 'b, const FORMAT: u128> $iterator<'a, 'b, FORMAT> {
is_sign!();
is_digit_separator!(FORMAT);
#[inline(always)]
pub fn new(byte: &'b mut Bytes<'a, FORMAT>) -> Self {
Self {
byte,
}
}
#[cfg_attr(not(feature = "compact"), inline(always))]
#[allow(clippy::assertions_on_constants)] pub fn take_n(&mut self, n: usize) -> Option<Bytes<'a, FORMAT>> {
if Self::IS_CONTIGUOUS {
let end = self.byte.slc.len().min(n + self.cursor());
let slc: &[u8] = &self.byte.slc[..end];
unsafe {
let byte: Bytes<'_, FORMAT> = Bytes::from_parts(slc, self.cursor());
unsafe { self.set_cursor(end) };
Some(byte)
}
} else {
None
}
}
}
};
}
macro_rules! skip_iterator_iterator_impl {
($iterator:ident) => {
impl<'a: 'b, 'b, const FORMAT: u128> Iterator for $iterator<'a, 'b, FORMAT> {
type Item = &'a u8;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
let value = self.peek()?;
self.byte.index += 1;
if !Self::IS_CONTIGUOUS && self.is_digit(*value) {
self.increment_count();
}
Some(value)
}
}
};
}
macro_rules! skip_iterator_iter_base {
($format:ident, $mask:ident, $count:ident) => {
const IS_CONTIGUOUS: bool = $format & flags::$mask == 0;
#[inline(always)]
fn get_buffer(&self) -> &'a [u8] {
self.byte.get_buffer()
}
#[inline(always)]
fn cursor(&self) -> usize {
self.byte.cursor()
}
#[inline(always)]
unsafe fn set_cursor(&mut self, index: usize) {
debug_assert!(index <= self.buffer_length());
unsafe { self.byte.set_cursor(index) };
}
#[inline(always)]
fn current_count(&self) -> usize {
if Self::IS_CONTIGUOUS {
self.byte.current_count()
} else {
self.byte.$count
}
}
#[inline(always)]
unsafe fn step_by_unchecked(&mut self, count: usize) {
unsafe { self.byte.step_by_unchecked_impl(count, Self::IS_CONTIGUOUS) }
}
#[inline(always)]
unsafe fn peek_many_unchecked<V>(&self) -> V {
unsafe { self.byte.peek_many_unchecked_impl(Self::IS_CONTIGUOUS) }
}
};
}
macro_rules! skip_iterator_digits_iter_base {
() => {
#[inline(always)]
fn is_consumed(&mut self) -> bool {
self.peek().is_none()
}
};
}
macro_rules! skip_iterator_bytesiter_impl {
($iterator:ident, $mask:ident, $count:ident, $i:ident, $l:ident, $t:ident, $c:ident) => {
unsafe impl<'a: 'b, 'b, const FORMAT: u128> Iter<'a> for $iterator<'a, 'b, FORMAT> {
skip_iterator_iter_base!(FORMAT, $mask, $count);
}
impl<'a: 'b, 'b, const FORMAT: u128> DigitsIter<'a> for $iterator<'a, 'b, FORMAT> {
skip_iterator_digits_iter_base!();
#[inline(always)]
fn increment_count(&mut self) {
self.byte.$count += 1;
}
#[inline(always)]
fn peek(&mut self) -> Option<<Self as Iterator>::Item> {
let format = NumberFormat::<{ FORMAT }> {};
const I: u128 = flags::$i;
const L: u128 = flags::$l;
const T: u128 = flags::$t;
const C: u128 = flags::$c;
const IL: u128 = I | L;
const IT: u128 = I | T;
const LT: u128 = L | T;
const ILT: u128 = I | L | T;
const IC: u128 = I | C;
const LC: u128 = L | C;
const TC: u128 = T | C;
const ILC: u128 = IL | C;
const ITC: u128 = IT | C;
const LTC: u128 = LT | C;
const ILTC: u128 = ILT | C;
match format.digit_separator_flags() & flags::$mask {
0 => peek_noskip!(self),
I => peek_i!(self),
L => peek_l!(self),
T => peek_t!(self),
IL => peek_il!(self),
IT => peek_it!(self),
LT => peek_lt!(self),
ILT => peek_ilt!(self),
IC => peek_ic!(self),
LC => peek_lc!(self),
TC => peek_tc!(self),
ILC => peek_ilc!(self),
ITC => peek_itc!(self),
LTC => peek_ltc!(self),
ILTC => peek_iltc!(self),
_ => unreachable!(),
}
}
#[inline(always)]
fn is_digit(&self, value: u8) -> bool {
let format = NumberFormat::<{ FORMAT }> {};
char_is_digit_const(value, format.mantissa_radix())
}
}
};
}
skip_iterator!(IntegerDigitsIterator, "Iterator that skips over digit separators in the integer.");
skip_iterator_impl!(IntegerDigitsIterator, mantissa_radix);
skip_iterator_iterator_impl!(IntegerDigitsIterator);
skip_iterator_bytesiter_impl!(
IntegerDigitsIterator,
INTEGER_DIGIT_SEPARATOR_FLAG_MASK,
integer_count,
INTEGER_INTERNAL_DIGIT_SEPARATOR,
INTEGER_LEADING_DIGIT_SEPARATOR,
INTEGER_TRAILING_DIGIT_SEPARATOR,
INTEGER_CONSECUTIVE_DIGIT_SEPARATOR
);
skip_iterator!(
FractionDigitsIterator,
"Iterator that skips over digit separators in the fraction."
);
skip_iterator_impl!(FractionDigitsIterator, mantissa_radix);
skip_iterator_iterator_impl!(FractionDigitsIterator);
skip_iterator_bytesiter_impl!(
FractionDigitsIterator,
FRACTION_DIGIT_SEPARATOR_FLAG_MASK,
fraction_count,
FRACTION_INTERNAL_DIGIT_SEPARATOR,
FRACTION_LEADING_DIGIT_SEPARATOR,
FRACTION_TRAILING_DIGIT_SEPARATOR,
FRACTION_CONSECUTIVE_DIGIT_SEPARATOR
);
skip_iterator!(
ExponentDigitsIterator,
"Iterator that skips over digit separators in the exponent."
);
skip_iterator_impl!(ExponentDigitsIterator, exponent_radix);
skip_iterator_iterator_impl!(ExponentDigitsIterator);
skip_iterator_bytesiter_impl!(
ExponentDigitsIterator,
EXPONENT_DIGIT_SEPARATOR_FLAG_MASK,
exponent_count,
EXPONENT_INTERNAL_DIGIT_SEPARATOR,
EXPONENT_LEADING_DIGIT_SEPARATOR,
EXPONENT_TRAILING_DIGIT_SEPARATOR,
EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR
);
skip_iterator!(
SpecialDigitsIterator,
"Iterator that skips over digit separators in special floats."
);
skip_iterator_iterator_impl!(SpecialDigitsIterator);
impl<'a: 'b, 'b, const FORMAT: u128> SpecialDigitsIterator<'a, 'b, FORMAT> {
is_sign!();
is_digit_separator!(FORMAT);
}
unsafe impl<'a: 'b, 'b, const FORMAT: u128> Iter<'a> for SpecialDigitsIterator<'a, 'b, FORMAT> {
skip_iterator_iter_base!(FORMAT, SPECIAL_DIGIT_SEPARATOR, integer_count);
}
impl<'a: 'b, 'b, const FORMAT: u128> DigitsIter<'a> for SpecialDigitsIterator<'a, 'b, FORMAT> {
skip_iterator_digits_iter_base!();
#[inline(always)]
fn increment_count(&mut self) {
}
#[inline(always)]
fn peek(&mut self) -> Option<<Self as Iterator>::Item> {
let format = NumberFormat::<{ FORMAT }> {};
if format.special_digit_separator() {
peek_iltc!(self)
} else {
peek_noskip!(self)
}
}
#[inline(always)]
fn is_digit(&self, value: u8) -> bool {
let format = NumberFormat::<{ FORMAT }> {};
char_is_digit_const(value, format.mantissa_radix())
}
}