pub const fn num_bytes_for_bitmap(entries: usize) -> usize {
entries.div_ceil(8)
}
#[derive(Debug)]
pub struct BitmapView<'a> {
len: usize,
data: &'a [u8],
}
impl<'a> BitmapView<'a> {
#[inline]
pub const fn new(data: &'a [u8], len: usize) -> Self {
debug_assert!(data.len() >= num_bytes_for_bitmap(len));
BitmapView { len, data }
}
#[inline]
pub fn value(&self, idx: usize) -> bool {
debug_assert!(idx <= self.len, "idx: {}, len: {}", idx, self.len);
let byte = self.data[idx >> 3]; (byte >> (idx & 7)) & 1 != 0 }
#[inline]
pub fn count_trues(&self) -> usize {
let subset = &self.data[0..num_bytes_for_bitmap(self.len)];
let mut count = subset
.iter()
.map(|&b| b.count_ones())
.fold(0, |acc, v| acc + (v as usize));
let rem = self.len % 8;
if rem != 0 {
let last = subset.last().unwrap();
count -= last.count_ones() as usize;
let mask = (255 << (8 - rem)) >> (8 - rem);
count += (mask & last).count_ones() as usize;
}
count
}
#[inline]
pub fn all_true(&self) -> bool {
self.count_trues() == self.len
}
}
#[derive(Debug)]
pub struct BitmapViewMut<'a> {
len: usize,
data: &'a mut [u8],
}
impl<'a> BitmapViewMut<'a> {
#[inline]
pub const fn new(data: &'a mut [u8], len: usize) -> Self {
debug_assert!(data.len() >= num_bytes_for_bitmap(len));
BitmapViewMut { len, data }
}
#[inline]
pub const fn set(&mut self, idx: usize) {
debug_assert!(idx <= self.len);
let byte = idx / 8;
let bit = idx & 7; self.data[byte] |= 1 << bit;
}
#[inline]
pub const fn unset(&mut self, idx: usize) {
debug_assert!(idx <= self.len);
let byte = idx / 8;
let bit = idx & 7; self.data[byte] &= !(1 << bit);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn view_all_false() {
let data = &[0, 0, 0, 0];
let view = BitmapView::new(data, 32);
assert!(!view.value(0));
assert!(!view.value(13));
assert_eq!(0, view.count_trues());
}
#[test]
fn view_all_true() {
let data = &[u8::MAX, u8::MAX, u8::MAX, u8::MAX];
let view = BitmapView::new(data, 32);
assert!(view.value(0));
assert!(view.value(13));
assert_eq!(32, view.count_trues());
}
#[test]
fn view_all_true_logical_subset() {
let data = &[u8::MAX, u8::MAX, u8::MAX, u8::MAX];
let view = BitmapView::new(data, 8);
assert!(view.value(0));
assert!(view.value(8));
assert_eq!(8, view.count_trues());
}
#[test]
fn view_all_true_logical_subset_partial_byte() {
let data = &[u8::MAX, u8::MAX, u8::MAX, u8::MAX];
let view = BitmapView::new(data, 3);
assert!(view.value(0));
assert_eq!(3, view.count_trues());
}
#[test]
fn set_bit() {
let mut data = [0, 0];
let len = 10;
BitmapViewMut::new(&mut data, len).set(3);
BitmapViewMut::new(&mut data, len).set(8);
BitmapViewMut::new(&mut data, len).set(9);
let view = BitmapView::new(&data, len);
assert!(!view.value(0));
assert!(view.value(3));
assert!(view.value(8));
assert!(view.value(9));
assert_eq!(3, view.count_trues());
}
#[test]
fn unset_bit() {
let mut data = [u8::MAX, u8::MAX];
let len = 10;
BitmapViewMut::new(&mut data, len).unset(3);
BitmapViewMut::new(&mut data, len).unset(8);
BitmapViewMut::new(&mut data, len).unset(9);
let view = BitmapView::new(&data, len);
assert!(view.value(0));
assert!(!view.value(3));
assert!(!view.value(8));
assert!(!view.value(9));
assert_eq!(7, view.count_trues());
}
}