rsonpath/classification/depth/shared/
mask_64.rs

1use crate::{
2    bin_u64,
3    classification::{depth::DepthBlock, quotes::QuoteClassifiedBlock},
4    debug,
5    input::InputBlock,
6};
7use std::marker::PhantomData;
8
9const SIZE: usize = 64;
10
11/// Works on a 64-byte slice, but uses a heuristic to quickly
12/// respond to queries and not count the depth exactly unless
13/// needed.
14///
15/// The heuristic checks if it is possible to achieve the queried
16/// depth within the block by counting the number of opening
17/// and closing structural characters. This can be done much
18/// more quickly than precise depth calculation.
19pub(crate) struct DepthVector64<'a, B: InputBlock<'a, SIZE>> {
20    pub(crate) quote_classified: QuoteClassifiedBlock<B, u64, SIZE>,
21    pub(crate) opening_mask: u64,
22    pub(crate) opening_count: u32,
23    pub(crate) closing_mask: u64,
24    pub(crate) idx: usize,
25    pub(crate) depth: i32,
26    pub(crate) phantom: PhantomData<&'a ()>,
27}
28
29impl<'a, B: InputBlock<'a, SIZE>> DepthBlock<'a> for DepthVector64<'a, B> {
30    #[inline(always)]
31    fn advance_to_next_depth_decrease(&mut self) -> bool {
32        debug_assert!(is_x86_feature_detected!("popcnt"));
33        let next_closing = self.closing_mask.trailing_zeros() as usize;
34
35        if next_closing == SIZE {
36            return false;
37        }
38
39        bin_u64!("opening_mask", self.opening_mask);
40        bin_u64!("closing_mask", self.closing_mask);
41
42        self.opening_mask >>= next_closing;
43        self.closing_mask >>= next_closing;
44        self.opening_mask >>= 1;
45        self.closing_mask >>= 1;
46
47        bin_u64!("new opening_mask", self.opening_mask);
48        bin_u64!("new closing_mask", self.closing_mask);
49
50        let new_opening_count = self.opening_mask.count_ones() as i32;
51        let delta = (self.opening_count as i32) - new_opening_count - 1;
52        self.opening_count = new_opening_count as u32;
53
54        debug!("next_closing: {next_closing}");
55        debug!("new_opening_count: {new_opening_count}");
56        debug!("delta: {delta}");
57
58        self.depth += delta;
59        self.idx += next_closing + 1;
60
61        true
62    }
63
64    #[inline(always)]
65    fn get_depth(&self) -> isize {
66        self.depth as isize
67    }
68
69    #[inline(always)]
70    fn depth_at_end(&self) -> isize {
71        debug_assert!(is_x86_feature_detected!("popcnt"));
72        (((self.opening_count as i32) - self.closing_mask.count_ones() as i32) + self.depth) as isize
73    }
74
75    #[inline(always)]
76    fn add_depth(&mut self, depth: isize) {
77        self.depth += depth as i32;
78    }
79
80    #[inline(always)]
81    fn estimate_lowest_possible_depth(&self) -> isize {
82        debug_assert!(is_x86_feature_detected!("popcnt"));
83        (self.depth - self.closing_mask.count_ones() as i32) as isize
84    }
85}