use crate::{
access::BitAccess,
indices::BitIdx,
order::BitOrder,
pointer::BitPtr,
slice::{
BitSlice,
iter::{
Chunks,
ChunksExact,
ChunksExactMut,
ChunksMut,
GenericSplitN,
Iter,
IterMut,
RChunks,
RChunksExact,
RChunksExactMut,
RChunksMut,
RSplit,
RSplitMut,
RSplitN,
RSplitNMut,
Split,
SplitMut,
SplitN,
SplitNMut,
Windows,
},
proxy::BitMut,
},
store::BitStore,
};
use core::{
cmp,
marker::PhantomData,
ops::{
Range,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
},
ptr::NonNull,
slice,
};
#[cfg(feature = "alloc")]
use crate::vec::BitVec;
pub unsafe fn bits_from_raw_parts<'a, O, T>(
data: *const T,
head: BitIdx<T>,
bits: usize,
) -> &'a BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
BitPtr::new(data, head, bits).into_bitslice()
}
pub unsafe fn bits_from_raw_parts_mut<'a, O, T>(
data: *mut T,
head: BitIdx<T>,
bits: usize,
) -> &'a mut BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
BitPtr::new(data, head, bits).into_bitslice_mut()
}
pub fn from_mut<O, T>(elt: &mut T) -> &mut BitSlice<O, T>
where O: BitOrder, T: BitStore {
BitSlice::from_element_mut(elt)
}
pub unsafe fn from_raw_parts<'a, O, T>(
data: *const T,
len: usize,
) -> &'a BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
BitSlice::from_slice(slice::from_raw_parts(data, len))
}
pub unsafe fn from_raw_parts_mut<'a, O, T>(
data: *mut T,
len: usize,
) -> &'a mut BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
BitSlice::from_slice_mut(slice::from_raw_parts_mut(data, len))
}
pub fn from_ref<O, T>(elt: &T) -> &BitSlice<O, T>
where O: BitOrder, T: BitStore {
BitSlice::from_element(elt)
}
impl<O, T> BitSlice<O, T>
where O: BitOrder, T: BitStore {
pub fn len(&self) -> usize {
self.bitptr().len()
}
pub fn is_empty(&self) -> bool {
self.bitptr().len() == 0
}
#[inline]
pub fn first(&self) -> Option<&bool> {
0.get(self)
}
#[inline]
pub fn first_mut(&mut self) -> Option<BitMut<O, T>> {
0.get_mut(self)
}
#[inline]
pub fn split_first(&self) -> Option<(&bool, &Self)> {
if self.is_empty() {
None
}
else {
let (head, rest) = self.split_at(1);
unsafe { Some((0.get_unchecked(head), rest)) }
}
}
#[inline]
pub fn split_first_mut(&mut self) -> Option<(BitMut<O, T>, &mut Self)> {
if self.is_empty() {
None
}
else {
let (head, rest) = self.split_at_mut(1);
Some((unsafe { 0.get_unchecked_mut(head) }, rest))
}
}
#[inline]
pub fn split_last(&self) -> Option<(&bool, &Self)> {
match self.len() {
0 => None,
len => {
let (rest, tail) = self.split_at(len - 1);
Some((unsafe { 0.get_unchecked(tail) }, rest))
},
}
}
#[inline]
pub fn split_last_mut(&mut self) -> Option<(BitMut<O, T>, &mut Self)> {
match self.len() {
0 => None,
len => {
let (rest, tail) = self.split_at_mut(len - 1);
Some((unsafe { 0.get_unchecked_mut(tail) }, rest))
},
}
}
#[inline]
pub fn last(&self) -> Option<&bool> {
match self.len() {
0 => None,
len => Some(unsafe { (len - 1).get_unchecked(self) }),
}
}
#[inline]
pub fn last_mut(&mut self) -> Option<BitMut<O, T>> {
match self.len() {
0 => None,
len => Some(unsafe { (len - 1).get_unchecked_mut(self) }),
}
}
#[inline]
pub fn get<'a, I>(&'a self, index: I) -> Option<I::Immut>
where I: BitSliceIndex<'a, O, T> {
index.get(self)
}
#[inline]
pub fn get_mut<'a, I>(&'a mut self, index: I) -> Option<I::Mut>
where I: BitSliceIndex<'a, O, T> {
index.get_mut(self)
}
#[inline]
pub unsafe fn get_unchecked<'a, I>(&'a self, index: I) -> I::Immut
where I: BitSliceIndex<'a, O, T> {
index.get_unchecked(self)
}
#[inline]
pub unsafe fn get_unchecked_mut<'a, I>(&'a mut self, index: I) -> I::Mut
where I: BitSliceIndex<'a, O, T> {
index.get_unchecked_mut(self)
}
#[inline]
pub fn as_ptr(&self) -> *const T {
self.bitptr().pointer().r()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.bitptr().pointer().w()
}
pub fn swap(&mut self, a: usize, b: usize) {
let len = self.len();
assert!(a < len, "Index {} out of bounds: {}", a, len);
assert!(b < len, "Index {} out of bounds: {}", b, len);
unsafe { self.swap_unchecked(a, b); }
}
pub fn reverse(&mut self) {
let mut cur: &mut Self = self;
loop {
let len = cur.len();
if len < 2 {
return;
}
let back = len - 1;
unsafe {
cur.swap_unchecked(0, back);
cur = cur.get_unchecked_mut(1 .. back);
}
}
}
#[inline]
pub fn iter(&self) -> Iter<O, T> {
self.into_iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<O, T> {
self.into_iter()
}
pub fn windows(&self, width: usize) -> Windows<O, T> {
assert_ne!(width, 0, "Window width cannot be zero");
super::Windows {
inner: self,
width,
}
}
pub fn chunks(&self, chunk_size: usize) -> Chunks<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
super::Chunks {
inner: self,
width: chunk_size,
}
}
pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
super::ChunksMut {
inner: self,
width: chunk_size,
}
}
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
let len = self.len();
let rem = len % chunk_size;
let mid = len - rem;
let (inner, extra) = self.split_at(mid);
super::ChunksExact {
inner,
extra,
width: chunk_size,
}
}
pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
let len = self.len();
let rem = len % chunk_size;
let mid = len - rem;
let (inner, extra) = self.split_at_mut(mid);
super::ChunksExactMut {
inner,
extra,
width: chunk_size,
}
}
pub fn rchunks(&self, chunk_size: usize) -> RChunks<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
RChunks {
inner: self,
width: chunk_size,
}
}
pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
RChunksMut {
inner: self,
width: chunk_size,
}
}
pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
let (extra, inner) = self.split_at(self.len() % chunk_size);
RChunksExact {
inner,
extra,
width: chunk_size,
}
}
pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<O, T> {
assert_ne!(chunk_size, 0, "Chunk width cannot be zero");
let (extra, inner) = self.split_at_mut(self.len() % chunk_size);
RChunksExactMut {
inner,
extra,
width: chunk_size,
}
}
pub fn split_at(&self, mid: usize) -> (&Self, &Self) {
let len = self.len();
assert!(mid <= len, "Index {} out of bounds: {}", mid, len);
unsafe { self.split_at_unchecked(mid) }
}
#[inline]
pub fn split_at_mut(&mut self, mid: usize) -> (&mut Self, &mut Self) {
let (head, tail) = self.split_at(mid);
(head.bitptr().into_bitslice_mut(), tail.bitptr().into_bitslice_mut())
}
#[inline]
pub fn split<F>(&self, func: F) -> Split<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
Split {
inner: self,
place: Some(0),
func,
}
}
#[inline]
pub fn split_mut<F>(&mut self, func: F) -> SplitMut<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
SplitMut {
inner: self,
place: Some(0),
func,
}
}
#[inline]
pub fn rsplit<F>(&self, func: F) -> RSplit<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
RSplit {
inner: self.split(func),
}
}
#[inline]
pub fn rsplit_mut<F>(&mut self, func: F) -> RSplitMut<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
RSplitMut {
inner: self.split_mut(func),
}
}
#[inline]
pub fn splitn<F>(&self, n: usize, func: F) -> SplitN<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
SplitN {
inner: GenericSplitN {
inner: self.split(func),
count: n,
}
}
}
#[inline]
pub fn splitn_mut<F>(&mut self, n: usize, func: F) -> SplitNMut<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
SplitNMut {
inner: GenericSplitN {
inner: self.split_mut(func),
count: n,
}
}
}
#[inline]
pub fn rsplitn<F>(&self, n: usize, func: F) -> RSplitN<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
RSplitN {
inner: GenericSplitN {
inner: self.rsplit(func),
count: n,
}
}
}
#[inline]
pub fn rsplitn_mut<F>(&mut self, n: usize, func: F) -> RSplitNMut<'_, O, T, F>
where F: FnMut(usize, &bool) -> bool {
RSplitNMut {
inner: GenericSplitN {
inner: self.rsplit_mut(func),
count: n,
}
}
}
pub fn contains<P, U>(&self, query: &BitSlice<P, U>) -> bool
where P: BitOrder, U: BitStore {
let len = query.len();
if len > self.len() {
return false;
}
self.windows(len).any(|s| s == query)
}
pub fn starts_with<P, U>(&self, prefix: &BitSlice<P, U>) -> bool
where P: BitOrder, U: BitStore {
let plen = prefix.len();
self.len() >= plen && prefix == unsafe { self.get_unchecked(.. plen) }
}
pub fn ends_with<P, U>(&self, suffix: &BitSlice<P, U>) -> bool
where P: BitOrder, U: BitStore, {
let slen = suffix.len();
let len = self.len();
len >= slen && suffix == unsafe { self.get_unchecked(len - slen ..) }
}
pub fn rotate_left(&mut self, mut by: usize) {
let len = self.len();
assert!(by <= len, "Slices cannot be rotated by more than their length");
if by == 0 || by == len {
return;
}
let mut tmp = 0usize;
let bits = BitSlice::<O, _>::from_element_mut(&mut tmp);
while by > 0 {
let shamt = cmp::min(usize::BITS as usize, by);
unsafe {
bits.get_unchecked_mut(.. shamt)
.clone_from_slice(self.get_unchecked(.. shamt));
for (to, from) in (shamt .. len).enumerate() {
self.copy_unchecked(from, to);
}
self.get_unchecked_mut(len - shamt ..)
.clone_from_slice(bits.get_unchecked(.. shamt));
}
by -= shamt;
}
}
pub fn rotate_right(&mut self, mut by: usize) {
let len = self.len();
assert!(by <= len, "Slices cannot be rotated by more than their length");
if by == 0 || by == len {
return;
}
let mut tmp = 0usize;
let bits = BitSlice::<O, _>::from_element_mut(&mut tmp);
while by > 0 {
let shamt = cmp::min(usize::BITS as usize, by);
unsafe {
bits.get_unchecked_mut(.. shamt)
.clone_from_slice(self.get_unchecked(len - shamt ..));
for (from, to) in (shamt .. len).enumerate().rev() {
self.copy_unchecked(from, to);
}
self.get_unchecked_mut(.. shamt)
.clone_from_slice(bits.get_unchecked(.. shamt));
}
by -= shamt;
}
}
pub fn clone_from_slice<P, U>(&mut self, src: &BitSlice<P, U>)
where P: BitOrder, U: BitStore {
assert_eq!(
self.len(),
src.len(),
"Cloning from slice requires equal lengths",
);
for idx in 0 .. self.len() {
unsafe {
self.set_unchecked(idx, *src.get_unchecked(idx));
}
}
}
pub fn copy_from_slice(&mut self, src: &Self) {
self.clone_from_slice(src)
}
pub fn swap_with_slice<P, U>(&mut self, other: &mut BitSlice<P, U>)
where P: BitOrder, U: BitStore {
assert_eq!(
self.len(),
other.len(),
"Swapping between slices requires equal lengths",
);
self.iter_mut().zip(other.iter_mut()).for_each(|(mut this, mut that)| {
let (a, b) = (*this, *that);
*this = b;
*that = a;
})
}
pub unsafe fn align_to<U>(&self) -> (&Self, &BitSlice<O, U>, &Self)
where U: BitStore {
let bitptr = self.bitptr();
let (l, c, r) = bitptr.as_slice().align_to::<U>();
let l_start = *bitptr.head() as usize;
let l = &Self::from_slice(l)[l_start ..];
let c = BitSlice::from_slice(c);
let r = &Self::from_slice(r)[.. bitptr.len() - l.len() - c.len()];
(l, c, r)
}
#[inline]
pub unsafe fn align_to_mut<U>(&mut self) -> (
&mut Self,
&mut BitSlice<O, U>,
&mut Self,
)
where U: BitStore {
let (l, c, r) = self.align_to::<U>();
(
l.bitptr().into_bitslice_mut(),
c.bitptr().into_bitslice_mut(),
r.bitptr().into_bitslice_mut(),
)
}
#[cfg(feature = "alloc")]
#[inline]
pub fn to_vec(&self) -> BitVec<O, T> {
BitVec::from_bitslice(self)
}
}
pub trait BitSliceIndex<'a, O, T>
where O: 'a + BitOrder, T: 'a + BitStore {
type Immut;
type Mut;
fn get(self, slice: &'a BitSlice<O, T>) -> Option<Self::Immut>;
fn get_mut(self, slice: &'a mut BitSlice<O, T>) -> Option<Self::Mut>;
unsafe fn get_unchecked(self, slice: &'a BitSlice<O, T>) -> Self::Immut;
unsafe fn get_unchecked_mut(
self,
slice: &'a mut BitSlice<O, T>,
) -> Self::Mut;
fn index(self, slice: &'a BitSlice<O, T>) -> Self::Immut;
fn index_mut(self, slice: &'a mut BitSlice<O, T>) -> Self::Mut;
}
impl<'a, O, T> BitSliceIndex<'a, O, T> for usize
where O: 'a + BitOrder, T: 'a + BitStore {
type Immut = &'a bool;
type Mut = BitMut<'a, O, T>;
fn get(self, slice: &'a BitSlice<O, T>) -> Option<Self::Immut> {
if self < slice.len() {
Some(unsafe { self.get_unchecked(slice) })
}
else {
None
}
}
fn get_mut(self, slice: &'a mut BitSlice<O, T>) -> Option<Self::Mut> {
if self < slice.len() {
Some(unsafe { self.get_unchecked_mut(slice) })
}
else {
None
}
}
unsafe fn get_unchecked(self, slice: &'a BitSlice<O, T>) -> Self::Immut {
let bitptr = slice.bitptr();
let (elt, bit) = bitptr.head().offset(self as isize);
let data_ptr = bitptr.pointer().a();
if (&*data_ptr.offset(elt)).get::<O>(bit) {
&true
}
else {
&false
}
}
#[inline]
unsafe fn get_unchecked_mut(
self,
slice: &'a mut BitSlice<O, T>,
) -> Self::Mut {
let bp = slice.bitptr();
let (offset, head) = bp.head().offset(self as isize);
let ptr = bp.pointer().a().offset(offset);
BitMut {
_parent: PhantomData,
data: NonNull::new_unchecked(ptr as *mut T::Access),
head,
bit: (*ptr).get::<O>(head)
}
}
fn index(self, slice: &'a BitSlice<O, T>) -> Self::Immut {
self.get(slice).unwrap_or_else(|| {
panic!("Index {} out of bounds: {}", self, slice.len())
})
}
fn index_mut(self, slice: &'a mut BitSlice<O, T>) -> Self::Mut {
let len = slice.len();
self.get_mut(slice).unwrap_or_else(|| {
panic!("Index {} out of bounds: {}", self, len)
})
}
}
macro_rules! range_impl {
( $( $r:ty => get $get:expr, unchecked $unchecked:expr; )* ) => { $(
impl<'a, O, T> BitSliceIndex<'a, O, T> for $r
where O: 'a + BitOrder, T: 'a + BitStore {
type Immut = &'a BitSlice<O, T>;
type Mut = &'a mut BitSlice<O, T>;
fn get(self, slice: Self::Immut) -> Option<Self::Immut> {
$get(self, slice)
}
#[inline]
fn get_mut(self, slice: Self::Mut) -> Option<Self::Mut> {
self.get(slice).map(|s| s.bitptr().into_bitslice_mut())
}
unsafe fn get_unchecked(self, slice: Self::Immut) -> Self::Immut {
$unchecked(self, slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: Self::Mut) -> Self::Mut {
self.get_unchecked(slice).bitptr().into_bitslice_mut()
}
#[inline]
fn index(self, slice: Self::Immut) -> Self::Immut {
let r = self.clone();
let l = slice.len();
self.clone()
.get(slice)
.unwrap_or_else(|| {
panic!("Range {:?} out of bounds: {}", r, l)
})
}
#[inline]
fn index_mut(self, slice: Self::Mut) -> Self::Mut {
self.index(slice).bitptr().into_bitslice_mut()
}
}
)* };
( $( $r:ty => map $func:expr; )* ) => { $(
impl<'a, O, T> BitSliceIndex<'a, O, T> for $r
where O: 'a + BitOrder, T: 'a + BitStore {
type Immut = &'a BitSlice<O, T>;
type Mut = &'a mut BitSlice<O, T>;
#[inline]
fn get(self, slice: Self::Immut) -> Option<Self::Immut> {
$func(self).get(slice)
}
#[inline]
fn get_mut(self, slice: Self::Mut) -> Option<Self::Mut> {
$func(self).get_mut(slice)
}
#[inline]
unsafe fn get_unchecked(self, slice: Self::Immut) -> Self::Immut {
$func(self).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: Self::Mut) -> Self::Mut {
$func(self).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: Self::Immut) -> Self::Immut {
$func(self).index(slice)
}
#[inline]
fn index_mut(self, slice: Self::Mut) -> Self::Mut {
$func(self).index_mut(slice)
}
}
)* };
}
range_impl! {
Range<usize> => get |Range { start, end }, slice: Self::Immut| {
let len = slice.len();
if start > len || end > len || start > end {
return None;
}
Some(unsafe { (start .. end).get_unchecked(slice) })
},
unchecked |Range { start, end }, slice: Self::Immut| {
let (data, head, _) = slice.bitptr().raw_parts();
let (skip, new_head) = head.offset(start as isize);
BitPtr::new_unchecked(
data.r().offset(skip),
new_head,
end - start,
).into_bitslice()
};
RangeFrom<usize> => get |RangeFrom { start }, slice: Self::Immut| {
let len = slice.len();
if start <= len {
Some(unsafe { (start ..).get_unchecked(slice) })
}
else {
None
}
},
unchecked |RangeFrom { start }, slice: Self::Immut| {
let (data, head, bits) = slice.bitptr().raw_parts();
let (skip, new_head) = head.offset(start as isize);
BitPtr::new_unchecked(
data.r().offset(skip),
new_head,
bits - start,
).into_bitslice()
};
RangeTo<usize> => get |RangeTo { end }, slice: Self::Immut| {
let len = slice.len();
if end <= len {
Some(unsafe { (.. end).get_unchecked(slice) })
}
else {
None
}
},
unchecked |RangeTo { end }, slice: Self::Immut| {
let mut bp = slice.bitptr();
bp.set_len(end);
bp.into_bitslice()
};
}
range_impl! {
RangeInclusive<usize> => map |this: Self| {
#[allow(clippy::range_plus_one)]
(*this.start() .. *this.end() + 1)
};
RangeToInclusive<usize> => map |RangeToInclusive { end }| {
#[allow(clippy::range_plus_one)]
(.. end + 1)
};
}
impl<'a, O, T> BitSliceIndex<'a, O, T> for RangeFull
where O: 'a + BitOrder, T: 'a + BitStore {
type Immut = &'a BitSlice<O, T>;
type Mut = &'a mut BitSlice<O, T>;
#[inline]
fn get(self, slice: Self::Immut) -> Option<Self::Immut> {
Some(slice)
}
#[inline]
fn get_mut(self, slice: Self::Mut) -> Option<Self::Mut> {
Some(slice)
}
#[inline]
unsafe fn get_unchecked(self, slice: Self::Immut) -> Self::Immut {
slice
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: Self::Mut) -> Self::Mut {
slice
}
#[inline]
fn index(self, slice: Self::Immut) -> Self::Immut {
slice
}
#[inline]
fn index_mut(self, slice: Self::Mut) -> Self::Mut {
slice
}
}