Skip to main content

rsonpath/classification/
depth.rs

1//! JSON depth calculations on byte streams.
2//!
3//! Used for iterating over the document while keeping track of depth.
4//! This is heavily optimized for skipping irrelevant parts of a JSON document.
5//! For example, to quickly skip to the end of the currently opened object one can set the
6//! depth to `1` and then advance until it reaches `0`.
7//!
8//! It also supports stopping and resuming with [`ResumeClassifierState`].
9use super::structural::BracketType;
10use crate::{
11    classification::{quotes::QuoteClassifiedIterator, ResumeClassifierState},
12    input::{error::InputError, InputBlockIterator},
13    FallibleIterator, MaskType, BLOCK_SIZE,
14};
15
16/// Common trait for structs that enrich a byte block with JSON depth information.
17pub trait DepthBlock<'a>: Sized {
18    /// Add depth to the block.
19    /// This is usually done at the start of a block to carry any accumulated
20    /// depth over.
21    fn add_depth(&mut self, depth: isize);
22
23    /// Returns depth at the current position.
24    fn get_depth(&self) -> isize;
25
26    /// A lower bound on the depth that can be reached when advancing.
27    ///
28    /// It is guaranteed that [`get_depth`](`DepthBlock::get_depth`)
29    /// will always return something greater or equal to this return value, but it is not guaranteed to be a depth that
30    /// is actually achievable within the block. In particular, an implementation always returning
31    /// [`isize::MIN`] is a correct implementation. This is meant to be a tool for performance improvements,
32    /// not reliably checking the actual minimal depth within the block.
33    fn estimate_lowest_possible_depth(&self) -> isize;
34
35    /// Returns exact depth at the end of the decorated slice.
36    fn depth_at_end(&self) -> isize;
37
38    /// Advance to the next position at which depth may decrease.
39    ///
40    /// # Returns
41    /// `false` if the end of the block was reached without any depth decrease,
42    /// `true` otherwise.
43    fn advance_to_next_depth_decrease(&mut self) -> bool;
44}
45
46/// Trait for depth iterators, i.e. finite iterators returning depth information
47/// about JSON documents.
48pub trait DepthIterator<'i, I, Q, M, const N: usize>: FallibleIterator<Item = Self::Block, Error = InputError>
49where
50    I: InputBlockIterator<'i, N>,
51{
52    /// Type of the [`DepthBlock`] implementation used by this iterator.
53    type Block: DepthBlock<'i>;
54
55    /// Resume classification from a state retrieved by a previous
56    /// [`DepthIterator::stop`] or [`StructuralIterator::stop`](`crate::classification::structural::StructuralIterator::stop`) invocation.
57    fn resume(state: ResumeClassifierState<'i, I, Q, M, N>, opening: BracketType) -> (Option<Self::Block>, Self);
58
59    /// Stop classification and return a state object that can be used to resume
60    /// a classifier from the place in which the current one was stopped.
61    fn stop(self, block: Option<Self::Block>) -> ResumeClassifierState<'i, I, Q, M, N>;
62}
63
64/// The result of resuming a [`DepthIterator`] &ndash; the first block and the rest of the iterator.
65pub struct DepthIteratorResumeOutcome<'i, I, Q, D, M, const N: usize>(pub Option<D::Block>, pub D)
66where
67    I: InputBlockIterator<'i, N>,
68    D: DepthIterator<'i, I, Q, M, N>;
69
70pub(crate) mod nosimd;
71pub(crate) mod shared;
72
73#[cfg(target_arch = "x86")]
74pub(crate) mod avx2_32;
75#[cfg(target_arch = "x86_64")]
76pub(crate) mod avx2_64;
77#[cfg(target_arch = "x86_64")]
78pub(crate) mod avx512_64;
79#[cfg(target_arch = "aarch64")]
80pub(crate) mod neon_64;
81#[cfg(target_arch = "x86")]
82pub(crate) mod sse2_32;
83#[cfg(target_arch = "x86_64")]
84pub(crate) mod sse2_64;
85
86pub(crate) trait DepthImpl {
87    type Classifier<'i, I, Q>: DepthIterator<'i, I, Q, MaskType, BLOCK_SIZE>
88    where
89        I: InputBlockIterator<'i, BLOCK_SIZE>,
90        Q: QuoteClassifiedIterator<'i, I, MaskType, BLOCK_SIZE>;
91
92    fn resume<'i, I, Q>(
93        state: ResumeClassifierState<'i, I, Q, MaskType, BLOCK_SIZE>,
94        opening: BracketType,
95    ) -> DepthIteratorResumeOutcome<'i, I, Q, Self::Classifier<'i, I, Q>, MaskType, BLOCK_SIZE>
96    where
97        I: InputBlockIterator<'i, BLOCK_SIZE>,
98        Q: QuoteClassifiedIterator<'i, I, MaskType, BLOCK_SIZE>,
99    {
100        let (first_block, iter) =
101            <Self::Classifier<'i, I, Q> as DepthIterator<'i, I, Q, MaskType, BLOCK_SIZE>>::resume(state, opening);
102        DepthIteratorResumeOutcome(first_block, iter)
103    }
104}