use std::fmt::{Binary, Debug, Write};
#[doc = include_str!("../README.md")]
#[cfg(doctest)]
struct ReadmeDoctests;
#[derive(Default, Clone)]
pub struct BoolVec {
bytes: Vec<u8>,
capacity: usize,
length: usize,
}
struct BoolIndex {
byte_index: usize,
bit_index: u8,
}
pub struct BoolVecIter<'a> {
vec: &'a BoolVec,
counter: usize,
}
impl BoolIndex {
fn from(int_index: usize) -> Self {
BoolIndex {
byte_index: int_index / 8,
bit_index: (int_index % 8) as u8,
}
}
}
impl BoolVec {
pub fn new() -> Self {
Self {
bytes: Vec::new(),
capacity: 0,
length: 0,
}
}
#[allow(clippy::slow_vector_initialization)]
pub fn with_capacity(capacity: usize) -> Self {
if capacity == 0 {
return Self::new();
}
let byte_capacity = ((capacity - 1) / 8) + 1;
let mut bytes = Vec::with_capacity(byte_capacity);
bytes.resize(byte_capacity, 0);
Self {
bytes,
capacity: byte_capacity * 8,
length: 0,
}
}
pub fn from<S: AsRef<[bool]>>(slice: S) -> Self {
let slice = slice.as_ref();
let mut bool_vec = Self::with_capacity(slice.len());
for b in slice {
bool_vec.push(*b);
}
bool_vec
}
pub fn get(&self, int_index: usize) -> Option<bool> {
let index = BoolIndex::from(int_index);
if int_index >= self.length {
return None;
}
Some((self.bytes[index.byte_index] << index.bit_index) & 128 == 128)
}
pub fn set(&mut self, int_index: usize, value: bool) -> Option<()> {
let index = BoolIndex::from(int_index);
if int_index >= self.length {
return None;
}
let byte = &mut self.bytes[index.byte_index];
if value {
*byte |= 1 << (7 - index.bit_index);
} else {
*byte &= !(1 << (7 - index.bit_index));
}
Some(())
}
pub fn negate(&mut self, int_index: usize) -> Option<bool> {
let negated_value = !self.get(int_index)?;
let _ = self.set(int_index, negated_value);
Some(negated_value)
}
pub fn push(&mut self, value: bool) {
self.length += 1;
if self.length > self.capacity {
self.bytes.push(0);
self.capacity = self.bytes.capacity()*8;
}
let _ = self.set(self.length - 1, value);
}
pub fn pop(&mut self) -> Option<bool> {
if self.length == 0 {
return None;
}
let to_return = self.get(self.length - 1);
self.set(self.length - 1, false)?;
self.length -= 1;
to_return
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn len(&self) -> usize {
self.length
}
pub fn is_empty(&self) -> bool {
self.length == 0
}
pub fn bytes_capacity(&self) -> usize {
self.bytes.capacity()
}
pub fn bytes_len(&self) -> usize {
self.bytes.len()
}
pub fn into_vec(&self) -> Vec<bool> {
let mut new_vec = Vec::with_capacity(self.len());
for b in self {
new_vec.push(b);
}
new_vec
}
}
impl PartialEq for BoolVec {
fn eq(&self, other: &Self) -> bool {
if self.length != other.length {
return false;
}
let min_length = if self.bytes_len() <= other.bytes_len() {
self.bytes_len()
} else {
other.bytes_len()
};
self.bytes[..min_length] == other.bytes[..min_length]
}
}
impl Debug for BoolVec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.length == 0 {
return f.write_str("[]");
}
if !f.alternate() {
return f.debug_list().entries(self).finish();
}
f.write_str("[\n")?;
let mut counter = 0;
for b in self {
if counter % 8 == 0 {
f.write_str(" ")?;
}
f.write_str(b.to_string().as_str())?;
if b {
f.write_char(' ')?;
}
counter += 1;
if counter < self.length {
f.write_str(", ")?;
}
if counter % 8 == 0 {
f.write_char('\n')?;
}
}
f.write_str("\n]")
}
}
impl Binary for BoolVec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.length == 0 {
return f.write_str("[]");
}
let mut counter = 0;
f.write_char('[')?;
if f.alternate() {
f.write_char('\n')?;
}
for byte in self.bytes.iter() {
if f.alternate() {
f.write_str(" ")?;
}
std::fmt::Binary::fmt(byte, f)?;
counter += 1;
if counter < self.bytes.len() {
f.write_str(", ")?;
if f.alternate() {
f.write_char('\n')?;
}
}
}
if f.alternate() {
f.write_char('\n')?;
}
f.write_char(']')
}
}
impl<'a> IntoIterator for &'a BoolVec {
type Item = bool;
type IntoIter = BoolVecIter<'a>;
fn into_iter(self) -> Self::IntoIter {
BoolVecIter {
vec: self,
counter: 0,
}
}
}
impl<'a> Iterator for BoolVecIter<'a> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
let item = self.vec.get(self.counter)?;
self.counter += 1;
Some(item)
}
}
#[macro_export]
macro_rules! boolvec {
[$($val:expr),*] => [
{
count_macro::count!{
$(
let _ = $val;
let _ = _int_;
)*
let mut vec = bool_vec::BoolVec::with_capacity(_int_);
}
$(
vec.push($val);
)*
vec
}
];
[$val:expr; $length:expr] => [
{
let mut vec = bool_vec::BoolVec::with_capacity($length);
for x in 0..$length {
vec.push($val);
}
vec
}
];
}