Skip to main content

rsonpath/classification/memmem/
nosimd.rs

1use super::*;
2use crate::input::{error::InputErrorConvertible as _, InputBlockIterator as _};
3
4pub(crate) struct Constructor;
5
6impl MemmemImpl for Constructor {
7    type Classifier<'i, 'b, 'r, I, R>
8        = SequentialMemmemClassifier<'i, 'b, 'r, I, R, BLOCK_SIZE>
9    where
10        I: Input + 'i,
11        <I as Input>::BlockIterator<'i, 'r, R, BLOCK_SIZE>: 'b,
12        R: InputRecorder<<I as Input>::Block<'i, BLOCK_SIZE>> + 'r,
13        'i: 'r;
14
15    fn memmem<'i, 'b, 'r, I, R>(
16        input: &'i I,
17        iter: &'b mut <I as Input>::BlockIterator<'i, 'r, R, BLOCK_SIZE>,
18    ) -> Self::Classifier<'i, 'b, 'r, I, R>
19    where
20        I: Input,
21        R: InputRecorder<<I as Input>::Block<'i, BLOCK_SIZE>>,
22        'i: 'r,
23    {
24        Self::Classifier { input, iter }
25    }
26}
27
28pub(crate) struct SequentialMemmemClassifier<'i, 'b, 'r, I, R, const N: usize>
29where
30    I: Input,
31    R: InputRecorder<I::Block<'i, N>> + 'r,
32{
33    input: &'i I,
34    iter: &'b mut I::BlockIterator<'i, 'r, R, N>,
35}
36
37impl<'i, 'r, I, R, const N: usize> SequentialMemmemClassifier<'i, '_, 'r, I, R, N>
38where
39    I: Input,
40    R: InputRecorder<I::Block<'i, N>> + 'r,
41{
42    #[inline]
43    fn find_label_sequential(
44        &mut self,
45        label: &StringPattern,
46        mut offset: usize,
47    ) -> Result<Option<(usize, I::Block<'i, N>)>, InputError> {
48        let label_size = label.quoted().len();
49        let first_c = if label.unquoted().is_empty() {
50            b'"'
51        } else {
52            label.unquoted()[0]
53        };
54
55        while let Some(block) = self.iter.next().e()? {
56            for (i, c) in block.iter().copied().enumerate() {
57                let j = offset + i;
58
59                if c == first_c && j > 0 && self.input.is_member_match(j - 1, j + label_size - 1, label).e()? {
60                    return Ok(Some((j - 1, block)));
61                }
62            }
63
64            offset += block.len();
65        }
66
67        Ok(None)
68    }
69}
70
71impl<'i, 'b, 'r, I, R, const N: usize> Memmem<'i, 'b, 'r, I, N> for SequentialMemmemClassifier<'i, 'b, 'r, I, R, N>
72where
73    I: Input,
74    R: InputRecorder<I::Block<'i, N>> + 'r,
75{
76    // Output the relative offsets
77    fn find_label(
78        &mut self,
79        first_block: Option<I::Block<'i, N>>,
80        start_idx: usize,
81        label: &StringPattern,
82    ) -> Result<Option<(usize, I::Block<'i, N>)>, InputError> {
83        if let Some(b) = first_block {
84            if let Some(res) = shared::find_label_in_first_block(self.input, b, start_idx, label)? {
85                return Ok(Some(res));
86            }
87        }
88        let next_block_offset = self.iter.get_offset();
89
90        self.find_label_sequential(label, next_block_offset)
91    }
92}