#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub struct BitEnc {
storage: Vec<u32>,
width: usize,
mask: u32,
len: usize,
usable_bits_per_block: usize,
}
fn mask(width: usize) -> u32 {
(1 << width) - 1
}
impl BitEnc {
pub fn new(width: usize) -> Self {
assert!(width <= 8, "Only encoding widths up to 8 supported");
BitEnc {
storage: Vec::new(),
width,
mask: mask(width),
len: 0,
usable_bits_per_block: 32 - 32 % width,
}
}
pub fn with_capacity(width: usize, n: usize) -> Self {
assert!(width <= 8, "Only encoding widths up to 8 supported");
BitEnc {
storage: Vec::with_capacity(n * width / 32),
width,
mask: mask(width),
len: 0,
usable_bits_per_block: 32 - 32 % width,
}
}
pub fn push(&mut self, value: u8) {
let (block, bit) = self.addr(self.len);
if bit == 0 {
self.storage.push(0);
}
self.set_by_addr(block, bit, value);
self.len += 1;
}
pub fn push_values(&mut self, mut n: usize, value: u8) {
{
let (block, bit) = self.addr(self.len);
if bit > 0 {
for bit in (bit..32).step_by(self.width).take(n) {
self.set_by_addr(block, bit, value);
n -= 1;
self.len += 1;
}
}
}
if n > 0 {
let mut value_block = 0;
{
let mut v = u32::from(value);
for _ in 0..32 / self.width {
value_block |= v;
v <<= self.width;
}
}
let i = self.len + n;
let (block, bit) = self.addr(i);
self.storage.resize(block, value_block);
if bit > 0 {
let shifted_block = value_block >> (self.usable_bits_per_block - bit);
self.storage.push(shifted_block);
}
self.len = i;
}
}
pub fn set(&mut self, i: usize, value: u8) {
let (block, bit) = self.addr(i);
self.set_by_addr(block, bit, value);
}
pub fn get(&self, i: usize) -> Option<u8> {
if i >= self.len {
None
} else {
let (block, bit) = self.addr(i);
Some(self.get_by_addr(block, bit))
}
}
pub fn iter(&self) -> BitEncIter<'_> {
BitEncIter { bitenc: self, i: 0 }
}
pub fn clear(&mut self) {
self.storage.clear();
self.len = 0;
}
fn get_by_addr(&self, block: usize, bit: usize) -> u8 {
((self.storage[block] >> bit) & self.mask) as u8
}
fn set_by_addr(&mut self, block: usize, bit: usize, value: u8) {
let mask = self.mask << bit;
self.storage[block] |= mask;
self.storage[block] ^= mask;
self.storage[block] |= (u32::from(value) & self.mask) << bit;
}
fn addr(&self, i: usize) -> (usize, usize) {
let k = i * self.width;
(
k / self.usable_bits_per_block,
k % self.usable_bits_per_block,
)
}
#[deprecated(
since = "0.33.0",
note = "Please use the more specific `nr_blocks` and `nr_symbols` functions instead."
)]
pub fn len(&self) -> usize {
self.len
}
pub fn nr_blocks(&self) -> usize {
self.storage.len()
}
pub fn nr_symbols(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize)]
pub struct BitEncIter<'a> {
bitenc: &'a BitEnc,
i: usize,
}
impl<'a> Iterator for BitEncIter<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
let value = self.bitenc.get(self.i);
self.i += 1;
value
}
}
#[cfg(test)]
mod tests {
use super::BitEnc;
#[test]
fn test_bitenc() {
let mut bitenc = BitEnc::new(2);
bitenc.push(0);
bitenc.push(2);
bitenc.push(1);
let mut values: Vec<u8> = bitenc.iter().collect();
assert_eq!(values, [0, 2, 1]);
bitenc.set(1, 3);
values = bitenc.iter().collect();
assert_eq!(values, [0, 3, 1]);
}
#[test]
fn test_push_values() {
let mut bitenc = BitEnc::new(2);
bitenc.push_values(32, 0);
assert_eq!(bitenc.storage, [0, 0]);
}
#[test]
fn test_push_values_edge_cases() {
let mut bitenc = BitEnc::new(7);
bitenc.push_values(5, 0b101010);
let values: Vec<u8> = bitenc.iter().collect();
assert_eq!(values, [42, 42, 42, 42, 42]);
assert_eq!(bitenc.nr_blocks(), 2);
assert_eq!(bitenc.nr_symbols(), 5);
bitenc.push_values(1, 23);
let values: Vec<u8> = bitenc.iter().collect();
assert_eq!(values, [42, 42, 42, 42, 42, 23]);
assert_eq!(bitenc.nr_blocks(), 2);
assert_eq!(bitenc.nr_symbols(), 6);
bitenc.push_values(12, 17);
let values: Vec<u8> = bitenc.iter().collect();
assert_eq!(
values,
[42, 42, 42, 42, 42, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17]
);
assert_eq!(bitenc.nr_blocks(), 5);
assert_eq!(bitenc.nr_symbols(), 18);
}
#[test]
fn test_issue29() {
for w in 2..9 {
let mut vec = BitEnc::with_capacity(w, 1000);
for i in 0..1000 {
println!("Push {}", i);
vec.push(1);
}
}
}
}