#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
#![deny(unreachable_pub, private_in_public)]
use derive_more::{From, Into};
use deterministic_bloom::const_size::BloomFilter;
use std::boxed::Box;
use wasm_bindgen::prelude::{wasm_bindgen, JsError};
#[wasm_bindgen(js_name = "setPanicHook")]
pub fn set_panic_hook() {
#[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
}
macro_rules! gen_bloom {
($name: ident, $n: expr, $k: expr) => {
#[doc = concat!("A monomorphic wrapper for [BloomFilter]`s with a size of ", stringify!($n), " bytes and ", stringify!($k), " hash functions.")]
#[wasm_bindgen]
#[derive(Debug, Default, From, Into)]
pub struct $name {
pub(crate) boxed: Box<BloomFilter<$n, $k>>,
}
#[wasm_bindgen]
impl $name {
#[doc = concat!("Initialize a blank [", stringify!($name), "] (i.e. contains no elements).")]
#[doc = concat!("use deterministic_bloom_wasm::", stringify!($name), ";")]
#[doc = concat!("let blank = ", stringify!($name), "::new();")]
#[doc = concat!("assert_eq!(", stringify!($name), "::count_ones(&blank), 0);")]
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Default::default()
}
#[doc = concat!("Attempt to initialize a [", stringify!($name), "] with a starting array.")]
#[doc = concat!("Fails with a [JsError] if the [Vec] is not exactly ", stringify!($n), " bytes long.")]
pub fn try_from_vec(vec: Vec<u8>) -> Result<$name, JsError> {
$name::try_from(vec).map_err(|e| JsError::new(&e.to_string()))
}
#[doc = concat!("use deterministic_bloom_wasm::", stringify!($name), ";")]
#[doc = concat!("let size = ", stringify!($name), "::byte_count();")]
#[doc = concat!("assert_eq!(size, ", stringify!($k), ");")]
pub fn byte_count() -> usize {
$k
}
#[doc = concat!("use deterministic_bloom_wasm::", stringify!($name), ";")]
#[doc = concat!("assert_eq!(", stringify!($name), "::hash_count(), ", stringify!($n), ");")]
pub fn hash_count() -> usize {
$n
}
#[doc = concat!("use deterministic_bloom_wasm::", stringify!($name), ";")]
#[doc = concat!("let mut bloom = ", stringify!($name), "::new();")]
pub fn insert_vec(&mut self, new_val: Vec<u8>) -> () {
self.boxed.insert(&new_val);
}
#[doc = concat!("use deterministic_bloom_wasm::", stringify!($name), ";")]
#[doc = concat!("let mut bloom = ", stringify!($name), "::new();")]
pub fn contains(&self, item: Vec<u8>) -> bool {
self.boxed.contains(&item)
}
#[doc = concat!("use deterministic_bloom_wasm::", stringify!($name), ";")]
#[doc = concat!("let mut bloom = ", stringify!($name), "::new();")]
#[doc = concat!("assert!(bloom.count_ones() >= ", $k, ");")]
#[doc = concat!("assert!(bloom.count_ones() <= 3 * ", $k, ");")]
pub fn count_ones(&self) -> usize {
self.boxed.count_ones()
}
#[doc = concat!("use deterministic_bloom_wasm::", stringify!($name), ";")]
#[doc = concat!("let mut bloom = ", stringify!($name), "::new();")]
#[doc = concat!("assert_ne!(bloom.as_bytes(), vec![0; ", $n, "]);")]
#[doc = concat!("assert_eq!(bloom.as_bytes().len(), ", $n, ");")]
pub fn as_bytes(&self) -> Vec<u8> {
self.boxed.as_bytes().to_vec()
}
}
impl From<BloomFilter<$n, $k>> for $name {
fn from(bloom: BloomFilter<$n, $k>) -> Self {
$name {
boxed: Box::new(bloom)
}
}
}
impl TryFrom<Vec<u8>> for $name {
type Error = deterministic_bloom::common::Error;
fn try_from(vec: Vec<u8>) -> Result<Self, deterministic_bloom::common::Error> {
<BloomFilter<$n, $k>>::try_from(vec).map($name::from)
}
}
};
}
gen_bloom!(SmallBloomFilter, 256, 13);
gen_bloom!(MediumBloomFilter, 4096, 17);
gen_bloom!(LargeBloomFilter, 1048576, 23);