use super::{
shared::{mask_32, vector_256},
*,
};
use crate::{block, debug, input::error::InputErrorConvertible};
use std::marker::PhantomData;
super::shared::quote_classifier!(Avx2QuoteClassifier32, BlockAvx2Classifier, 32, u32);
struct BlockAvx2Classifier {
internal_classifier: mask_32::BlockClassifier32Bit,
}
impl BlockAvx2Classifier {
fn new() -> Self {
Self {
internal_classifier: mask_32::BlockClassifier32Bit::new(),
}
}
#[inline(always)]
unsafe fn classify<'a, B: InputBlock<'a, 32>>(&mut self, block: &B) -> u32 {
block!(block[..32]);
let classification = vector_256::classify_block(block);
let slashes = classification.slashes;
let quotes = classification.quotes;
self.internal_classifier.classify(slashes, quotes)
}
}
#[cfg(test)]
mod tests {
use super::{Constructor, QuotesImpl};
use crate::{
input::{Input, OwnedBytes},
result::empty::EmptyRecorder,
FallibleIterator,
};
use test_case::test_case;
#[test_case("", 0)]
#[test_case("abcd", 0)]
#[test_case(r#""abcd""#, 0b01_1111)]
#[test_case(r#""num": 42, "string": "something" "#, 0b0_0111_1111_1110_0011_1111_1000_0000_1111)]
#[test_case(r#"abc\"abc\""#, 0b00_0000_0000)]
#[test_case(r#"abc\\"abc\\""#, 0b0111_1110_0000)]
#[test_case(r#"{"aaa":[{},{"b":{"c":[1,2,3]}}],"#, 0b0000_0000_0000_0110_0011_0000_0001_1110)]
fn single_block(str: &str, expected: u32) {
if !std::arch::is_x86_feature_detected!("avx2") {
return;
}
let owned_str = str.to_owned();
let input = OwnedBytes::from(owned_str);
let mut leading_padding = input.leading_padding_len() as u32;
let iter = input.iter_blocks::<_, 32>(&EmptyRecorder);
let mut classifier = Constructor::new(iter);
while leading_padding >= 32 {
let mask = classifier.next().unwrap().unwrap().within_quotes_mask;
assert_eq!(mask, 0);
leading_padding -= 32;
}
let first_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let len_in_first_mask = if leading_padding == 0 { 0 } else { 32 - leading_padding };
let second_mask = classifier.next().unwrap().unwrap().within_quotes_mask;
let combined_mask = (first_mask >> leading_padding) | (second_mask << len_in_first_mask);
assert_eq!(combined_mask, expected);
}
}