use super::{
bitmask_for_key,
index_for_key,
};
use crate::bloom::Bitmap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CompressedBitmap {
block_map: Vec<usize>,
bitmap: Vec<usize>,
#[cfg(debug_assertions)]
max_key: usize,
}
impl CompressedBitmap {
pub fn new(max_key: usize) -> Self {
let blocks = index_for_key(max_key);
let num_blocks = match blocks % (u64::BITS as usize) {
| 0 => index_for_key(blocks),
| _ => index_for_key(blocks) + 1, };
let block_map = vec![0; num_blocks];
CompressedBitmap {
bitmap: Vec::new(),
block_map,
#[cfg(debug_assertions)]
max_key,
}
}
pub fn set(&mut self, key: usize, value: bool) {
#[cfg(debug_assertions)]
debug_assert!(key <= self.max_key, "key {} > {} max", key, self.max_key);
let block_index = index_for_key(key);
let block_map_index = index_for_key(block_index);
let block_map_bitmask = bitmask_for_key(block_index);
let offset: usize = (0..block_map_index)
.map(|i| self.block_map[i].count_ones() as usize)
.sum();
let mask = block_map_bitmask - 1;
let offset = offset + (self.block_map[block_map_index] & mask).count_ones() as usize;
if self.block_map[block_map_index] & block_map_bitmask == 0 {
if !value {
return;
}
if offset >= self.bitmap.len() {
self.bitmap.push(bitmask_for_key(key));
} else {
self.bitmap.insert(offset, bitmask_for_key(key));
}
self.block_map[block_map_index] |= block_map_bitmask;
return;
}
if value {
self.bitmap[offset] |= bitmask_for_key(key);
} else {
self.bitmap[offset] &= !bitmask_for_key(key);
}
}
pub fn get(&self, key: usize) -> bool {
let block_index = index_for_key(key);
let block_map_index = index_for_key(block_index);
let block_map_bitmask = bitmask_for_key(block_index);
if self.block_map[block_map_index] & block_map_bitmask == 0 {
return false;
}
let offset: usize = (0..block_map_index)
.map(|i| self.block_map[i].count_ones() as usize)
.sum();
let mask = block_map_bitmask - 1;
let offset: usize = offset + (self.block_map[block_map_index] & mask).count_ones() as usize;
self.bitmap[offset] & bitmask_for_key(key) != 0
}
}
impl Bitmap for CompressedBitmap {
fn get(&self, key: usize) -> bool {
self.get(key)
}
fn set(&mut self, key: usize, value: bool) {
self.set(key, value)
}
fn new_with_capacity(max_key: usize) -> Self {
Self::new(max_key)
}
}