rsonpath-lib 0.3.3

Blazing fast JSONPath query engine powered by SIMD. Core library of `rsonpath`.
Documentation
use super::*;
use crate::classification::{
    quotes::QuoteClassifiedBlock, ResumeClassifierBlockState, ResumeClassifierState,
};
use crate::debug;

struct Block<'a> {
    quote_classified: QuoteClassifiedBlock<'a>,
    idx: usize,
    are_colons_on: bool,
    are_commas_on: bool,
}

impl<'a> Block<'a> {
    fn new(
        quote_classified_block: QuoteClassifiedBlock<'a>,
        are_colons_on: bool,
        are_commas_on: bool,
    ) -> Self {
        Self {
            quote_classified: quote_classified_block,
            idx: 0,
            are_colons_on,
            are_commas_on,
        }
    }

    fn from_idx(
        quote_classified_block: QuoteClassifiedBlock<'a>,
        idx: usize,
        are_colons_on: bool,
        are_commas_on: bool,
    ) -> Self {
        Self {
            quote_classified: quote_classified_block,
            idx,
            are_colons_on,
            are_commas_on,
        }
    }
}

impl<'a> Iterator for Block<'a> {
    type Item = Structural;

    fn next(&mut self) -> Option<Self::Item> {
        while self.idx < self.quote_classified.block.len() {
            let character = self.quote_classified.block[self.idx];
            let idx_mask = 1_u64 << self.idx;
            let is_quoted = (self.quote_classified.within_quotes_mask & idx_mask) == idx_mask;

            self.idx += 1;

            match character {
                _ if is_quoted => (),
                b':' if self.are_colons_on => return Some(Colon(self.idx - 1)),
                b'[' | b'{' => return Some(Opening(self.idx - 1)),
                b',' if self.are_commas_on => return Some(Comma(self.idx - 1)),
                b']' | b'}' => return Some(Closing(self.idx - 1)),
                _ => (),
            }
        }

        None
    }
}

pub(crate) struct SequentialClassifier<'a, I: QuoteClassifiedIterator<'a>> {
    iter: I,
    block: Option<Block<'a>>,
    are_colons_on: bool,
    are_commas_on: bool,
}

impl<'a, I: QuoteClassifiedIterator<'a>> SequentialClassifier<'a, I> {
    #[inline(always)]
    pub(crate) fn new(iter: I) -> Self {
        Self {
            iter,
            block: None,
            are_colons_on: false,
            are_commas_on: false,
        }
    }
}

impl<'a, I: QuoteClassifiedIterator<'a>> Iterator for SequentialClassifier<'a, I> {
    type Item = Structural;

    #[inline(always)]
    fn next(&mut self) -> Option<Structural> {
        let mut item = self.block.as_mut().and_then(Iterator::next);

        while item.is_none() {
            match self.iter.next() {
                Some(block) => {
                    let mut block = Block::new(block, self.are_colons_on, self.are_commas_on);
                    item = block.next();
                    self.block = Some(block);
                }
                None => return None,
            }
        }

        item.map(|x| x.offset(self.iter.get_offset()))
    }
}

impl<'a, I: QuoteClassifiedIterator<'a>> std::iter::FusedIterator for SequentialClassifier<'a, I> {}

impl<'a, I: QuoteClassifiedIterator<'a>> StructuralIterator<'a, I> for SequentialClassifier<'a, I> {
    fn turn_commas_on(&mut self, idx: usize) {
        if !self.are_commas_on {
            self.are_commas_on = true;
            debug!("Turning commas on at {idx}.");

            if let Some(block) = self.block.take() {
                let quote_classified_block = block.quote_classified;
                let block_idx = (idx + 1) % I::block_size();

                if block_idx != 0 {
                    let new_block = Block::from_idx(
                        quote_classified_block,
                        block_idx,
                        self.are_colons_on,
                        true,
                    );
                    self.block = Some(new_block);
                }
            }
        }
    }

    fn turn_commas_off(&mut self) {
        self.are_commas_on = false;
        debug!("Turning commas off.");
    }

    fn turn_colons_on(&mut self, idx: usize) {
        if !self.are_colons_on {
            self.are_colons_on = true;
            debug!("Turning colons on at {idx}.");

            if let Some(block) = self.block.take() {
                let quote_classified_block = block.quote_classified;
                let block_idx = (idx + 1) % I::block_size();

                if block_idx != 0 {
                    let new_block = Block::from_idx(
                        quote_classified_block,
                        block_idx,
                        true,
                        self.are_commas_on,
                    );
                    self.block = Some(new_block);
                }
            }
        }
    }

    fn turn_colons_off(&mut self) {
        self.are_colons_on = false;
        debug!("Turning colons off.");
    }

    fn stop(self) -> ResumeClassifierState<'a, I> {
        let block = self.block.map(|b| ResumeClassifierBlockState {
            block: b.quote_classified,
            idx: b.idx,
        });
        ResumeClassifierState {
            iter: self.iter,
            block,
            are_colons_on: self.are_colons_on,
            are_commas_on: self.are_commas_on,
        }
    }

    fn resume(state: ResumeClassifierState<'a, I>) -> Self {
        Self {
            iter: state.iter,
            block: state.block.map(|b| Block {
                quote_classified: b.block,
                idx: b.idx,
                are_commas_on: state.are_commas_on,
                are_colons_on: state.are_colons_on,
            }),
            are_commas_on: state.are_commas_on,
            are_colons_on: state.are_colons_on,
        }
    }
}