#![cfg(feature = "alloc")]
use crate::{
boxed::BitBox,
index::BitIdx,
mem::BitMemory,
order::{
BitOrder,
Lsb0,
},
pointer::BitPtr,
slice::BitSlice,
store::BitStore,
};
use alloc::vec::Vec;
use core::{
mem::ManuallyDrop,
ptr::NonNull,
slice,
};
use funty::IsInteger;
use tap::{
pipe::Pipe,
tap::Tap,
};
#[repr(C)]
pub struct BitVec<O = Lsb0, T = usize>
where
O: BitOrder,
T: BitStore,
{
pointer: NonNull<BitSlice<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 bitptr = slice.bitptr();
let (base, elts) = (bitptr.pointer().to_const(), bitptr.elements());
let source = unsafe { slice::from_raw_parts(base, elts) };
let vec = elts
.pipe(Vec::with_capacity)
.pipe(ManuallyDrop::new)
.tap_mut(|v| v.extend(source.iter().map(BitStore::load_value)));
unsafe {
bitptr.set_pointer(vec.as_ptr() as *const T);
}
let capacity = vec.capacity();
Self {
pointer: bitptr.to_nonnull(),
capacity,
}
}
#[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 len = vec.len();
if len > BitSlice::<O, T>::MAX_ELTS {
return Err(vec);
}
let vec = ManuallyDrop::new(vec);
let (base, capacity) = (vec.as_ptr(), vec.capacity());
Ok(Self {
pointer: unsafe {
BitPtr::new_unchecked(
base,
BitIdx::ZERO,
len * T::Mem::BITS as usize,
)
}
.to_nonnull(),
capacity,
})
}
#[inline]
pub fn extend_from_bitslice(&mut self, other: &BitSlice<O, T>) {
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 into_boxed_bitslice(self) -> BitBox<O, T> {
let mut bitptr = self.bitptr();
let boxed = self.into_boxed_slice().pipe(ManuallyDrop::new);
unsafe {
bitptr.set_pointer(boxed.as_ptr());
}
unsafe { BitBox::from_raw(bitptr.to_bitslice_ptr_mut::<O>()) }
}
#[inline]
pub fn into_vec(self) -> Vec<T> {
let mut this = ManuallyDrop::new(self);
let buf = this.as_mut_slice();
unsafe {
Vec::from_raw_parts(
buf.as_mut_ptr() as *mut T,
buf.len(),
this.capacity,
)
}
}
#[inline]
pub fn elements(&self) -> usize {
self.bitptr().elements()
}
#[inline]
pub fn set_uninitialized(&mut self, value: bool) {
let head = self.bitptr().head().value() as usize;
let tail = head + self.len();
let capa = self.capacity();
let mut bp = self.bitptr();
unsafe {
bp.set_head(BitIdx::ZERO);
bp.set_len(capa);
let bits = bp.to_bitslice_mut::<O>();
bits.get_unchecked_mut(.. head).set_all(value);
bits.get_unchecked_mut(tail ..).set_all(value);
}
}
#[inline]
pub fn force_align(&mut self) {
let bitptr = self.bitptr();
let head = bitptr.head().value() as usize;
if head == 0 {
return;
}
let last = bitptr.len() + head;
unsafe {
self.pointer =
bitptr.tap_mut(|bp| bp.set_head(BitIdx::ZERO)).to_nonnull();
self.copy_within_unchecked(head .. last, 0);
}
}
#[inline]
pub fn set_elements(&mut self, element: T::Mem) {
self.as_mut_slice()
.iter_mut()
.for_each(|elt| *elt = element.into());
}
#[inline]
#[cfg(not(tarpaulin_include))]
pub fn as_bitslice(&self) -> &BitSlice<O, T> {
unsafe { &*self.pointer.as_ptr() }
}
#[inline]
#[cfg(not(tarpaulin_include))]
pub fn as_mut_bitslice(&mut self) -> &mut BitSlice<O, T> {
unsafe { &mut *self.pointer.as_ptr() }
}
#[inline]
#[cfg(not(tarpaulin_include))]
pub fn as_bitptr(&self) -> *const BitSlice<O, T> {
self.pointer.as_ptr() as *const BitSlice<O, T>
}
#[inline]
#[cfg(not(tarpaulin_include))]
pub fn as_mut_bitptr(&mut self) -> *mut BitSlice<O, T> {
self.pointer.as_ptr()
}
#[inline]
#[cfg(not(tarpaulin_include))]
pub(crate) fn bitptr(&self) -> BitPtr<T> {
self.pointer.as_ptr().pipe(BitPtr::from_bitslice_ptr_mut)
}
fn with_vec<F, R>(&mut self, func: F) -> R
where F: FnOnce(&mut ManuallyDrop<Vec<T::Mem>>) -> R {
let cap = self.capacity;
let mut bitptr = self.bitptr();
let (base, elts) =
(bitptr.pointer().to_mut() as *mut T::Mem, bitptr.elements());
let mut vec = unsafe { Vec::from_raw_parts(base, elts, cap) }
.pipe(ManuallyDrop::new);
let out = func(&mut vec);
unsafe {
bitptr.set_pointer(vec.as_ptr() as *mut T);
}
self.pointer = bitptr.to_nonnull();
self.capacity = vec.capacity();
out
}
}
mod api;
mod iter;
mod ops;
mod traits;
pub use iter::{
Drain,
IntoIter,
Splice,
};
#[cfg(test)]
mod tests;