use sha3::{
digest::{ExtendableOutput, Update, XofReader},
Shake256,
};
use super::BloomFilter;
pub const SATURATION_THRESHOLD: usize = 1019;
pub const HASH_BYTE_SIZE: usize = 32;
pub type Namefilter = BloomFilter<256, 30>;
impl Namefilter {
pub fn saturate(&mut self) {
let mut xof = {
let mut h = Shake256::default();
h.update(self.as_bytes());
h.finalize_xof()
};
let hash = &mut [0u8; HASH_BYTE_SIZE];
loop {
xof.read(hash);
let mut clone = self.clone();
clone.add(hash);
if clone.count_ones() > SATURATION_THRESHOLD {
break;
}
*self = clone
}
}
}
impl AsRef<[u8]> for Namefilter {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn saturate_not_greater_than_threshold() {
let namefilters = (0..47)
.map(|i| {
let mut namefilter = Namefilter::new();
for i in 0..i {
namefilter.add(&[i as u8]);
}
namefilter.saturate();
namefilter
})
.collect::<Vec<_>>();
for namefilter in namefilters {
assert!(namefilter.count_ones() <= SATURATION_THRESHOLD);
}
}
}