use std::{
cmp::{min, PartialEq},
fmt::{self, Debug},
hash::{Hash, Hasher},
iter::FromIterator,
mem::{replace, size_of},
ops::{
Bound::{Excluded, Included, Unbounded},
Index, Range, RangeBounds,
},
slice,
};
#[cfg(feature = "bincode")]
use bincode::{Decode, Encode};
use num_traits::{PrimInt, Zero};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
pub struct Vob<T = usize> {
len: usize,
vec: Vec<T>,
}
impl Vob<usize> {
pub fn new() -> Vob<usize> {
Default::default()
}
pub fn with_capacity(capacity: usize) -> Vob<usize> {
Vob {
len: 0,
vec: Vec::with_capacity(blocks_required::<usize>(capacity)),
}
}
pub fn from_elem(value: bool, len: usize) -> Vob<usize> {
let mut v = Vob {
len,
vec: vec![if value { !0 } else { 0 }; blocks_required::<usize>(len)],
};
v.mask_last_block();
v
}
pub fn from_bytes(slice: &[u8]) -> Vob<usize> {
let new_len = slice.len().checked_mul(8).expect("Overflow detected");
let mut v = Vob::with_capacity(new_len);
for i in 0..blocks_required::<usize>(new_len) {
let mut w = usize::zero();
for j in 0..bytes_per_block::<usize>() {
let off = i * bytes_per_block::<usize>() + j;
if off >= slice.len() {
continue;
}
let b = slice[off];
w |= (b.reverse_bits() as usize) << (j * 8);
}
v.vec.push(w);
}
v.len = new_len;
v
}
}
impl<T: Debug + PrimInt> Vob<T> {
pub fn new_with_storage_type(capacity: usize) -> Vob<T> {
Vob {
len: 0,
vec: Vec::with_capacity(blocks_required::<T>(capacity)),
}
}
pub fn from_elem_with_storage_type(value: bool, len: usize) -> Vob<T> {
let mut v = Vob {
len,
vec: vec![if value { !T::zero() } else { T::zero() }; blocks_required::<T>(len)],
};
v.mask_last_block();
v
}
pub fn capacity(&self) -> usize {
self.vec.capacity() * bits_per_block::<T>()
}
pub fn reserve(&mut self, additional: usize) {
let unused_bits: usize = self.capacity() - self.len();
if additional > unused_bits {
let needed_extra_bits = additional - unused_bits;
self.capacity()
.checked_add(needed_extra_bits)
.expect("Overflow detected");
self.vec.reserve(blocks_required::<T>(needed_extra_bits));
}
}
pub fn shrink_to_fit(&mut self) {
self.vec.shrink_to_fit();
}
pub fn truncate(&mut self, len: usize) {
if len > self.len {
return;
}
self.len = len;
self.vec.truncate(blocks_required::<T>(len));
self.mask_last_block();
}
pub fn push(&mut self, value: bool) {
debug_assert_eq!(self.vec.len(), blocks_required::<T>(self.len));
if self.len % bits_per_block::<T>() == 0 {
self.vec.push(T::zero());
}
let i = self.len;
self.len = i.checked_add(1).expect("Overflow detected");
self.set(i, value);
}
pub fn pop(&mut self) -> Option<bool> {
if self.len == 0 {
return None;
}
let v = self.get(self.len - 1);
debug_assert!(v.is_some());
let new_len = self.len - 1;
self.truncate(new_len);
v
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn split_off(&mut self, at: usize) -> Vob<T> {
debug_assert_eq!(self.vec.len(), blocks_required::<T>(self.len));
if at >= self.len {
return Vob::<T>::new_with_storage_type(0);
} else if at == 0 {
let mut result = Vob::<T>::new_with_storage_type(0);
result.vec = replace(&mut self.vec, result.vec);
result.len = replace(&mut self.len, result.len);
debug_assert_eq!(self.len, 0);
debug_assert_eq!(self.vec.len(), 0);
return result;
}
let block_to_split = blocks_required::<T>(at) - 1;
let ub = at % bits_per_block::<T>();
let mut nv = Vob::<T>::new_with_storage_type(self.len - at);
if ub > 0 {
let first_block_len = if bits_per_block::<T>() - ub > self.len - at {
self.len - at
} else {
bits_per_block::<T>() - ub
};
nv.vec.push(self.vec[block_to_split] >> ub);
nv.len = first_block_len;
nv.mask_last_block();
}
if self.vec.len() > block_to_split + 1 {
nv.extend_blocks(self, block_to_split + 1);
}
self.truncate(at);
nv
}
pub fn get(&self, index: usize) -> Option<bool> {
if index >= self.len {
return None;
}
let blk = self.vec[block_offset::<T>(index)];
Some(blk & (T::one() << (index % bits_per_block::<T>())) != T::zero())
}
pub fn set(&mut self, index: usize, value: bool) -> bool {
if index >= self.len {
panic!(
"Index out of bounds: the len is {} but the index is {}",
self.len, index
);
}
let msk = T::one() << (index % bits_per_block::<T>());
let off = block_offset::<T>(index);
let old_v = self.vec[off];
let new_v = if value { old_v | msk } else { old_v & !msk };
if new_v != old_v {
self.vec[off] = new_v;
true
} else {
false
}
}
pub fn iter(&self) -> Iter<T> {
Iter {
vob: self,
range: 0..self.len,
}
}
fn process_range<R>(&self, range: R) -> Range<usize>
where
R: RangeBounds<usize>,
{
let start = match range.start_bound() {
Included(t) => min(*t, self.len),
Excluded(t) => min(*t + 1, self.len),
Unbounded => 0,
};
let end = match range.end_bound() {
Included(t) => min(*t + 1, self.len()),
Excluded(t) => min(*t, self.len()),
Unbounded => self.len,
};
Range { start, end }
}
pub fn iter_set_bits<R>(&self, range: R) -> IterSetBits<T>
where
R: RangeBounds<usize>,
{
IterSetBits {
vob: self,
range: self.process_range(range),
}
}
pub fn iter_unset_bits<R>(&self, range: R) -> IterUnsetBits<T>
where
R: RangeBounds<usize>,
{
IterUnsetBits {
vob: self,
range: self.process_range(range),
}
}
pub fn iter_storage(&self) -> StorageIter<T> {
StorageIter {
iter: self.vec.iter(),
}
}
pub fn resize(&mut self, new_len: usize, value: bool) {
if new_len <= self.len {
self.truncate(new_len);
return;
}
if value && self.len > 0 {
let off = block_offset::<T>(self.len);
let v = self.vec[off];
self.vec[off] = v | (T::max_value() << (self.len % bits_per_block::<T>()));
}
self.vec.resize(
blocks_required::<T>(new_len),
if value { T::max_value() } else { T::zero() },
);
self.len = new_len;
self.mask_last_block();
}
pub fn extend_from_slice(&mut self, other: &[bool]) {
for &blk in other.iter() {
self.push(blk);
}
}
pub fn extend_from_vob(&mut self, other: &Vob<T>) {
self.extend_blocks(other, 0);
}
fn extend_blocks(&mut self, other: &Vob<T>, block_offset: usize) {
debug_assert!(block_offset * bits_per_block::<T>() <= other.len(),);
debug_assert_eq!(self.vec.len(), blocks_required::<T>(self.len));
self.reserve(other.len());
let ub = self.len % bits_per_block::<T>();
if ub == 0 {
self.vec.extend(other.vec.iter().skip(block_offset));
} else {
let msk = (T::one() << ub) - T::one();
for block in other.vec.iter().skip(block_offset) {
let new_block: T = block.rotate_left(ub as u32);
{
let last = self.vec.last_mut().unwrap();
debug_assert_eq!(*last & !msk, T::zero());
*last = *last | new_block & !msk;
}
self.vec.push(new_block & msk);
}
}
let new_len = self
.len
.checked_add(other.len() - block_offset * bits_per_block::<T>())
.expect("Overflow detected");
self.vec.truncate(blocks_required::<T>(new_len));
self.len = new_len;
self.mask_last_block();
}
pub fn clear(&mut self) {
self.len = 0;
self.vec.clear();
}
pub fn set_all(&mut self, value: bool) {
for blk in self.vec.iter_mut() {
*blk = if value { T::max_value() } else { T::zero() };
}
self.mask_last_block();
}
pub fn negate(&mut self) {
for blk in self.vec.iter_mut() {
*blk = !*blk;
}
self.mask_last_block();
}
pub fn and(&mut self, other: &Vob<T>) -> bool {
if self.len != other.len {
panic!(
"Cannot 'and' two Vobs of different length ({} {})",
self.len, other.len
);
}
let mut chngd = false;
for (self_blk, other_blk) in self.vec.iter_mut().zip(other.vec.iter()) {
let old_v = *self_blk;
let new_v = old_v & *other_blk;
*self_blk = new_v;
chngd |= old_v != new_v;
}
chngd
}
pub fn or(&mut self, other: &Vob<T>) -> bool {
if self.len != other.len {
panic!(
"Cannot 'or' two Vobs of different length ({} {})",
self.len, other.len
);
}
let mut chngd = false;
for (self_blk, other_blk) in self.vec.iter_mut().zip(other.vec.iter()) {
let old_v = *self_blk;
let new_v = old_v | *other_blk;
*self_blk = new_v;
chngd |= old_v != new_v;
}
chngd
}
pub fn xor(&mut self, other: &Vob<T>) -> bool {
if self.len != other.len {
panic!(
"Cannot 'xor' two Vobs of different length ({} {})",
self.len, other.len
);
}
let mut chngd = false;
for (self_blk, other_blk) in self.vec.iter_mut().zip(other.vec.iter()) {
let old_v = *self_blk;
let new_v = old_v ^ *other_blk;
*self_blk = new_v;
chngd |= old_v != new_v;
}
chngd
}
#[inline]
fn _mask_last_block(&mut self) {
debug_assert_eq!(self.vec.len(), blocks_required::<T>(self.len));
let ub = self.len % bits_per_block::<T>();
if ub > 0 {
let msk = (T::one() << ub) - T::one();
let off = block_offset::<T>(self.len);
let old_v = self.vec[off];
let new_v = old_v & msk;
if new_v != old_v {
self.vec[off] = new_v;
}
}
}
#[cfg(not(feature = "unsafe_internals"))]
fn mask_last_block(&mut self) {
self._mask_last_block()
}
#[cfg(feature = "unsafe_internals")]
pub fn mask_last_block(&mut self) {
self._mask_last_block()
}
}
#[cfg(feature = "unsafe_internals")]
impl<T> Vob<T> {
pub unsafe fn get_storage_mut(&mut self) -> &mut Vec<T> {
&mut self.vec
}
pub fn get_storage(&self) -> &[T] {
self.vec.as_ref()
}
pub unsafe fn set_len(&mut self, len: usize) {
self.len = len;
}
}
impl<T: Debug + PrimInt> Debug for Vob<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "Vob[")?;
for blk in self {
write!(fmt, "{}", if blk { 1 } else { 0 })?;
}
write!(fmt, "]")?;
Ok(())
}
}
impl<T: Debug + PrimInt> Extend<bool> for Vob<T> {
fn extend<I: IntoIterator<Item = bool>>(&mut self, iterable: I) {
let iterator = iterable.into_iter();
let (min, _) = iterator.size_hint();
self.reserve(min);
for e in iterator {
self.push(e)
}
}
}
impl FromIterator<bool> for Vob<usize> {
fn from_iter<I: IntoIterator<Item = bool>>(iter: I) -> Self {
let mut v = Vob::new();
v.extend(iter);
v
}
}
static TRUE: bool = true;
static FALSE: bool = false;
impl<T: Debug + PrimInt> Index<usize> for Vob<T> {
type Output = bool;
fn index(&self, index: usize) -> &bool {
match self.get(index) {
Some(true) => &TRUE,
Some(false) => &FALSE,
None => panic!(
"index out of bounds: the len is {} but the index is {}",
self.len, index
),
}
}
}
#[derive(Clone)]
pub struct Iter<'a, T: 'a> {
vob: &'a Vob<T>,
range: Range<usize>,
}
impl<T: Debug + PrimInt> Iterator for Iter<'_, T> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
self.range.next().map(|i| self.vob.get(i).unwrap())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
impl<T: Debug + PrimInt> DoubleEndedIterator for Iter<'_, T> {
fn next_back(&mut self) -> Option<bool> {
self.range.next_back().map(|i| self.vob.get(i).unwrap())
}
}
impl<T: Debug + PrimInt> ExactSizeIterator for Iter<'_, T> {}
impl<'a, T: Debug + PrimInt> IntoIterator for &'a Vob<T> {
type Item = bool;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
#[derive(Clone)]
pub struct IterSetBits<'a, T: 'a> {
vob: &'a Vob<T>,
range: Range<usize>,
}
impl<T: Debug + PrimInt> Iterator for IterSetBits<'_, T> {
type Item = usize;
fn next(&mut self) -> Option<usize> {
debug_assert!(self.range.end <= self.vob.len);
if let Some(i) = self.range.next() {
let mut b = block_offset::<T>(i);
let mut v = self.vob.vec[b];
if v == T::max_value() {
return Some(i);
}
let mut i_off = i % bits_per_block::<T>();
loop {
let tz = (v >> i_off).trailing_zeros() as usize;
if tz < bits_per_block::<T>() {
let bs = b * bits_per_block::<T>() + i_off + tz;
self.range.start = bs + 1;
if bs >= self.range.end {
break;
}
return Some(bs);
}
b += 1;
if b == blocks_required::<T>(self.range.end) {
self.range.start = self.range.end;
break;
}
v = self.vob.vec[b];
i_off = 0;
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
#[derive(Clone)]
pub struct IterUnsetBits<'a, T: 'a> {
vob: &'a Vob<T>,
range: Range<usize>,
}
impl<T: Debug + PrimInt> Iterator for IterUnsetBits<'_, T> {
type Item = usize;
fn next(&mut self) -> Option<usize> {
debug_assert!(self.range.end <= self.vob.len);
if let Some(i) = self.range.next() {
let mut b = block_offset::<T>(i);
let mut v = self.vob.vec[b];
if v == T::zero() {
return Some(i);
}
let mut i_off = i % bits_per_block::<T>();
loop {
let tz = (!v >> i_off).trailing_zeros() as usize;
if tz < bits_per_block::<T>() {
let bs = b * bits_per_block::<T>() + i_off + tz;
self.range.start = bs + 1;
if bs >= self.range.end {
break;
}
return Some(bs);
}
b += 1;
if b == blocks_required::<T>(self.range.end) {
self.range.start = self.range.end;
break;
}
v = self.vob.vec[b];
i_off = 0;
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
impl<T: Debug + PrimInt> PartialEq for Vob<T> {
fn eq(&self, other: &Self) -> bool {
if self.len != other.len {
return false;
}
self.iter_storage()
.zip(other.iter_storage())
.all(|(w1, w2)| w1 == w2)
}
}
impl<T: Debug + PrimInt> Eq for Vob<T> {}
impl<T: Debug + Hash + PrimInt> Hash for Vob<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
for blk in self.iter_storage() {
blk.hash(state);
}
}
}
#[derive(Clone)]
pub struct StorageIter<'a, B: 'a> {
iter: slice::Iter<'a, B>,
}
impl<T: Debug + PrimInt> Iterator for StorageIter<'_, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.iter.next().cloned()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
fn bits_per_block<T>() -> usize {
bytes_per_block::<T>() * 8
}
fn bytes_per_block<T>() -> usize {
size_of::<T>()
}
fn block_offset<T>(off: usize) -> usize {
off / bits_per_block::<T>()
}
fn blocks_required<T>(num_bits: usize) -> usize {
num_bits / bits_per_block::<T>()
+ if num_bits % bits_per_block::<T>() == 0 {
0
} else {
1
}
}
#[macro_export]
macro_rules! vob {
(@single $($x:tt)*) => (());
($($rest:expr),+,) => ( vob!($($rest),+) );
(@count $($rest:expr),*) => (<[()]>::len(&[$(vob!(@single $rest)),*]));
($val:expr; $len:expr) => (
$crate::Vob::from_elem($val, $len)
);
() => (Vob::new());
($($x:expr),*) => ({
let c = vob!(@count $($x),*);
let mut vob = $crate::Vob::with_capacity(c);
$(
vob.push($x);
)*
vob
});
}
impl<T: Debug + PrimInt> std::ops::BitOrAssign<&Vob<T>> for Vob<T> {
#[inline(always)]
fn bitor_assign(&mut self, other: &Self) {
let _ = self.or(other);
}
}
impl<T: Debug + PrimInt> std::ops::BitOr<&Vob<T>> for &Vob<T> {
type Output = Vob<T>;
#[inline(always)]
fn bitor(self, other: &Vob<T>) -> Vob<T> {
let mut rv = self.clone();
let _ = rv.or(other);
rv
}
}
impl<T: Debug + PrimInt> std::ops::BitOr<&Vob<T>> for Vob<T> {
type Output = Self;
#[inline(always)]
fn bitor(mut self, other: &Self) -> Self {
let _ = self.or(other);
self
}
}
impl<T: Debug + PrimInt> std::ops::BitAndAssign<&Vob<T>> for Vob<T> {
#[inline(always)]
fn bitand_assign(&mut self, other: &Self) {
let _ = self.and(other);
}
}
impl<T: Debug + PrimInt> std::ops::BitAnd<&Vob<T>> for &Vob<T> {
type Output = Vob<T>;
#[inline(always)]
fn bitand(self, other: &Vob<T>) -> Vob<T> {
let mut rv = self.clone();
let _ = rv.and(other);
rv
}
}
impl<T: Debug + PrimInt> std::ops::BitAnd<&Vob<T>> for Vob<T> {
type Output = Self;
#[inline(always)]
fn bitand(mut self, other: &Self) -> Self {
let _ = self.and(other);
self
}
}
impl<T: Debug + PrimInt> std::ops::BitXorAssign<&Vob<T>> for Vob<T> {
#[inline(always)]
fn bitxor_assign(&mut self, other: &Self) {
let _ = self.xor(other);
}
}
impl<T: Debug + PrimInt> std::ops::BitXor<&Vob<T>> for &Vob<T> {
type Output = Vob<T>;
#[inline(always)]
fn bitxor(self, other: &Vob<T>) -> Vob<T> {
let mut rv = self.clone();
let _ = rv.xor(other);
rv
}
}
impl<T: Debug + PrimInt> std::ops::BitXor<&Vob<T>> for Vob<T> {
type Output = Self;
#[inline(always)]
fn bitxor(mut self, other: &Self) -> Self {
let _ = self.xor(other);
self
}
}
#[cfg(test)]
mod tests {
use super::{block_offset, blocks_required, Vob};
use rand::{self, Rng};
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
iter::FromIterator,
mem::size_of,
};
#[test]
fn test_block_offset() {
assert_eq!(block_offset::<usize>(0), 0);
assert_eq!(block_offset::<usize>(1), 0);
assert_eq!(block_offset::<usize>(2), 0);
assert_eq!(block_offset::<usize>(size_of::<usize>() * 8 - 1), 0);
assert_eq!(block_offset::<usize>(size_of::<usize>() * 8), 1);
}
#[test]
fn test_blocks_required() {
assert_eq!(blocks_required::<usize>(0), 0);
assert_eq!(blocks_required::<usize>(1), 1);
assert_eq!(blocks_required::<usize>(2), 1);
assert_eq!(blocks_required::<usize>(size_of::<usize>() * 8), 1);
assert_eq!(blocks_required::<usize>(size_of::<usize>() * 8 + 1), 2);
}
#[test]
fn test_non_usize_storage() {
let mut v = Vob::<u8>::new_with_storage_type(0);
for _ in 0..size_of::<u8>() * 8 {
v.push(true);
}
assert_eq!(v.get(0), Some(true));
assert_eq!(v.get(size_of::<u8>() * 8 - 1), Some(true));
assert_eq!(v.get(size_of::<u8>() * 8), None);
v.push(true);
assert_eq!(v.get(size_of::<u8>() * 8), Some(true));
v.set(size_of::<u8>() * 8, false);
assert_eq!(v.get(size_of::<u8>() * 8), Some(false));
assert_eq!(v.get(size_of::<u8>() * 8 + 1), None);
assert_eq!(v.set(size_of::<u8>() * 8, true), true);
assert_eq!(v.set(size_of::<u8>() * 8, true), false);
assert_eq!(v.get(size_of::<u8>() * 8 - 1), Some(true));
assert_eq!(v.get(size_of::<u8>() * 8 - 2), Some(true));
}
#[test]
fn test_capacity() {
assert_eq!(Vob::new().capacity(), 0);
assert_eq!(
Vob::with_capacity(size_of::<usize>() * 8 + 1).capacity(),
size_of::<usize>() * 8 * 2
);
}
#[test]
fn test_reserve() {
let mut v = Vob::new();
v.reserve(10);
assert!(v.capacity() >= size_of::<usize>() * 8);
v.reserve(10);
assert!(v.capacity() >= size_of::<usize>() * 8, "over-reserved");
v.push(true); v.reserve(size_of::<usize>() * 8);
assert!(v.capacity() >= size_of::<usize>() * 8 * 2);
}
#[test]
#[should_panic(expected = "Overflow detected")]
fn test_reserve_panic() {
let mut v = Vob::new();
v.push(true);
v.push(true);
v.reserve(usize::MAX);
}
#[test]
fn test_beyond_a_word() {
let mut v = Vob::new();
for _ in 0..size_of::<usize>() * 8 {
v.push(true);
}
assert_eq!(v.get(0), Some(true));
assert_eq!(v.get(size_of::<usize>() * 8 - 1), Some(true));
assert_eq!(v.get(size_of::<usize>() * 8), None);
v.push(true);
assert_eq!(v.get(size_of::<usize>() * 8), Some(true));
v.set(size_of::<usize>() * 8, false);
assert_eq!(v.get(size_of::<usize>() * 8), Some(false));
assert_eq!(v.get(size_of::<usize>() * 8 + 1), None);
assert_eq!(v.set(size_of::<usize>() * 8, true), true);
assert_eq!(v.set(size_of::<usize>() * 8, true), false);
assert_eq!(v.get(size_of::<usize>() * 8 - 1), Some(true));
assert_eq!(v.get(size_of::<usize>() * 8 - 2), Some(true));
}
#[test]
#[should_panic(expected = "Index out of bounds")]
fn test_set_beyond_a_word() {
let mut v = vob![true];
assert_eq!(v.set(0, false), true);
v.set(1, true);
}
#[test]
fn test_from_bytes() {
let v = Vob::from_bytes(&[]);
assert_eq!(v, vob![]);
let v = Vob::from_bytes(&[0b10100000, 0b00010010]);
assert_eq!(
v,
vob![
true, false, true, false, false, false, false, false, false, false, false, true,
false, false, true, false
]
);
let v = Vob::from_bytes(&[
0b10100000, 0b00010010, 0b00110101, 0b11001010, 0b00110001, 0b10010101, 0b01111100,
0b01010001,
]);
assert_eq!(
v,
vob![
true, false, true, false, false, false, false, false, false, false, false, true,
false, false, true, false, false, false, true, true, false, true, false, true,
true, true, false, false, true, false, true, false, false, false, true, true,
false, false, false, true, true, false, false, true, false, true, false, true,
false, true, true, true, true, true, false, false, false, true, false, true, false,
false, false, true
]
);
}
#[test]
fn test_truncate() {
let mut v = Vob::from_elem(true, 2 * size_of::<usize>() * 8 + 1);
assert_eq!(v, Vob::from_elem(true, 2 * size_of::<usize>() * 8 + 1));
v.truncate(2 * size_of::<usize>() * 8 + 1);
assert_eq!(v, Vob::from_elem(true, 2 * size_of::<usize>() * 8 + 1));
v.truncate(3 * size_of::<usize>() * 8 + 1);
assert_eq!(v, Vob::from_elem(true, 2 * size_of::<usize>() * 8 + 1));
v.truncate(0);
assert_eq!(v, Vob::new());
}
#[test]
fn test_from_elem_with_storaget() {
let mut v = Vob::<u64>::from_elem_with_storage_type(true, 2 * size_of::<usize>() * 8 + 1);
assert_eq!(
v,
Vob::<u64>::from_elem_with_storage_type(true, 2 * size_of::<usize>() * 8 + 1)
);
v.truncate(2 * size_of::<usize>() * 8 + 1);
assert_eq!(
v,
Vob::<u64>::from_elem_with_storage_type(true, 2 * size_of::<usize>() * 8 + 1)
);
v.truncate(3 * size_of::<usize>() * 8 + 1);
assert_eq!(
v,
Vob::<u64>::from_elem_with_storage_type(true, 2 * size_of::<usize>() * 8 + 1)
);
v.truncate(0);
assert_eq!(v, Vob::<u64>::new_with_storage_type(0));
}
#[test]
fn test_is_empty() {
assert_eq!(vob![].is_empty(), true);
assert_eq!(vob![true].is_empty(), false);
}
#[test]
fn test_resize() {
let mut v = Vob::new();
v.resize(1, true);
assert_eq!(v[0], true);
let mut v = Vob::new();
v.push(false);
v.resize(129, true);
assert_eq!(v.len(), 129);
assert_eq!(v.get(0), Some(false));
assert_eq!(v.get(1), Some(true));
assert_eq!(v.get(128), Some(true));
v.resize(1, true);
assert_eq!(v.len(), 1);
assert_eq!(v.get(0), Some(false));
let mut v = Vob::new();
v.push(false);
v.resize(2, true);
assert_eq!(v.len(), 2);
assert_eq!(v.get(0), Some(false));
assert_eq!(v.get(1), Some(true));
}
#[test]
fn test_mask_last_block1() {
let mut v = Vob::<u64>::new_with_storage_type(0);
v.extend(vob![true, true].iter());
assert_eq!(v.vec, vec![3]);
v.vec[0] = 0xaaaaaaaa;
v.len = 7;
v.mask_last_block();
assert_eq!(v.vec, vec![42]);
v.len = 30;
v.vec[0] = 0xffffaaaa;
v.mask_last_block();
assert_eq!(v.vec, vec![1073719978]);
}
#[test]
fn test_mask_last_block2() {
let mut v = Vob::<u64>::new_with_storage_type(128);
for _ in 0..128 {
v.push(true);
}
let full_block = 0xffffffffffffffff;
assert_eq!(v.vec, vec![full_block, full_block]);
let one_zero = 0xaaaaaaaaaaaaaaaa;
v.len = 68;
v.vec[0] = one_zero;
v.vec[1] = v.vec[0];
v.mask_last_block();
assert_eq!(v.vec, vec![one_zero, 0b1010]);
}
#[test]
fn test_index() {
let v1 = vob![false, true];
assert_eq!(v1[0], false);
assert_eq!(v1[1], true);
}
#[test]
fn test_iter_set_bits() {
let mut v1 = vob![false, true, false, true];
assert_eq!(v1.iter_set_bits(..).collect::<Vec<usize>>(), vec![1, 3]);
v1.resize(127, false);
v1.push(true);
v1.push(false);
v1.push(true);
v1.push(true);
v1.resize(256, false);
v1.push(true);
assert_eq!(
v1.iter_set_bits(..).collect::<Vec<usize>>(),
vec![1, 3, 127, 129, 130, 256]
);
assert_eq!(
v1.iter_set_bits(2..256).collect::<Vec<usize>>(),
vec![3, 127, 129, 130]
);
assert_eq!(
v1.iter_set_bits(2..).collect::<Vec<usize>>(),
vec![3, 127, 129, 130, 256]
);
assert_eq!(v1.iter_set_bits(..3).collect::<Vec<usize>>(), vec![1]);
}
#[test]
fn test_iter_unset_bits() {
let mut v1 = vob![false, true, false, false];
assert_eq!(
v1.iter_unset_bits(..).collect::<Vec<usize>>(),
vec![0, 2, 3]
);
assert_eq!(
v1.iter_unset_bits(..10).collect::<Vec<usize>>(),
vec![0, 2, 3]
);
v1.resize(127, true);
v1.push(false);
v1.push(true);
v1.push(false);
v1.push(false);
v1.resize(256, true);
v1.push(false);
assert_eq!(
v1.iter_unset_bits(..).collect::<Vec<usize>>(),
vec![0, 2, 3, 127, 129, 130, 256]
);
assert_eq!(
v1.iter_unset_bits(3..256).collect::<Vec<usize>>(),
vec![3, 127, 129, 130]
);
}
#[test]
fn test_eq() {
let v1 = Vob::from_iter(vec![true, false]);
let v2 = Vob::from_iter(vec![true, false]);
assert_eq!(v1, v2);
let v3 = Vob::from_iter(vec![true, true]);
assert_ne!(v1, v3);
let v4 = Vob::from_iter(vec![true, false, true]);
assert_ne!(v1, v4);
}
#[test]
fn test_hash() {
fn hash<T: Hash>(t: &T) -> u64 {
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}
let v1 = vob![true, false];
let v2 = vob![false, true];
let v3 = vob![true, false];
assert_eq!(hash(&v1), hash(&v3));
assert_ne!(hash(&v1), hash(&v2));
assert_ne!(hash(&v2), hash(&v3));
}
#[test]
fn test_macros() {
let v1 = vob![true, false];
let mut v2 = Vob::new();
v2.push(true);
v2.push(false);
assert_eq!(v1, v2);
v2.set(1, true);
assert_eq!(v2, vob![true; 2]);
assert_ne!(v2, vob![false; 2]);
}
fn random_vob(len: usize) -> Vob {
let mut rng = rand::rng();
let mut vob = Vob::with_capacity(len);
for _ in 0..len {
vob.push(rng.random());
}
vob
}
#[test]
fn test_extend_from_vob() {
let mut rng = rand::rng();
for _ in 0..200 {
let len_a: u8 = rng.random();
let len_b: u8 = rng.random();
let mut a = random_vob(len_a as usize);
let mut a_copy = a.clone();
let b = random_vob(len_b as usize);
a.extend_from_vob(&b);
a_copy.extend(b.iter());
assert_eq!(a_copy, a);
assert_eq!(a_copy.vec, a.vec);
}
}
#[test]
#[cfg(feature = "unsafe_internals")]
fn test_storage_mut() {
let mut v1 = vob![true, false, true];
{
let storage = unsafe { v1.get_storage_mut() };
assert_eq!(storage[0], 0b101);
storage[0] = 0b111;
}
assert_eq!(v1.get(1), Some(true));
}
#[test]
fn test_split_off() {
for len_a in 0..128 {
for len_b in 0..128 {
let a = random_vob(len_a as usize);
let b = random_vob(len_b as usize);
let mut joined = a.clone();
joined.extend_from_vob(&b);
assert_eq!(joined.len(), len_a + len_b);
let b_ = joined.split_off(len_a as usize);
assert_eq!(a, joined, "lower part for {}, {}", len_a, len_b);
assert_eq!(b, b_, "upper part for {}, {}", len_a, len_b);
}
}
}
#[test]
fn push_adjusts_vec_correctly() {
let mut v = Vob::new();
v.push(false);
assert_eq!(v.vec.len(), 1);
v.pop();
v.push(true);
assert_eq!(v.vec.len(), 1);
}
}