#![cfg(feature = "parse")]
use core::mem;
#[cfg(not(feature = "format"))]
pub use crate::noskip::{AsBytes, Bytes};
#[cfg(feature = "format")]
pub use crate::skip::{AsBytes, Bytes};
#[cfg(feature = "parse")]
pub unsafe trait Iter<'a> {
const IS_CONTIGUOUS: bool;
#[inline(always)]
fn as_ptr(&self) -> *const u8 {
self.as_slice().as_ptr()
}
#[inline(always)]
fn as_slice(&self) -> &'a [u8] {
debug_assert!(self.cursor() <= self.buffer_length());
unsafe { self.get_buffer().get_unchecked(self.cursor()..) }
}
fn get_buffer(&self) -> &'a [u8];
#[inline(always)]
fn buffer_length(&self) -> usize {
self.get_buffer().len()
}
#[inline(always)]
fn is_buffer_empty(&self) -> bool {
self.cursor() >= self.get_buffer().len()
}
fn cursor(&self) -> usize;
unsafe fn set_cursor(&mut self, index: usize);
fn current_count(&self) -> usize;
#[inline(always)]
fn is_contiguous(&self) -> bool {
Self::IS_CONTIGUOUS
}
#[inline(always)]
fn first(&self) -> Option<&'a u8> {
self.get_buffer().get(self.cursor())
}
#[inline(always)]
fn first_is_cased(&self, value: u8) -> bool {
Some(&value) == self.first()
}
#[inline(always)]
fn first_is_uncased(&self, value: u8) -> bool {
if let Some(&c) = self.first() {
c.eq_ignore_ascii_case(&value)
} else {
false
}
}
#[inline(always)]
fn first_is(&self, value: u8, is_cased: bool) -> bool {
if is_cased {
self.first_is_cased(value)
} else {
self.first_is_uncased(value)
}
}
unsafe fn step_by_unchecked(&mut self, count: usize);
#[inline(always)]
unsafe fn step_unchecked(&mut self) {
debug_assert!(!self.as_slice().is_empty());
unsafe { self.step_by_unchecked(1) };
}
#[inline(always)]
unsafe fn peek_many_unchecked<V>(&self) -> V {
unimplemented!();
}
#[inline(always)]
fn peek_u32(&self) -> Option<u32> {
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<u32>() {
unsafe { Some(self.peek_many_unchecked()) }
} else {
None
}
}
#[inline(always)]
fn peek_u64(&self) -> Option<u64> {
if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::<u64>() {
unsafe { Some(self.peek_many_unchecked()) }
} else {
None
}
}
}
pub trait DigitsIter<'a>: Iterator<Item = &'a u8> + Iter<'a> {
#[inline(always)]
#[allow(clippy::wrong_self_convention)] fn is_consumed(&mut self) -> bool {
self.peek().is_none()
}
fn increment_count(&mut self);
fn peek(&mut self) -> Option<Self::Item>;
#[inline(always)]
fn try_read(&mut self) -> Option<Self::Item> {
if let Some(value) = self.peek() {
unsafe { self.step_unchecked() };
Some(value)
} else {
None
}
}
#[inline(always)]
fn peek_is_cased(&mut self, value: u8) -> bool {
Some(&value) == self.peek()
}
#[inline(always)]
fn peek_is_uncased(&mut self, value: u8) -> bool {
if let Some(&c) = self.peek() {
c.eq_ignore_ascii_case(&value)
} else {
false
}
}
#[inline(always)]
fn peek_is(&mut self, value: u8, is_cased: bool) -> bool {
if is_cased {
self.peek_is_cased(value)
} else {
self.peek_is_uncased(value)
}
}
#[inline(always)]
fn read_if<Pred: FnOnce(u8) -> bool>(&mut self, pred: Pred) -> Option<u8> {
if let Some(&peeked) = self.peek() {
if pred(peeked) {
unsafe { self.step_unchecked() };
Some(peeked)
} else {
None
}
} else {
None
}
}
#[inline(always)]
fn read_if_value_cased(&mut self, value: u8) -> Option<u8> {
if self.peek() == Some(&value) {
unsafe { self.step_unchecked() };
Some(value)
} else {
None
}
}
#[inline(always)]
fn read_if_value_uncased(&mut self, value: u8) -> Option<u8> {
self.read_if(|x| x.eq_ignore_ascii_case(&value))
}
#[inline(always)]
fn read_if_value(&mut self, value: u8, is_cased: bool) -> Option<u8> {
if is_cased {
self.read_if_value_cased(value)
} else {
self.read_if_value_uncased(value)
}
}
#[inline(always)]
fn skip_zeros(&mut self) -> usize {
let start = self.current_count();
while self.read_if_value_cased(b'0').is_some() {
self.increment_count();
}
self.current_count() - start
}
fn is_digit(&self, value: u8) -> bool;
}