1pub mod applier;
16pub mod creator;
17pub mod error;
18pub mod reader;
19
20use std::hash::{BuildHasher, BuildHasherDefault, Hasher};
21use std::sync::LazyLock;
22
23pub const SEED: u128 = 42;
25
26static ELEMENT_HASHER: LazyLock<fastbloom::DefaultHasher> =
27 LazyLock::new(|| fastbloom::DefaultHasher::seeded(&SEED.to_be_bytes()));
28
29pub fn element_hash(elem: &[u8]) -> u64 {
35 ELEMENT_HASHER.hash_one(elem)
36}
37
38#[derive(Default)]
40pub struct PrehashedHasher(u64);
41
42impl Hasher for PrehashedHasher {
43 fn finish(&self) -> u64 {
44 self.0
45 }
46
47 fn write(&mut self, _bytes: &[u8]) {
48 unreachable!("PrehashedHasher only accepts u64 hashes")
49 }
50
51 fn write_u64(&mut self, hash: u64) {
52 self.0 = hash;
53 }
54}
55
56pub type PrehashedBuildHasher = BuildHasherDefault<PrehashedHasher>;
57
58pub type PrehashedBloomFilter = fastbloom::BloomFilter<512, PrehashedBuildHasher>;
60
61#[cfg(test)]
62mod tests {
63 use fastbloom::BloomFilter;
64
65 use super::*;
66
67 #[test]
68 fn test_prehashed_filter_matches_seeded_filter() {
69 for count in [0usize, 1, 7, 100, 5000] {
72 let elems = (0..count)
73 .map(|i| format!("elem-{i}").into_bytes())
74 .chain([Vec::new()])
75 .collect::<Vec<_>>();
76 let mut seeded = BloomFilter::with_false_pos(0.01)
77 .seed(&SEED)
78 .expected_items(elems.len());
79 let mut prehashed = BloomFilter::with_false_pos(0.01)
80 .hasher(PrehashedBuildHasher::default())
81 .expected_items(elems.len());
82 for elem in &elems {
83 seeded.insert(elem);
84 prehashed.insert(&element_hash(elem));
85 }
86 assert_eq!(seeded.as_slice(), prehashed.as_slice());
87 }
88 }
89}