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`] – 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}