extern crate bit_vec;
extern crate rand;
extern crate twox_hash;
#[macro_use]
extern crate serde_derive;
extern crate serde;
use bit_vec::BitVec;
use std::cmp;
use std::f64;
use std::hash::{Hash, Hasher};
use twox_hash::XxHash64;
pub struct Bloom {
bitmap: BitVec,
bitmap_size: u64,
k: u64,
seeds: (u64, u64),
xx: (XxHash64, XxHash64),
}
#[derive(Serialize, Deserialize)]
pub struct SerdeBloom {
bitmap: Vec<u8>,
bitmap_size: u64,
k: u64,
seeds: (u64, u64)
}
impl Default for Bloom {
fn default() -> Self {
Bloom::new_with_rate(1_000_000, 1e-6)
}
}
impl From<&Bloom> for SerdeBloom {
fn from(bloom: &Bloom) -> Self {
Self {
bitmap: bloom.bitmap.to_bytes(),
bitmap_size: bloom.bitmap_size,
k: bloom.k,
seeds: bloom.seeds
}
}
}
impl From<&SerdeBloom> for Bloom {
fn from(serde_bloom: &SerdeBloom) -> Self {
Bloom::from_existing(
serde_bloom.bitmap.as_slice(),
serde_bloom.bitmap_size,
serde_bloom.k,
serde_bloom.seeds
)
}
}
impl Bloom {
pub fn new(bitmap_size: usize, items_count: usize) -> Self {
assert!(bitmap_size > 0 && items_count > 0);
let bitmap_size = (bitmap_size as u64) * 8u64;
let k = Self::optimal_k_num(bitmap_size, items_count);
let bitmap = BitVec::from_elem(bitmap_size as usize, false);
let seeds = (rand::random(), rand::random());
let xx = (Self::xx_new(seeds.0), Self::xx_new(seeds.1));
Self {
bitmap,
bitmap_size,
k,
seeds,
xx,
}
}
pub fn new_with_rate(items_count: usize, fp_p: f64) -> Self {
let bitmap_size = Self::compute_bitmap_size(items_count, fp_p);
Bloom::new(bitmap_size, items_count)
}
pub fn from_existing_struct(other: &Bloom) -> Self {
Self {
bitmap: BitVec::from_bytes(other.bitmap().to_bytes().as_slice()),
bitmap_size: other.bitmap_size,
k: other.k,
seeds: other.seeds,
xx: other.xx(),
}
}
pub fn from_existing(
bitmap: &[u8],
bitmap_size: u64,
k: u64,
seeds: (u64, u64)
) -> Self {
let xx = (Self::xx_new(seeds.0), Self::xx_new(seeds.1));
Self {
bitmap: BitVec::from_bytes(bitmap),
bitmap_size,
k,
seeds,
xx,
}
}
pub fn compute_bitmap_size(items_count: usize, fp_p: f64) -> usize {
assert!(items_count > 0);
assert!(fp_p > 0.0 && fp_p < 1.0);
let log2 = f64::consts::LN_2;
let log2_2 = log2 * log2;
((items_count as f64) * f64::ln(fp_p) / (-8.0 * log2_2)).ceil() as usize
}
fn bit_offset(&self, hashes: (u64, u64), i_k: u64) -> usize {
(self.double_hash(hashes, i_k) % self.bitmap_size) as usize
}
pub fn add<T: Hash>(&mut self, item: &T) {
let hashes = self.hashes(item);
for i_k in 0..self.k {
let bit_offset = self.bit_offset(hashes, i_k);
self.bitmap.set(bit_offset, true);
}
}
pub fn check<T: Hash>(&self, item: &T) -> bool {
let hashes = self.hashes(item);
for i_k in 0..self.k {
let bit_offset = self.bit_offset(hashes, i_k);
if !self.bitmap.get(bit_offset).unwrap_or_else(|| panic!("bit_offset {} not in bitmap!", bit_offset)) {
return false;
}
}
true
}
pub fn check_and_add<T: Hash>(&mut self, item: &T) -> bool {
let hashes = self.hashes(item);
let mut found = true;
for i_k in 0..self.k {
let bit_offset = self.bit_offset(hashes, i_k);
if !self.bitmap.get(bit_offset).unwrap_or_else(|| panic!("bit_offset {} not in bitmap!", bit_offset)) {
found = false;
self.bitmap.set(bit_offset, true);
}
}
found
}
pub fn bitmap(&self) -> BitVec {
self.bitmap.clone()
}
pub fn number_of_bits(&self) -> u64 {
self.bitmap_size
}
pub fn number_of_hash_functions(&self) -> u64 {
self.k
}
pub fn xx(&self) -> (XxHash64, XxHash64) {
self.xx
}
fn optimal_k_num(bitmap_size: u64, items_count: usize) -> u64 {
let m = bitmap_size as f64;
let n = items_count as f64;
let k = (m / n * f64::ln(2.0f64)).ceil() as u64;
cmp::max(k, 1)
}
fn hash1<T: Hash>(&self, t: &T) -> u64 {
let mut hasher = self.xx().0;
t.hash(&mut hasher);
hasher.finish()
}
fn hash2<T: Hash>(&self, t: &T) -> u64 {
let mut hasher = self.xx().1;
t.hash(&mut hasher);
hasher.finish()
}
fn hashes<T: Hash>(&self, t: &T) -> (u64, u64) {
(self.hash1(t), self.hash2(t))
}
fn double_hash(&self, hashes: (u64, u64), i_k: u64) -> u64 {
hashes.0.wrapping_add(i_k.wrapping_mul(hashes.1)) % self.bitmap_size
}
pub fn clear(&mut self) {
self.bitmap.clear()
}
fn xx_new(seed: u64) -> XxHash64 {
XxHash64::with_seed(seed)
}
}
#[test]
fn bloom_test_add() {
let mut bloom = Bloom::default();
let key: u64 = rand::random();
assert_eq!(bloom.check(&key), false);
bloom.add(&key);
assert_eq!(bloom.check(&key), true);
}
#[test]
fn bloom_test_check_and_add() {
let mut bloom = Bloom::default();
let key: u64 = rand::random();
assert_eq!(bloom.check_and_add(&key), false);
assert_eq!(bloom.check_and_add(&key), true);
}
#[test]
fn bloom_test_clear() {
let mut bloom = Bloom::default();
let key: u64 = rand::random();
bloom.add(&key);
assert_eq!(bloom.check(&key), true);
bloom.clear();
assert_eq!(bloom.check(&key), false);
}
#[test]
fn bloom_test_load() {
let mut original = Bloom::default();
let key: u64 = rand::random();
original.add(&key);
assert_eq!(original.check(&key), true);
let cloned = Bloom::from_existing(
&original.bitmap().to_bytes(),
original.number_of_bits(),
original.number_of_hash_functions(),
original.seeds,
);
assert_eq!(cloned.check(&key), true);
}
#[test]
fn bloom_test_load_struct() {
let mut original = Bloom::default();
let key: u64 = rand::random();
original.add(&key);
assert_eq!(original.check(&key), true);
let cloned = Bloom::from_existing_struct(&original);
assert_eq!(cloned.check(&key), true);
}
#[test]
fn bloom_test_serde() {
let mut original = Bloom::default();
let key: u64 = rand::random();
original.add(&key);
assert_eq!(original.check(&key), true);
let serde = SerdeBloom::from(&original);
let original = Bloom::from(&serde);
assert_eq!(original.check(&key), true);
}