rsonpath/classification/structural/
nosimd.rs

1use super::*;
2use crate::classification::{quotes::QuoteClassifiedBlock, ResumeClassifierBlockState};
3use crate::debug;
4
5pub(crate) struct Constructor;
6
7impl StructuralImpl for Constructor {
8    type Classifier<'i, I, Q>
9        = SequentialClassifier<'i, I, Q, BLOCK_SIZE>
10    where
11        I: InputBlockIterator<'i, BLOCK_SIZE>,
12        Q: QuoteClassifiedIterator<'i, I, MaskType, BLOCK_SIZE>;
13
14    #[inline(always)]
15    #[allow(dead_code)]
16    fn new<'i, I, Q>(iter: Q) -> Self::Classifier<'i, I, Q>
17    where
18        I: InputBlockIterator<'i, BLOCK_SIZE>,
19        Q: QuoteClassifiedIterator<'i, I, MaskType, BLOCK_SIZE>,
20    {
21        Self::Classifier {
22            iter,
23            block: None,
24            are_colons_on: false,
25            are_commas_on: false,
26        }
27    }
28}
29
30struct Block<'i, I, const N: usize>
31where
32    I: InputBlockIterator<'i, N>,
33{
34    quote_classified: QuoteClassifiedBlock<I::Block, MaskType, N>,
35    idx: usize,
36    are_colons_on: bool,
37    are_commas_on: bool,
38}
39
40impl<'i, I, const N: usize> Block<'i, I, N>
41where
42    I: InputBlockIterator<'i, N>,
43{
44    fn new(
45        quote_classified_block: QuoteClassifiedBlock<I::Block, MaskType, N>,
46        are_colons_on: bool,
47        are_commas_on: bool,
48    ) -> Self {
49        Self {
50            quote_classified: quote_classified_block,
51            idx: 0,
52            are_colons_on,
53            are_commas_on,
54        }
55    }
56
57    fn from_idx(
58        quote_classified_block: QuoteClassifiedBlock<I::Block, MaskType, N>,
59        idx: usize,
60        are_colons_on: bool,
61        are_commas_on: bool,
62    ) -> Self {
63        Self {
64            quote_classified: quote_classified_block,
65            idx,
66            are_colons_on,
67            are_commas_on,
68        }
69    }
70}
71
72impl<'i, I, const N: usize> Iterator for Block<'i, I, N>
73where
74    I: InputBlockIterator<'i, N>,
75{
76    type Item = Structural;
77
78    fn next(&mut self) -> Option<Self::Item> {
79        while self.idx < self.quote_classified.block.len() {
80            let character = self.quote_classified.block[self.idx];
81            let idx_mask = 1 << self.idx;
82            let is_quoted = (self.quote_classified.within_quotes_mask & idx_mask) == idx_mask;
83
84            let structural = match character {
85                _ if is_quoted => None,
86                b':' if self.are_colons_on => Some(Colon(self.idx)),
87                b'{' => Some(Opening(BracketType::Curly, self.idx)),
88                b'[' => Some(Opening(BracketType::Square, self.idx)),
89                b',' if self.are_commas_on => Some(Comma(self.idx)),
90                b'}' => Some(Closing(BracketType::Curly, self.idx)),
91                b']' => Some(Closing(BracketType::Square, self.idx)),
92                _ => None,
93            };
94
95            self.idx += 1;
96
97            if structural.is_some() {
98                return structural;
99            };
100        }
101
102        None
103    }
104}
105
106pub(crate) struct SequentialClassifier<'i, I, Q, const N: usize>
107where
108    I: InputBlockIterator<'i, N>,
109{
110    iter: Q,
111    block: Option<Block<'i, I, N>>,
112    are_colons_on: bool,
113    are_commas_on: bool,
114}
115
116impl<'i, I, Q, const N: usize> SequentialClassifier<'i, I, Q, N>
117where
118    I: InputBlockIterator<'i, N>,
119    Q: QuoteClassifiedIterator<'i, I, MaskType, N>,
120{
121    #[inline]
122    fn reclassify(&mut self, idx: usize) {
123        if let Some(block) = self.block.take() {
124            let quote_classified_block = block.quote_classified;
125            let relevant_idx = idx + 1;
126            let block_idx = (idx + 1) % N;
127            debug!("relevant_idx is {relevant_idx}.");
128
129            if block_idx != 0 || relevant_idx == self.iter.get_offset() {
130                let new_block = Block::from_idx(
131                    quote_classified_block,
132                    block_idx,
133                    self.are_colons_on,
134                    self.are_commas_on,
135                );
136                self.block = Some(new_block);
137            }
138        }
139    }
140}
141
142impl<'i, I, Q, const N: usize> FallibleIterator for SequentialClassifier<'i, I, Q, N>
143where
144    I: InputBlockIterator<'i, N>,
145    Q: QuoteClassifiedIterator<'i, I, MaskType, N>,
146{
147    type Item = Structural;
148    type Error = InputError;
149
150    #[inline(always)]
151    fn next(&mut self) -> Result<Option<Structural>, InputError> {
152        let mut item = self.block.as_mut().and_then(Iterator::next);
153
154        while item.is_none() {
155            match self.iter.next()? {
156                Some(block) => {
157                    let mut block = Block::new(block, self.are_colons_on, self.are_commas_on);
158                    item = block.next();
159                    self.block = Some(block);
160                }
161                None => return Ok(None),
162            }
163        }
164
165        Ok(item.map(|x| x.offset(self.iter.get_offset())))
166    }
167}
168
169impl<'i, I, Q, const N: usize> StructuralIterator<'i, I, Q, MaskType, N> for SequentialClassifier<'i, I, Q, N>
170where
171    I: InputBlockIterator<'i, N>,
172    Q: QuoteClassifiedIterator<'i, I, MaskType, N>,
173{
174    fn turn_colons_and_commas_on(&mut self, idx: usize) {
175        if !self.are_commas_on && !self.are_colons_on {
176            self.are_commas_on = true;
177            self.are_colons_on = true;
178            debug!("Turning both commas and colons on at {idx}.");
179
180            self.reclassify(idx);
181        } else if !self.are_commas_on {
182            self.turn_commas_on(idx);
183        } else if !self.are_colons_on {
184            self.turn_colons_on(idx);
185        }
186    }
187
188    fn turn_colons_and_commas_off(&mut self) {
189        if self.are_commas_on && self.are_colons_on {
190            self.are_commas_on = false;
191            self.are_colons_on = false;
192            debug!("Turning both commas and colons off.");
193        } else if self.are_commas_on {
194            self.turn_commas_off();
195        } else if self.are_colons_on {
196            self.turn_colons_off();
197        }
198    }
199
200    fn turn_commas_on(&mut self, idx: usize) {
201        if !self.are_commas_on {
202            self.are_commas_on = true;
203            debug!("Turning commas on at {idx}.");
204
205            self.reclassify(idx);
206        }
207    }
208
209    fn turn_commas_off(&mut self) {
210        self.are_commas_on = false;
211        debug!("Turning commas off.");
212    }
213
214    fn turn_colons_on(&mut self, idx: usize) {
215        if !self.are_colons_on {
216            self.are_colons_on = true;
217            debug!("Turning colons on at {idx}.");
218
219            self.reclassify(idx);
220        }
221    }
222
223    fn turn_colons_off(&mut self) {
224        self.are_colons_on = false;
225        debug!("Turning colons off.");
226    }
227
228    fn stop(self) -> ResumeClassifierState<'i, I, Q, MaskType, N> {
229        let block = self.block.map(|b| ResumeClassifierBlockState {
230            block: b.quote_classified,
231            idx: b.idx,
232        });
233        ResumeClassifierState {
234            iter: self.iter,
235            block,
236            are_colons_on: self.are_colons_on,
237            are_commas_on: self.are_commas_on,
238        }
239    }
240
241    fn resume(state: ResumeClassifierState<'i, I, Q, MaskType, N>) -> Self {
242        Self {
243            iter: state.iter,
244            block: state.block.map(|b| Block {
245                quote_classified: b.block,
246                idx: b.idx,
247                are_commas_on: state.are_commas_on,
248                are_colons_on: state.are_colons_on,
249            }),
250            are_commas_on: state.are_commas_on,
251            are_colons_on: state.are_colons_on,
252        }
253    }
254}