#![no_std]
extern crate alloc;
pub use self::iter::{IntoIter, Iter};
use alloc::vec::Vec;
use core::cmp::max;
mod bitwise;
mod convert;
mod eq;
mod extend;
mod fmt;
mod hash;
mod index;
mod iter;
mod macros;
#[cfg(feature = "serde")]
mod serde;
const BITS_PER_BYTE: usize = u8::BITS as usize;
const BITS_PER_WORD: usize = usize::BITS as usize;
const BYTES_PER_WORD: usize = size_of::<usize>();
#[derive(Clone, Default)]
pub struct BitVec {
len: usize,
data: Vec<usize>,
}
impl BitVec {
#[inline]
pub const fn new() -> Self {
let len = 0;
let data = Vec::new();
Self { len, data }
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
let len = 0;
let words = Self::words_required(capacity);
let data = Vec::with_capacity(words);
Self { len, data }
}
}
impl BitVec {
#[inline]
pub fn capacity(&self) -> usize {
self.data.capacity().saturating_mul(BITS_PER_WORD)
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
}
impl BitVec {
#[inline]
pub fn get(&self, index: usize) -> Option<bool> {
if index >= self.len {
None
} else {
unsafe { Some(self.get_unchecked(index)) }
}
}
pub unsafe fn get_unchecked(&self, index: usize) -> bool {
let (div, rem) = (index / BITS_PER_WORD, index % BITS_PER_WORD);
let word = unsafe { self.data.get_unchecked(div) };
let mask = 1 << (BITS_PER_WORD - 1 - rem);
word & mask != 0
}
#[inline]
#[must_use]
pub fn set(&mut self, index: usize, value: bool) -> Option<&mut Self> {
if index >= self.len {
None
} else {
unsafe { Some(self.set_unchecked(index, value)) }
}
}
pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) -> &mut Self {
let (div, rem) = (index / BITS_PER_WORD, index % BITS_PER_WORD);
let word = unsafe { self.data.get_unchecked_mut(div) };
let mask = 1 << (BITS_PER_WORD - 1 - rem);
if value {
*word |= mask;
} else {
*word &= !mask;
}
self
}
pub fn push(&mut self, value: bool) -> &mut Self {
if self.len == usize::MAX {
panic!("capacity overflow")
}
if self.len % BITS_PER_WORD != 0 {
unsafe {
self.set_unchecked(self.len, value);
}
} else if value {
self.data.push(const { 1 << (BITS_PER_WORD - 1) });
} else {
self.data.push(0);
}
self.len += 1;
self
}
pub fn pop(&mut self) -> Option<bool> {
if self.is_empty() {
return None;
}
let last = self.len - 1;
let value = unsafe { self.get_unchecked(last) };
if last % BITS_PER_WORD == 0 {
unsafe {
self.data.set_len(self.data.len() - 1);
}
}
self.len = last;
Some(value)
}
#[inline]
pub fn shrink_to_fit(&mut self) -> &mut Self {
let min_words = Self::words_required(self.len);
self.data.truncate(min_words);
self.data.shrink_to_fit();
self
}
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) -> &mut Self {
let min_capacity = max(self.len, min_capacity);
let min_words = Self::words_required(min_capacity);
self.data.truncate(min_words);
self.data.shrink_to_fit();
self
}
}
impl BitVec {
fn bytes_required(bits: usize) -> usize {
if bits == 0 {
0
} else {
(bits - 1) / BITS_PER_BYTE + 1
}
}
fn words_required(bits: usize) -> usize {
if bits == 0 {
0
} else {
(bits - 1) / BITS_PER_WORD + 1
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
#[test]
fn test_new() {
let vec = BitVec::new();
assert_eq!(vec.len, 0);
assert_eq!(vec.data, Vec::new());
}
#[test]
fn test_with_capacity() {
let vec = BitVec::with_capacity(0);
assert_eq!(vec.len, 0);
assert_eq!(vec.data.len(), 0);
assert_eq!(vec.data.capacity(), 0);
let vec = BitVec::with_capacity(1);
assert_eq!(vec.len, 0);
assert_eq!(vec.data.len(), 0);
assert_eq!(vec.data.capacity(), 1);
let vec = BitVec::with_capacity(BITS_PER_WORD);
assert_eq!(vec.len, 0);
assert_eq!(vec.data.len(), 0);
assert_eq!(vec.data.capacity(), 1);
let vec = BitVec::with_capacity(BITS_PER_WORD + 1);
assert_eq!(vec.len, 0);
assert_eq!(vec.data.len(), 0);
assert_eq!(vec.data.capacity(), 2);
}
#[test]
fn test_capacity() {
let vec = BitVec::with_capacity(0);
assert_eq!(vec.capacity(), 0);
let vec = BitVec::with_capacity(1);
assert_eq!(vec.capacity(), BITS_PER_WORD);
let vec = BitVec::with_capacity(BITS_PER_WORD);
assert_eq!(vec.capacity(), BITS_PER_WORD);
let vec = BitVec::with_capacity(BITS_PER_WORD + 1);
assert_eq!(vec.capacity(), BITS_PER_WORD * 2);
}
#[test]
fn test_get() {
let vec = bitvec![true, true, false, false];
assert_eq!(vec.get(0), Some(true));
assert_eq!(vec.get(1), Some(true));
assert_eq!(vec.get(2), Some(false));
assert_eq!(vec.get(3), Some(false));
assert_eq!(vec.get(4), None);
let vec = bitvec![true; BITS_PER_WORD];
assert_eq!(vec.get(BITS_PER_WORD - 1), Some(true));
assert_eq!(vec.get(BITS_PER_WORD), None);
let vec = bitvec![true; BITS_PER_WORD + 1];
assert_eq!(vec.get(BITS_PER_WORD), Some(true));
assert_eq!(vec.get(BITS_PER_WORD + 1), None);
}
#[test]
fn test_set() {
let mut vec = bitvec![true, true, false, false];
assert!(vec.set(0, true).is_some());
assert!(vec.set(1, false).is_some());
assert!(vec.set(2, true).is_some());
assert!(vec.set(3, false).is_some());
assert!(vec.set(4, true).is_none());
assert_eq!(vec, bitvec![true, false, true, false]);
let mut vec = bitvec![true; BITS_PER_WORD];
assert_eq!(vec.get(BITS_PER_WORD - 1), Some(true));
assert!(vec.set(BITS_PER_WORD - 1, false).is_some());
assert_eq!(vec.get(BITS_PER_WORD - 1), Some(false));
assert!(vec.set(BITS_PER_WORD, false).is_none());
let mut vec = bitvec![true; BITS_PER_WORD + 1];
assert_eq!(vec.get(BITS_PER_WORD), Some(true));
assert!(vec.set(BITS_PER_WORD, false).is_some());
assert_eq!(vec.get(BITS_PER_WORD), Some(false));
assert!(vec.set(BITS_PER_WORD + 1, false).is_none());
}
#[test]
fn test_push() {
let mut vec = bitvec![true, true, false, false];
vec.push(true);
assert_eq!(vec, bitvec![true, true, false, false, true]);
vec.push(false);
assert_eq!(vec, bitvec![true, true, false, false, true, false]);
let mut vec = bitvec![true; BITS_PER_WORD - 1];
vec.push(true);
assert_eq!(vec.len, BITS_PER_WORD);
assert_eq!(vec.data, vec![usize::MAX]);
vec.push(false);
assert_eq!(vec.len, BITS_PER_WORD + 1);
assert_eq!(vec.data, vec![usize::MAX, 0]);
}
#[test]
fn test_pop() {
let mut vec = bitvec![true, true, false, false];
assert_eq!(vec.pop(), Some(false));
assert_eq!(vec, bitvec![true, true, false]);
assert_eq!(vec.pop(), Some(false));
assert_eq!(vec, bitvec![true, true]);
assert_eq!(vec.pop(), Some(true));
assert_eq!(vec, bitvec![true]);
assert_eq!(vec.pop(), Some(true));
assert_eq!(vec, bitvec![]);
assert_eq!(vec.pop(), None);
assert_eq!(vec, bitvec![]);
let mut vec = bitvec![false; BITS_PER_WORD + 1];
vec.push(true);
assert_eq!(vec.pop(), Some(true));
assert_eq!(vec.pop(), Some(false));
let mut vec = bitvec![true; BITS_PER_WORD + 1];
while vec.pop().is_some() {}
assert_eq!(vec.len, 0);
assert_eq!(vec.data.len(), 0);
}
}