1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//! Classification ignoring the structure of the JSON and looking for the occurrence
//! of a specific member name as quickly as possible.
use crate::{
    input::{error::InputError, Input},
    query::JsonString,
    result::InputRecorder,
    BLOCK_SIZE,
};
use cfg_if::cfg_if;

/// Classifier that can quickly find a member name in a byte stream.
pub trait Memmem<'i, 'b, 'r, I: Input, const N: usize> {
    /// Find a member key identified by a given [`JsonString`].
    ///
    /// - `first_block` &ndash; optional first block to search; if not provided,
    /// the search will start at the next block returned by the underlying [`Input`] iterator.
    /// - `start_idx` &ndash; index of the start of search, either falling inside `first_block`,
    /// or at the start of the next block.
    ///
    /// # Errors
    /// Errors when reading the underlying [`Input`] are propagated.
    fn find_label(
        &mut self,
        first_block: Option<I::Block<'i, N>>,
        start_idx: usize,
        label: &JsonString,
    ) -> Result<Option<(usize, I::Block<'i, N>)>, InputError>;
}

cfg_if! {
    if #[cfg(any(doc, not(feature = "simd")))] {
        mod nosimd;
        type MemmemImpl<'a, 'b, 'r, I, R> = nosimd::SequentialMemmemClassifier<'a, 'b, 'r, I, R, BLOCK_SIZE>;
    }
    else if #[cfg(simd = "avx2")] {
        mod avx2;
        type MemmemImpl<'a, 'b, 'r, I, R> = avx2::Avx2MemmemClassifier<'a, 'b, 'r, I, R>;
    }
    else {
        compile_error!("Target architecture is not supported by SIMD features of this crate. Disable the default `simd` feature.");
    }
}

/// Walk through the JSON document represented by `bytes`
/// and classify quoted sequences.
#[must_use]
#[inline(always)]
pub fn memmem<'i, 'b, 'r, I, R>(
    input: &'i I,
    iter: &'b mut I::BlockIterator<'i, 'r, BLOCK_SIZE, R>,
) -> impl Memmem<'i, 'b, 'r, I, BLOCK_SIZE>
where
    I: Input,
    R: InputRecorder<I::Block<'i, BLOCK_SIZE>>,
    'i: 'r,
{
    MemmemImpl::new(input, iter)
}