Skip to main content

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