subms_bloom_filter/features/
counting.rs1use crate::{FNV_OFFSET, FNV_PRIME, fnv1a64};
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17pub struct CountingBloomFilter {
18 bit_count: u32,
19 k: u32,
20 cells: Vec<u8>,
22}
23
24impl CountingBloomFilter {
25 pub fn new(expected_entries: usize) -> Self {
27 let bit_count = expected_entries.saturating_mul(10).max(64) as u32;
28 let bytes = (bit_count as usize).div_ceil(2);
30 Self {
31 bit_count,
32 k: 7,
33 cells: vec![0u8; bytes],
34 }
35 }
36
37 pub fn bit_count(&self) -> u32 {
38 self.bit_count
39 }
40 pub fn k(&self) -> u32 {
41 self.k
42 }
43
44 pub fn add(&mut self, key: &str) {
47 let (h1, h2) = self.hash_pair(key);
48 for i in 0..self.k {
49 let idx = h1.wrapping_add(i.wrapping_mul(h2)) % self.bit_count;
50 self.incr(idx);
51 }
52 }
53
54 pub fn might_contain(&self, key: &str) -> bool {
59 let (h1, h2) = self.hash_pair(key);
60 for i in 0..self.k {
61 let idx = h1.wrapping_add(i.wrapping_mul(h2)) % self.bit_count;
62 if self.read(idx) == 0 {
63 return false;
64 }
65 }
66 true
67 }
68
69 pub fn remove(&mut self, key: &str) {
74 let (h1, h2) = self.hash_pair(key);
75 for i in 0..self.k {
76 let idx = h1.wrapping_add(i.wrapping_mul(h2)) % self.bit_count;
77 self.decr(idx);
78 }
79 }
80
81 pub fn clear(&mut self) {
83 self.cells.fill(0);
84 }
85
86 fn hash_pair(&self, key: &str) -> (u32, u32) {
87 let h = fnv1a64(key);
88 let h1 = h as u32;
89 let h2 = ((h >> 32) as u32) | 1;
90 (h1, h2)
91 }
92
93 fn read(&self, idx: u32) -> u8 {
94 let byte = self.cells[(idx / 2) as usize];
95 if idx % 2 == 0 {
96 byte & 0x0f
97 } else {
98 (byte >> 4) & 0x0f
99 }
100 }
101
102 fn write_cell(&mut self, idx: u32, value: u8) {
103 let i = (idx / 2) as usize;
104 let v = value & 0x0f;
105 if idx % 2 == 0 {
106 self.cells[i] = (self.cells[i] & 0xf0) | v;
107 } else {
108 self.cells[i] = (self.cells[i] & 0x0f) | (v << 4);
109 }
110 }
111
112 fn incr(&mut self, idx: u32) {
113 let cur = self.read(idx);
114 if cur < 15 {
115 self.write_cell(idx, cur + 1);
116 }
117 }
118
119 fn decr(&mut self, idx: u32) {
120 let cur = self.read(idx);
121 if cur > 0 && cur < 15 {
124 self.write_cell(idx, cur - 1);
125 }
126 }
127}
128
129const _: u64 = FNV_PRIME;
132const _: u64 = FNV_OFFSET;
133
134#[cfg(test)]
135#[path = "counting_tests.rs"]
136mod tests;