zeppelin_embed/meta/
bitmap.rs1use roaring::RoaringBitmap;
4
5#[derive(Clone, Debug, Default, PartialEq)]
7pub struct DocBitmap {
8 inner: RoaringBitmap,
9}
10
11impl Eq for DocBitmap {}
12
13impl DocBitmap {
14 pub(crate) fn compact_for_cache(&mut self) {
15 self.inner = self.inner.clone();
16 }
17
18 pub(crate) fn resident_bytes(&self) -> Option<usize> {
19 let statistics = self.inner.statistics();
20 #[cfg(target_pointer_width = "64")]
21 const CONTAINER_BYTES: usize = 32;
22 #[cfg(target_pointer_width = "32")]
23 const CONTAINER_BYTES: usize = 16;
24 let containers = (statistics.n_containers as usize).checked_mul(CONTAINER_BYTES)?;
25 let arrays = (statistics.n_values_array_containers as usize)
26 .checked_mul(std::mem::size_of::<u16>())?;
27 let bitsets = usize::try_from(statistics.n_bytes_bitset_containers).ok()?;
28 containers.checked_add(arrays)?.checked_add(bitsets)
29 }
30
31 #[must_use]
33 pub fn new() -> Self {
34 Self::default()
35 }
36
37 #[must_use]
39 pub fn full(row_count: u32) -> Self {
40 Self {
41 inner: (0..row_count).collect(),
42 }
43 }
44
45 #[must_use]
47 pub fn from_ids(ids: impl IntoIterator<Item = u32>) -> Self {
48 Self {
49 inner: ids.into_iter().collect(),
50 }
51 }
52
53 pub fn insert(&mut self, document: u32) -> bool {
55 self.inner.insert(document)
56 }
57
58 pub fn remove(&mut self, document: u32) -> bool {
60 self.inner.remove(document)
61 }
62
63 #[must_use]
65 pub fn contains(&self, document: u32) -> bool {
66 self.inner.contains(document)
67 }
68
69 #[must_use]
71 pub fn cardinality(&self) -> u64 {
72 self.inner.len()
73 }
74
75 #[must_use]
77 pub fn is_empty(&self) -> bool {
78 self.inner.is_empty()
79 }
80
81 pub fn iter(&self) -> impl Iterator<Item = u32> + '_ {
83 self.inner.iter().inspect(|_| {
84 #[cfg(any(test, feature = "test-seams"))]
85 super::bitmap_observer::row();
86 })
87 }
88
89 pub(crate) fn first_at_or_after(&self, row_count: u32) -> Option<u32> {
92 #[cfg(any(test, feature = "test-seams"))]
93 super::bitmap_observer::probe();
94 self.inner.range(row_count..).next()
95 }
96
97 pub(crate) const fn as_roaring(&self) -> &RoaringBitmap {
98 &self.inner
99 }
100
101 pub fn union_with(&mut self, other: &Self) {
103 self.inner |= &other.inner;
104 }
105
106 pub fn intersect_with(&mut self, other: &Self) {
108 self.inner &= &other.inner;
109 }
110
111 pub fn subtract(&mut self, other: &Self) {
113 self.inner -= &other.inner;
114 }
115
116 #[must_use]
118 pub fn is_subset(&self, other: &Self) -> bool {
119 self.inner.is_subset(&other.inner)
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::DocBitmap;
126
127 #[test]
128 fn astra_15_empty_zero_and_max_u32_bitmap_bounds_are_checked() {
129 let empty = DocBitmap::new();
130 assert_eq!(empty.first_at_or_after(0), None);
131 assert_eq!(empty.first_at_or_after(u32::MAX), None);
132 let sparse = DocBitmap::from_ids([0, 2, 65_535, 65_536, u32::MAX - 1]);
133 for (bound, expected) in [
134 (0, Some(0)),
135 (1, Some(2)),
136 (3, Some(65_535)),
137 (65_536, Some(65_536)),
138 (65_537, Some(u32::MAX - 1)),
139 (u32::MAX, None),
140 ] {
141 assert_eq!(sparse.first_at_or_after(bound), expected);
142 }
143 let maximum = DocBitmap::from_ids([u32::MAX]);
144 assert_eq!(maximum.first_at_or_after(u32::MAX), Some(u32::MAX));
145 let dense = DocBitmap::full(131_072);
146 assert_eq!(dense.first_at_or_after(65_536), Some(65_536));
147 assert_eq!(dense.first_at_or_after(131_071), Some(131_071));
148 assert_eq!(dense.first_at_or_after(131_072), None);
149 }
150}