#![cfg(all(feature = "parse", not(feature = "format")))]
use core::{mem, ptr};
use crate::digit::char_is_digit_const;
use crate::format::NumberFormat;
use crate::iterator::{DigitsIter, Iter};
pub trait AsBytes<'a> {
fn bytes<const __: u128>(&'a self) -> Bytes<'a, __>;
}
impl<'a> AsBytes<'a> for [u8] {
#[inline(always)]
fn bytes<const __: u128>(&'a self) -> Bytes<'a, __> {
Bytes::new(self)
}
}
#[derive(Clone)]
pub struct Bytes<'a, const __: u128> {
slc: &'a [u8],
index: usize,
}
impl<'a, const __: u128> Bytes<'a, __> {
#[inline(always)]
pub const fn new(slc: &'a [u8]) -> Self {
Self {
slc,
index: 0,
}
}
#[inline(always)]
#[allow(clippy::assertions_on_constants)]
const unsafe fn from_parts(slc: &'a [u8], index: usize) -> Self {
debug_assert!(index <= slc.len());
debug_assert!(Self::IS_CONTIGUOUS);
Self {
slc,
index,
}
}
#[inline(always)]
pub fn integer_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
DigitsIterator {
byte: self,
}
}
#[inline(always)]
pub fn fraction_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
DigitsIterator {
byte: self,
}
}
#[inline(always)]
pub fn exponent_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
DigitsIterator {
byte: self,
}
}
#[inline(always)]
pub fn special_iter<'b>(&'b mut self) -> DigitsIterator<'a, 'b, __> {
DigitsIterator {
byte: self,
}
}
}
impl<'a, const __: u128> Iter<'a> for Bytes<'a, __> {
const IS_CONTIGUOUS: bool = true;
#[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 {
self.index
}
#[inline(always)]
fn first(&self) -> Option<&'a u8> {
self.slc.get(self.index)
}
#[inline(always)]
#[allow(clippy::assertions_on_constants)]
unsafe fn step_by_unchecked(&mut self, count: usize) {
debug_assert!(Self::IS_CONTIGUOUS);
debug_assert!(self.as_slice().len() >= count);
self.index += count;
}
#[inline(always)]
#[allow(clippy::assertions_on_constants)]
unsafe fn peek_many_unchecked<V>(&self) -> V {
debug_assert!(Self::IS_CONTIGUOUS);
debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
unsafe { ptr::read_unaligned::<V>(self.as_ptr() as *const _) }
}
}
pub struct DigitsIterator<'a: 'b, 'b, const __: u128> {
byte: &'b mut Bytes<'a, __>,
}
impl<'a: 'b, 'b, const __: u128> DigitsIterator<'a, 'b, __> {
#[inline(always)]
pub fn new(byte: &'b mut Bytes<'a, __>) -> 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, __>> {
debug_assert!(Self::IS_CONTIGUOUS);
let end = self.byte.slc.len().min(n + self.cursor());
let slc: &[u8] = &self.byte.slc[..end];
unsafe {
let byte: Bytes<'_, __> = Bytes::from_parts(slc, self.cursor());
unsafe { self.set_cursor(end) };
Some(byte)
}
}
}
impl<'a: 'b, 'b, const __: u128> Iter<'a> for DigitsIterator<'a, 'b, __> {
const IS_CONTIGUOUS: bool = Bytes::<'a, __>::IS_CONTIGUOUS;
#[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 {
self.byte.current_count()
}
#[inline(always)]
unsafe fn step_by_unchecked(&mut self, count: usize) {
debug_assert!(self.as_slice().len() >= count);
unsafe { self.byte.step_by_unchecked(count) }
}
#[inline(always)]
unsafe fn peek_many_unchecked<V>(&self) -> V {
debug_assert!(self.as_slice().len() >= mem::size_of::<V>());
unsafe { self.byte.peek_many_unchecked() }
}
}
impl<'a: 'b, 'b, const FORMAT: u128> DigitsIter<'a> for DigitsIterator<'a, 'b, FORMAT> {
#[inline(always)]
fn is_consumed(&mut self) -> bool {
self.is_buffer_empty()
}
#[inline(always)]
fn peek(&mut self) -> Option<<Self as Iterator>::Item> {
self.byte.slc.get(self.byte.index)
}
#[inline(always)]
fn is_digit(&self, value: u8) -> bool {
let format = NumberFormat::<{ FORMAT }> {};
char_is_digit_const(value, format.mantissa_radix())
}
}
impl<'a: 'b, 'b, const __: u128> Iterator for DigitsIterator<'a, 'b, __> {
type Item = &'a u8;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
let value = self.byte.slc.get(self.byte.index)?;
self.byte.index += 1;
Some(value)
}
}
impl<'a: 'b, 'b, const __: u128> ExactSizeIterator for DigitsIterator<'a, 'b, __> {
#[inline(always)]
fn len(&self) -> usize {
self.buffer_length() - self.cursor()
}
}