Skip to main content

rsonpath/engine/
tail_skipping.rs

1use crate::{
2    classification::{
3        depth::{DepthBlock as _, DepthIterator as _, DepthIteratorResumeOutcome},
4        quotes::QuoteClassifiedIterator,
5        simd::{dispatch_simd, Simd},
6        structural::{BracketType, StructuralIterator},
7        ResumeClassifierState,
8    },
9    debug,
10    engine::error::EngineError,
11    input::InputBlockIterator,
12    FallibleIterator as _, MaskType, BLOCK_SIZE,
13};
14use std::marker::PhantomData;
15
16pub(crate) struct TailSkip<'i, I, Q, S, V, const N: usize> {
17    classifier: Option<S>,
18    simd: V,
19    _phantom: (PhantomData<&'i ()>, PhantomData<(I, Q)>),
20}
21
22impl<'i, I, V> TailSkip<'i, I, V::QuotesClassifier<'i, I>, V::StructuralClassifier<'i, I>, V, BLOCK_SIZE>
23where
24    I: InputBlockIterator<'i, BLOCK_SIZE>,
25    V: Simd,
26{
27    pub(crate) fn new(classifier: V::StructuralClassifier<'i, I>, simd: V) -> Self {
28        Self {
29            classifier: Some(classifier),
30            simd,
31            _phantom: (PhantomData, PhantomData),
32        }
33    }
34
35    #[allow(
36        clippy::expect_used,
37        reason = "Enforcing the classifier invariant is clunky without this."
38    )]
39    pub(crate) fn skip(&mut self, opening: BracketType) -> Result<usize, EngineError> {
40        dispatch_simd!(self.simd; self, opening =>
41        fn <'i, I, V>(
42            tail_skip: &mut TailSkip<'i, I, V::QuotesClassifier<'i, I>, V::StructuralClassifier<'i, I>, V, BLOCK_SIZE>,
43            opening: BracketType) -> Result<usize, EngineError>
44        where
45            I: InputBlockIterator<'i, BLOCK_SIZE>,
46            V: Simd
47        {
48            debug!("Skipping");
49            let mut idx = 0;
50            let mut err = None;
51
52            let classifier = tail_skip.classifier.take().expect("tail skip must always hold a classifier");
53
54            tail_skip.classifier = Some('a: {
55                let resume_state = classifier.stop();
56                let DepthIteratorResumeOutcome(first_vector, mut depth_classifier) =
57                    tail_skip.simd.resume_depth_classification(resume_state, opening);
58
59                let mut current_vector = match first_vector {
60                    Some(v) => Some(v),
61                    None => match depth_classifier.next() {
62                        Ok(v) => v,
63                        Err(e) => {
64                            err = Some(e);
65                            let resume_state = depth_classifier.stop(None);
66                            break 'a tail_skip.simd.resume_structural_classification(resume_state);
67                        }
68                    },
69                };
70                let mut current_depth = 1;
71
72                'outer: while let Some(ref mut vector) = current_vector {
73                    vector.add_depth(current_depth);
74
75                    debug!("Fetched vector, current depth is {current_depth}");
76                    debug!("Estimate: {}", vector.estimate_lowest_possible_depth());
77
78                    if vector.estimate_lowest_possible_depth() <= 0 {
79                        while vector.advance_to_next_depth_decrease() {
80                            if vector.get_depth() == 0 {
81                                debug!("Encountered depth 0, breaking.");
82                                break 'outer;
83                            }
84                        }
85                    }
86
87                    current_depth = vector.depth_at_end();
88                    current_vector = match depth_classifier.next() {
89                        Ok(v) => v,
90                        Err(e) => {
91                            err = Some(e);
92                            let resume_state = depth_classifier.stop(None);
93                            break 'a tail_skip.simd.resume_structural_classification(resume_state);
94                        }
95                    };
96                }
97
98                debug!("Skipping complete, resuming structural classification.");
99                let resume_state = depth_classifier.stop(current_vector);
100                debug!("Finished at {}", resume_state.get_idx());
101                idx = resume_state.get_idx() - 1;
102                tail_skip.simd.resume_structural_classification(resume_state)
103            });
104
105            if let Some(err) = err {
106                Err(err.into())
107            } else {
108                Ok(idx)
109            }
110        })
111    }
112
113    pub(crate) fn stop(self) -> ResumeClassifierState<'i, I, V::QuotesClassifier<'i, I>, MaskType, BLOCK_SIZE> {
114        self.classifier.expect("tail skip must always hold a classifier").stop()
115    }
116}
117
118impl<'i, I, Q, S, V, const N: usize> std::ops::Deref for TailSkip<'i, I, Q, S, V, N>
119where
120    I: InputBlockIterator<'i, N>,
121    Q: QuoteClassifiedIterator<'i, I, MaskType, N>,
122    S: StructuralIterator<'i, I, Q, MaskType, N>,
123    V: Simd,
124{
125    type Target = S;
126
127    fn deref(&self) -> &Self::Target {
128        self.classifier
129            .as_ref()
130            .expect("tail skip must always hold a classifier")
131    }
132}
133
134impl<'i, I, Q, S, V, const N: usize> std::ops::DerefMut for TailSkip<'i, I, Q, S, V, N>
135where
136    I: InputBlockIterator<'i, N>,
137    Q: QuoteClassifiedIterator<'i, I, MaskType, N>,
138    S: StructuralIterator<'i, I, Q, MaskType, N>,
139    V: Simd,
140{
141    fn deref_mut(&mut self) -> &mut Self::Target {
142        self.classifier
143            .as_mut()
144            .expect("tail skip must always hold a classifier")
145    }
146}