use alloc::boxed::Box;
use alloc::vec::Vec;
use core::{
borrow::Borrow,
hash::{Hash, Hasher},
};
#[cfg(feature = "bitcode")]
use bitcode::{Decode, Encode};
use crate::{Filter, RapidHasher};
#[cfg_attr(feature = "bitcode", derive(Decode, Encode))]
pub struct Bf<T: ?Sized, F, H = RapidHasher> {
pub filter: F,
pub _phantom: core::marker::PhantomData<(H, Box<T>)>,
}
#[inline(always)]
fn hash<H: Hasher + Default, T: Hash + ?Sized>(key: &T) -> u64 {
let mut hasher = H::default();
key.hash(&mut hasher);
hasher.finish()
}
impl<T: ?Sized, F, H> Filter<T> for Bf<T, F, H>
where
T: Hash,
H: Hasher + Default,
F: Filter<u64>,
{
fn has<Q: ?Sized>(&self, key: &Q) -> bool
where
T: Borrow<Q>,
Q: Hash,
{
self.filter.has(&hash::<H, Q>(key))
}
fn len(&self) -> usize {
self.filter.len()
}
}
impl<T, F, H> Bf<T, F, H>
where
T: Hash,
H: Hasher + Default,
F: Filter<u64>,
{
pub fn from(keys: &[T]) -> Self
where
F: From<Vec<u64>>,
{
let mut keys: Vec<u64> = keys.iter().map(hash::<H, T>).collect();
keys.sort_unstable();
keys.dedup();
Self {
filter: F::from(keys),
_phantom: core::marker::PhantomData,
}
}
}
impl<T, F, H> From<&Vec<T>> for Bf<T, F, H>
where
T: Hash,
H: Hasher + Default,
F: Filter<u64> + From<Vec<u64>>,
{
fn from(v: &Vec<T>) -> Self {
Self::from(v.as_slice())
}
}
impl<T, F, H> From<&[T]> for Bf<T, F, H>
where
T: Hash,
H: Hasher + Default,
F: Filter<u64> + From<Vec<u64>>,
{
fn from(keys: &[T]) -> Self {
Self::from(keys)
}
}
impl<T: ?Sized, F, H> Bf<T, F, H>
where
T: Hash,
H: Hasher + Default,
F: Filter<u64>,
{
pub fn has<Q>(&self, key: &Q) -> bool
where
T: Borrow<Q>,
Q: Hash + ?Sized,
{
let borrowed: &Q = key.borrow();
self.filter.has(&hash::<H, Q>(borrowed))
}
pub fn wrap(filter: F) -> Self {
Self {
filter,
_phantom: core::marker::PhantomData,
}
}
}
impl<T: ?Sized, F, H> From<Bf<&T, F, H>> for Bf<T, F, H> {
fn from(src: Bf<&T, F, H>) -> Self {
Self {
filter: src.filter,
_phantom: core::marker::PhantomData,
}
}
}