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}