#![cfg(feature = "alloc")]
#[cfg(not(feature = "std"))]
use alloc::vec;
use alloc::vec::Vec;
use core::{
mem::{
self,
ManuallyDrop,
},
slice,
};
use funty::{
IsInteger,
IsNumber,
};
use tap::{
pipe::Pipe,
tap::Tap,
};
use crate::{
boxed::BitBox,
domain::Domain,
index::BitIdx,
mem::BitRegister,
mutability::{
Const,
Mut,
},
order::{
BitOrder,
Lsb0,
},
ptr::{
BitPtr,
BitSpan,
BitSpanError,
},
slice::BitSlice,
store::BitStore,
};
#[repr(C)]
pub struct BitVec<O = Lsb0, T = usize>
where
O: BitOrder,
T: BitStore,
{
bitspan: BitSpan<Mut, O, T>,
capacity: usize,
}
impl<O, T> BitVec<O, T>
where
O: BitOrder,
T: BitStore,
{
#[inline]
pub fn repeat(bit: bool, len: usize) -> Self {
let mut out = Self::with_capacity(len);
unsafe {
out.set_len(len);
}
out.set_elements(if bit { T::Mem::ALL } else { T::Mem::ZERO });
out
}
#[inline]
pub fn from_bitslice(slice: &BitSlice<O, T>) -> Self {
let mut bitspan = slice.as_bitspan();
let mut vec = bitspan
.elements()
.pipe(Vec::with_capacity)
.pipe(ManuallyDrop::new);
match slice.domain() {
Domain::Enclave { elem, .. } => vec.push(elem.load_value()),
Domain::Region { head, body, tail } => {
if let Some((_, elem)) = head {
vec.push(elem.load_value());
}
vec.extend(body.iter().map(BitStore::load_value));
if let Some((elem, _)) = tail {
vec.push(elem.load_value());
}
},
}
let bitspan = unsafe {
bitspan.set_address(vec.as_ptr() as *const T);
bitspan.assert_mut()
};
let capacity = vec.capacity();
Self { bitspan, capacity }
}
#[inline]
pub fn from_element(elem: T) -> Self {
vec![elem].pipe(Self::from_vec)
}
pub fn from_slice(slice: &[T]) -> Result<Self, BitSpanError<T>> {
slice.pipe(BitSlice::from_slice).map(Self::from_bitslice)
}
#[inline]
pub fn from_vec(vec: Vec<T>) -> Self {
Self::try_from_vec(vec)
.expect("Vector was too long to be converted into a `BitVec`")
}
#[inline]
pub fn try_from_vec(vec: Vec<T>) -> Result<Self, Vec<T>> {
let mut vec = ManuallyDrop::new(vec);
let capacity = vec.capacity();
BitPtr::from_mut_slice(vec.as_mut_slice())
.span(vec.len() * T::Mem::BITS as usize)
.map(|bitspan| Self { bitspan, capacity })
.map_err(|_| ManuallyDrop::into_inner(vec))
}
#[inline]
pub fn extend_from_bitslice<O2, T2>(&mut self, other: &BitSlice<O2, T2>)
where
O2: BitOrder,
T2: BitStore,
{
let len = self.len();
let olen = other.len();
self.resize(len + olen, false);
unsafe { self.get_unchecked_mut(len ..) }.clone_from_bitslice(other);
}
#[inline]
pub fn extend_from_raw_slice(&mut self, slice: &[T]) {
self.extend_from_bitslice(
BitSlice::<O, T>::from_slice(slice)
.expect("Slice is too long to encode as a BitSlice"),
);
}
#[inline]
pub fn elements(&self) -> usize {
self.as_bitspan().elements()
}
#[inline]
pub fn into_boxed_bitslice(mut self) -> BitBox<O, T> {
let mut bitspan = self.as_mut_bitspan();
let mut boxed =
self.into_vec().into_boxed_slice().pipe(ManuallyDrop::new);
unsafe {
bitspan.set_address(boxed.as_mut_ptr());
BitBox::from_raw(bitspan.to_bitslice_ptr_mut())
}
}
#[inline]
pub fn into_vec(self) -> Vec<T> {
let (bitspan, capacity) = (self.bitspan, self.capacity);
mem::forget(self);
unsafe {
Vec::from_raw_parts(
bitspan.address().to_mut(),
bitspan.elements(),
capacity,
)
}
}
#[inline]
pub fn set_elements(&mut self, element: T::Mem) {
self.as_mut_raw_slice()
.iter_mut()
.for_each(|elt| elt.store_value(element));
}
#[inline]
pub fn set_uninitialized(&mut self, value: bool) {
let head = self.as_bitspan().head().value() as usize;
let tail = head + self.len();
let capa = self.capacity();
let mut bp = self.as_mut_bitspan();
unsafe {
bp.set_head(BitIdx::ZERO);
bp.set_len(capa);
let bits = bp.to_bitslice_mut();
bits.get_unchecked_mut(.. head).set_all(value);
bits.get_unchecked_mut(tail ..).set_all(value);
}
}
#[inline]
pub fn force_align(&mut self) {
let bitspan = self.as_mut_bitspan();
let head = bitspan.head().value() as usize;
if head == 0 {
return;
}
let last = bitspan.len() + head;
unsafe {
self.bitspan = bitspan.tap_mut(|bp| bp.set_head(BitIdx::ZERO));
self.copy_within_unchecked(head .. last, 0);
}
}
#[cfg_attr(not(tarpaulin_include), inline(always))]
pub(crate) unsafe fn set_len_unchecked(&mut self, new_len: usize) {
self.bitspan.set_len(new_len);
}
#[cfg_attr(not(tarpaulin_include), inline(always))]
pub fn as_bitslice(&self) -> &BitSlice<O, T> {
self.bitspan.to_bitslice_ref()
}
#[cfg_attr(not(tarpaulin_include), inline(always))]
pub fn as_mut_bitslice(&mut self) -> &mut BitSlice<O, T> {
self.bitspan.to_bitslice_mut()
}
#[inline]
pub fn as_bitptr(&self) -> BitPtr<Const, O, T> {
self.bitspan.as_bitptr().immut()
}
#[cfg_attr(not(tarpaulin_include), inline(always))]
pub fn as_mut_bitptr(&mut self) -> BitPtr<Mut, O, T> {
self.bitspan.as_bitptr()
}
#[inline]
pub fn as_raw_slice(&self) -> &[T] {
unsafe {
slice::from_raw_parts(
self.bitspan.address().to_const(),
self.bitspan.elements(),
)
}
}
#[inline]
pub fn as_mut_raw_slice(&mut self) -> &mut [T] {
unsafe {
slice::from_raw_parts_mut(
self.bitspan.address().to_mut(),
self.bitspan.elements(),
)
}
}
#[inline]
pub fn as_raw_ptr(&self) -> *const T {
self.bitspan.address().to_const()
}
#[inline]
pub fn as_mut_raw_ptr(&mut self) -> *mut T {
self.bitspan.address().to_mut()
}
pub(crate) unsafe fn from_fields(
bitspan: BitSpan<Mut, O, T>,
capacity: usize,
) -> Self {
Self { bitspan, capacity }
}
fn strip_unalias(this: BitVec<O, T::Unalias>) -> Self {
let (bitspan, capacity) = (this.bitspan.cast::<T>(), this.capacity);
core::mem::forget(this);
Self { bitspan, capacity }
}
#[inline]
fn do_reservation(
&mut self,
additional: usize,
func: impl FnOnce(&mut Vec<T>, usize),
) {
let len = self.len();
let new_len = len
.checked_add(additional)
.expect("Bit-Vector capacity exceeded");
assert!(
new_len <= BitSlice::<O, T>::MAX_BITS,
"Bit-Vector capacity exceeded: {} > {}",
new_len,
BitSlice::<O, T>::MAX_BITS,
);
let bitspan = self.bitspan;
let head = bitspan.head();
let elts = bitspan.elements();
let new_elts = crate::mem::elts::<T>(head.value() as usize + new_len);
let extra = new_elts - elts;
self.with_vec(|vec| {
func(&mut **vec, extra);
vec.resize_with(new_elts, || unsafe { mem::zeroed() });
});
}
fn with_vec<F, R>(&mut self, func: F) -> R
where F: FnOnce(&mut ManuallyDrop<Vec<T>>) -> R {
let capacity = self.capacity;
let (ptr, length) =
(self.bitspan.address().to_mut(), self.bitspan.elements());
let mut vec = unsafe { Vec::from_raw_parts(ptr, length, capacity) }
.pipe(ManuallyDrop::new);
let out = func(&mut vec);
unsafe {
self.bitspan.set_address(vec.as_mut_ptr());
}
self.capacity = vec.capacity();
out
}
}
mod api;
mod iter;
mod ops;
mod traits;
pub use self::iter::{
Drain,
IntoIter,
Splice,
};
#[cfg(test)]
mod tests;