use std::io::Read;
use anyhow::Result;
use crate::resource::prp::PlasmaRead;
#[derive(Debug, Clone, Default)]
pub struct BitVector {
pub words: Vec<u32>,
}
impl BitVector {
pub fn new() -> Self {
Self { words: Vec::new() }
}
pub fn is_bit_set(&self, bit: usize) -> bool {
let word_idx = bit / 32;
let bit_idx = bit % 32;
if word_idx >= self.words.len() {
return false;
}
(self.words[word_idx] & (1 << bit_idx)) != 0
}
pub fn set_bit(&mut self, bit: usize, on: bool) {
let word_idx = bit / 32;
let bit_idx = bit % 32;
while word_idx >= self.words.len() {
self.words.push(0);
}
if on {
self.words[word_idx] |= 1 << bit_idx;
} else {
self.words[word_idx] &= !(1 << bit_idx);
}
}
pub fn read(reader: &mut impl Read) -> Result<Self> {
let count = reader.read_u32()?;
let mut words = Vec::with_capacity(count as usize);
for _ in 0..count {
words.push(reader.read_u32()?);
}
Ok(Self { words })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty() {
let bv = BitVector::new();
assert!(!bv.is_bit_set(0));
assert!(!bv.is_bit_set(100));
}
#[test]
fn test_set_get() {
let mut bv = BitVector::new();
bv.set_bit(5, true);
assert!(bv.is_bit_set(5));
assert!(!bv.is_bit_set(4));
bv.set_bit(33, true);
assert!(bv.is_bit_set(33));
assert_eq!(bv.words.len(), 2);
}
#[test]
fn test_read() {
use std::io::Cursor;
let data = [
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, ];
let mut cursor = Cursor::new(&data);
let bv = BitVector::read(&mut cursor).unwrap();
assert!(bv.is_bit_set(0));
assert!(!bv.is_bit_set(1));
assert!(bv.is_bit_set(2));
}
}