#[cfg(target_arch = "x86")]
pub(super) mod mask_32;
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub(super) mod mask_64;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub(super) mod vector_128;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub(super) mod vector_256;
#[cfg(target_arch = "x86_64")]
pub(super) mod vector_512;
#[cfg(target_arch = "aarch64")]
pub(super) mod vector_neon;
#[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))]
macro_rules! structural_classifier {
($name:ident, $core:ident, $mask_mod:ident, $size:literal, $mask_ty:ty) => {
pub(crate) struct Constructor;
impl StructuralImpl for Constructor {
type Classifier<'i, I, Q>
= $name<'i, I, Q>
where
I: InputBlockIterator<'i, BLOCK_SIZE>,
Q: QuoteClassifiedIterator<'i, I, MaskType, BLOCK_SIZE>;
#[inline]
fn new<'i, I, Q>(iter: Q) -> Self::Classifier<'i, I, Q>
where
I: InputBlockIterator<'i, BLOCK_SIZE>,
Q: QuoteClassifiedIterator<'i, I, MaskType, BLOCK_SIZE>,
{
Self::Classifier {
iter,
classifier: $core::new(),
block: None,
are_commas_on: false,
are_colons_on: false,
}
}
}
pub(crate) struct $name<'a, I, Q>
where
I: InputBlockIterator<'a, $size>,
{
iter: Q,
classifier: $core,
block: Option<$mask_mod::StructuralsBlock<I::Block>>,
are_commas_on: bool,
are_colons_on: bool,
}
impl<'a, I: InputBlockIterator<'a, $size>, Q: QuoteClassifiedIterator<'a, I, $mask_ty, $size>> $name<'a, I, Q> {
#[inline(always)]
fn current_block_is_spent(&self) -> bool {
self.block
.as_ref()
.map_or(true, $mask_mod::StructuralsBlock::is_empty)
}
#[inline]
fn reclassify(&mut self, idx: usize) {
if let Some(block) = self.block.take() {
let relative_idx = idx + 1 - self.iter.get_offset();
let quote_classified_block = block.quote_classified;
debug!("relative_idx is {relative_idx}.");
if relative_idx < $size {
debug!("need to reclassify.");
let mask = <$mask_ty>::MAX << relative_idx;
let mut new_block = unsafe { self.classifier.classify(quote_classified_block) };
new_block.structural_mask &= mask;
self.block = Some(new_block);
}
}
}
}
impl<'a, I, Q> FallibleIterator for $name<'a, I, Q>
where
I: InputBlockIterator<'a, $size>,
Q: QuoteClassifiedIterator<'a, I, $mask_ty, $size>,
{
type Item = Structural;
type Error = InputError;
#[inline(always)]
fn next(&mut self) -> Result<Option<Structural>, Self::Error> {
while self.current_block_is_spent() {
match self.iter.next() {
Ok(Some(block)) => {
self.block = unsafe { Some(self.classifier.classify(block)) };
}
Ok(None) => {
self.block = None;
break;
}
Err(err) => return Err(err),
}
}
Ok(self
.block
.as_mut()
.and_then(|b| b.next().map(|x| x.offset(self.iter.get_offset()))))
}
}
impl<'a, I, Q> StructuralIterator<'a, I, Q, $mask_ty, $size> for $name<'a, I, Q>
where
I: InputBlockIterator<'a, $size>,
Q: QuoteClassifiedIterator<'a, I, $mask_ty, $size>,
{
#[inline(always)]
fn turn_colons_and_commas_on(&mut self, idx: usize) {
if !self.are_commas_on && !self.are_colons_on {
self.are_commas_on = true;
self.are_colons_on = true;
debug!("Turning both commas and colons on at {idx}.");
unsafe { self.classifier.internal_classifier.toggle_colons_and_commas() }
self.reclassify(idx);
} else if !self.are_commas_on {
self.turn_commas_on(idx);
} else if !self.are_colons_on {
self.turn_colons_on(idx);
}
}
#[inline(always)]
fn turn_colons_and_commas_off(&mut self) {
if self.are_commas_on && self.are_colons_on {
self.are_commas_on = false;
self.are_colons_on = false;
debug!("Turning both commas and colons off.");
unsafe { self.classifier.internal_classifier.toggle_colons_and_commas() }
} else if self.are_commas_on {
self.turn_commas_off();
} else if self.are_colons_on {
self.turn_colons_off();
}
}
#[inline(always)]
fn turn_commas_on(&mut self, idx: usize) {
if !self.are_commas_on {
self.are_commas_on = true;
debug!("Turning commas on at {idx}.");
unsafe { self.classifier.internal_classifier.toggle_commas() }
self.reclassify(idx);
}
}
#[inline(always)]
fn turn_commas_off(&mut self) {
if self.are_commas_on {
self.are_commas_on = false;
debug!("Turning commas off.");
unsafe { self.classifier.internal_classifier.toggle_commas() }
}
}
#[inline(always)]
fn turn_colons_on(&mut self, idx: usize) {
if !self.are_colons_on {
self.are_colons_on = true;
debug!("Turning colons on at {idx}.");
unsafe { self.classifier.internal_classifier.toggle_colons() }
self.reclassify(idx);
}
}
#[inline(always)]
fn turn_colons_off(&mut self) {
if self.are_colons_on {
self.are_colons_on = false;
debug!("Turning colons off.");
unsafe { self.classifier.internal_classifier.toggle_colons() }
}
}
#[inline(always)]
fn stop(self) -> ResumeClassifierState<'a, I, Q, $mask_ty, $size> {
let block = self.block.map(|b| ResumeClassifierBlockState {
idx: b.get_idx() as usize,
block: b.quote_classified,
});
ResumeClassifierState {
iter: self.iter,
block,
are_commas_on: self.are_commas_on,
are_colons_on: self.are_colons_on,
}
}
#[inline(always)]
fn resume(state: ResumeClassifierState<'a, I, Q, $mask_ty, $size>) -> Self {
let mut classifier = $core::new();
unsafe {
if state.are_commas_on && state.are_colons_on {
classifier.internal_classifier.toggle_colons_and_commas();
} else {
if state.are_commas_on {
classifier.internal_classifier.toggle_commas();
}
if state.are_colons_on {
classifier.internal_classifier.toggle_colons();
}
}
}
let block = state.block.map(|b| {
let mut block = unsafe { classifier.classify(b.block) };
let idx_mask = <$mask_ty>::MAX.checked_shl(b.idx as u32).unwrap_or(0);
block.structural_mask &= idx_mask;
block
});
Self {
iter: state.iter,
block,
classifier,
are_commas_on: state.are_commas_on,
are_colons_on: state.are_colons_on,
}
}
}
};
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))]
pub(crate) use structural_classifier;