use serde::{Deserialize, Serialize};
#[derive(Serialize,Deserialize)]
pub struct BitVec {
binary: Vec<u64>,
bit_cursor: u128,
}
#[allow(dead_code)]
impl BitVec {
pub fn new() -> Self {
Self {
binary: Vec::new(),
bit_cursor: 0,
}
}
pub fn clear(&mut self) {
self.bit_cursor = 0;
}
pub fn len(&self) -> usize {
self.bit_cursor as usize
}
pub fn capacity(&self) -> usize {
self.binary.len() * 64
}
pub fn push(&mut self, bit: u64) {
let bit = bit & 1;
let (chunk_idx, chunk_bit_idx) = self.cursor_index_pair();
if chunk_idx >= self.binary.len() {
self.binary.push(0);
}
self.binary[chunk_idx] &= !(1 << chunk_bit_idx);
self.binary[chunk_idx] |= bit << chunk_bit_idx;
self.offset_cursor(1);
}
pub fn get(&self, idx: usize) -> u64 {
let idx = idx as u128;
let chunk_idx = Self::chunk_index(idx);
let chunk_bit_idx = Self::chunk_bit_index(idx);
if chunk_idx >= self.binary.len() {
return 0;
}
(self.binary[chunk_idx] >> chunk_bit_idx) & 1
}
pub fn set(&mut self, idx: usize, bit: u64) {
let idx = idx as u128;
let chunk_idx = Self::chunk_index(idx);
let chunk_bit_idx = Self::chunk_bit_index(idx);
if chunk_idx >= self.binary.len() {
return;
}
let mut chunk = self.binary[chunk_idx];
chunk &= !(1 << chunk_bit_idx);
chunk |= (bit & 1) << chunk_bit_idx;
self.binary[chunk_idx] = chunk;
}
fn cursor_index_pair(&self) -> (usize, u64) {
let idx = self.bit_cursor;
(Self::chunk_index(idx), Self::chunk_bit_index(idx))
}
fn chunk_index(idx: u128) -> usize {
(idx / 64) as usize
}
fn chunk_bit_index(idx: u128) -> u64 {
(idx % 64) as u64
}
fn offset_cursor(&mut self, offset: i64) {
self.bit_cursor = (self.bit_cursor as i128 + offset as i128) as u128;
}
pub fn iter(&self) -> impl Iterator<Item = u64> + '_ {
(0..self.len()).map(|idx| self.get(idx))
}
pub fn compute_bits_required(num_bits: u64) -> usize {
(((num_bits / 64) + (num_bits % 64).clamp(0, 1)) * 64) as usize
}
}
mod test {
#[allow(unused_imports)]
use super::*;
#[test]
fn sanity() {
let mut bit_list = BitVec::new();
bit_list.push(0);
bit_list.push(1);
bit_list.push(1);
bit_list.push(0);
assert_eq!(vec![0, 1, 1, 0], bit_list.iter().collect::<Vec<_>>());
bit_list.push(1);
assert_eq!(vec![0, 1, 1, 0, 1], bit_list.iter().collect::<Vec<_>>());
assert_eq!(5, bit_list.len());
assert_eq!(64, bit_list.capacity());
bit_list.set(1, 0);
bit_list.set(4, 0);
assert_eq!(vec![0, 0, 1, 0, 0], bit_list.iter().collect::<Vec<_>>());
bit_list.clear();
assert_eq!(Vec::<u64>::new(), bit_list.iter().collect::<Vec<u64>>());
assert_eq!(64, bit_list.capacity());
}
#[test]
fn read_back_sequence() {
let seq_len = 100_000;
let bit_sequence = (0u64..seq_len).map(|i| i % 2).collect::<Vec<_>>();
let mut bit_list = BitVec::new();
bit_sequence.iter().for_each(|&b| {
bit_list.push(b);
});
assert_eq!(bit_sequence, bit_list.iter().collect::<Vec<_>>());
assert_eq!(seq_len as usize, bit_list.len());
assert_eq!(BitVec::compute_bits_required(seq_len), bit_list.capacity());
}
}