#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Bitmap {
words: Vec<u64>,
len: u32,
}
impl Bitmap {
pub fn zeroed(len: u32) -> Self {
Self {
words: vec![0; Self::words_for_len(len)],
len,
}
}
pub fn set_all(len: u32) -> Self {
let mut bitmap = Self {
words: vec![u64::MAX; Self::words_for_len(len)],
len,
};
bitmap.clear_trailing_bits();
bitmap
}
pub fn len(&self) -> u32 {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn is_set(&self, index: u32) -> bool {
if index >= self.len {
return false;
}
let word_index = index as usize / 64;
let bit_index = index as usize % 64;
self.words
.get(word_index)
.map(|word| ((word >> bit_index) & 1) == 1)
.unwrap_or(false)
}
pub fn set(&mut self, index: u32, value: bool) {
if index >= self.len {
return;
}
let word_index = index as usize / 64;
let bit_index = index as usize % 64;
if value {
self.words[word_index] |= 1_u64 << bit_index;
} else {
self.words[word_index] &= !(1_u64 << bit_index);
}
}
pub fn count_ones(&self) -> u32 {
self.words.iter().map(|word| word.count_ones()).sum()
}
pub fn from_bools(values: &[bool]) -> Self {
let mut bitmap = Self::zeroed(values.len() as u32);
for (index, value) in values.iter().copied().enumerate() {
bitmap.set(index as u32, value);
}
bitmap
}
fn words_for_len(len: u32) -> usize {
if len == 0 {
0
} else {
((len - 1) / 64 + 1) as usize
}
}
fn clear_trailing_bits(&mut self) {
let remainder = self.len % 64;
if remainder == 0 || self.words.is_empty() {
return;
}
let mask = (1_u64 << remainder) - 1;
if let Some(last) = self.words.last_mut() {
*last &= mask;
}
}
}