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