use core::{
cmp::{
Eq,
Ord,
Ordering,
PartialEq,
PartialOrd,
},
convert::{
AsMut,
AsRef,
From,
},
hash::{
Hash,
Hasher,
},
iter::{
DoubleEndedIterator,
ExactSizeIterator,
Iterator,
IntoIterator,
},
marker::PhantomData,
mem,
ops::{
AddAssign,
BitAndAssign,
BitOrAssign,
BitXorAssign,
Index,
Neg,
Not,
ShlAssign,
ShrAssign,
},
ptr,
slice,
};
#[cfg(feature = "alloc")]
use core::fmt::{
self,
Debug,
Display,
Formatter,
};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::borrow::ToOwned;
#[cfg(feature = "std")]
use std::borrow::ToOwned;
#[cfg_attr(nightly, repr(transparent))]
pub struct BitSlice<E = crate::BigEndian, T = u8>
where E: crate::Endian, T: crate::Bits {
_endian: PhantomData<E>,
inner: [T],
}
impl<E, T> BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
pub fn get(&self, index: usize) -> bool {
assert!(index < self.len(), "Index out of range!");
let (elt, bit) = T::split(index);
self.as_ref()[elt].get(E::curr::<T>(bit))
}
pub fn set(&mut self, index: usize, value: bool) {
assert!(index < self.len(), "Index out of range!");
let (elt, bit) = T::split(index);
self.as_mut()[elt].set(E::curr::<T>(bit), value);
}
pub fn all(&self) -> bool {
let store = self.as_ref();
for elt in &store[.. self.elts()] {
if *elt != T::from(!0) {
return false;
}
}
let bits = self.bits();
if bits > 0 {
let tail = store[self.elts()];
for bit in 0 .. bits {
if !tail.get(E::curr::<T>(bit)) {
return false;
}
}
}
true
}
pub fn any(&self) -> bool {
let store = self.as_ref();
for elt in &store[.. self.elts()] {
if *elt != T::from(0) {
return true;
}
}
let bits = self.bits();
if bits > 0 {
let tail = store[self.elts()];
for bit in 0 .. bits {
if tail.get(E::curr::<T>(bit)) {
return true;
}
}
}
false
}
pub fn not_all(&self) -> bool {
!self.all()
}
pub fn not_any(&self) -> bool {
!self.any()
}
pub fn some(&self) -> bool {
self.any() && self.not_all()
}
pub fn count_ones(&self) -> usize {
self.into_iter().filter(|b| *b).count()
}
pub fn count_zeros(&self) -> usize {
self.into_iter().filter(|b| !b).count()
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn elts(&self) -> usize {
self.len() >> T::BITS
}
pub fn bits(&self) -> u8 {
self.len() as u8 & T::MASK
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&self) -> Iter<E, T> {
self.into_iter()
}
pub fn for_each<F>(&mut self, op: F)
where F: Fn(usize, bool) -> bool {
for idx in 0 .. self.len() {
let tmp = self.get(idx);
self.set(idx, op(idx, tmp));
}
}
pub(crate) fn as_ptr(&self) -> *const T {
self.inner.as_ptr()
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
self.inner.as_mut_ptr()
}
pub(crate) fn raw_len(&self) -> usize {
self.elts() + if self.bits() > 0 { 1 } else { 0 }
}
#[cfg(feature = "alloc")]
pub(crate) fn fmt_header(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "BitSlice<{}, {}>", E::TY, T::TY)
}
#[cfg(feature = "alloc")]
pub(crate) fn fmt_body(&self, fmt: &mut Formatter, debug: bool) -> fmt::Result {
let (elts, bits) = T::split(self.len());
let len = self.raw_len();
let buf = self.as_ref();
let alt = fmt.alternate();
for (idx, elt) in buf.iter().take(elts).enumerate() {
Self::fmt_element(fmt, elt)?;
if idx < len - 1 {
match (alt, debug) {
(false, false) => fmt.write_str(" "),
(true, false) => writeln!(fmt),
(false, true) => fmt.write_str(", "),
(true, true) => { writeln!(fmt, ",")?; fmt.write_str(" ") },
}?;
}
}
if bits > 0 {
Self::fmt_bits(fmt, &buf[elts], bits)?;
}
Ok(())
}
#[cfg(feature = "alloc")]
pub(crate) fn fmt_element(fmt: &mut Formatter, elt: &T) -> fmt::Result {
Self::fmt_bits(fmt, elt, T::WIDTH)
}
#[cfg(feature = "alloc")]
pub(crate) fn fmt_bits(fmt: &mut Formatter, elt: &T, bits: u8) -> fmt::Result {
use core::fmt::Write;
#[cfg(not(feature = "std"))]
use alloc::string::String;
let mut out = String::with_capacity(bits as usize);
for bit in 0 .. bits {
let cur = E::curr::<T>(bit);
out.write_str(if elt.get(cur) { "1" } else { "0" })?;
}
fmt.write_str(&out)
}
}
#[cfg(feature = "alloc")]
impl<E, T> ToOwned for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
type Owned = crate::BitVec<E, T>;
fn to_owned(&self) -> Self::Owned {
let mut out = Self::Owned::with_capacity(self.len());
unsafe {
let src = self.as_ptr();
let dst = out.as_mut_ptr();
let len = self.raw_len();
ptr::copy_nonoverlapping(src, dst, len);
out.set_len(self.len());
}
out
}
}
impl<E, T> Eq for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {}
impl<E, T> Ord for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
fn cmp(&self, rhs: &Self) -> Ordering {
match self.partial_cmp(rhs) {
Some(ord) => ord,
None => unreachable!("`BitSlice` has a total ordering"),
}
}
}
impl<A, B, C, D> PartialEq<BitSlice<C, D>> for BitSlice<A, B>
where A: crate::Endian, B: crate::Bits, C: crate::Endian, D: crate::Bits {
fn eq(&self, rhs: &BitSlice<C, D>) -> bool {
let (l, r) = (self.iter(), rhs.iter());
if l.len() != r.len() {
return false;
}
l.zip(r).all(|(l, r)| l == r)
}
}
impl<A, B, C, D> PartialOrd<BitSlice<C, D>> for BitSlice<A, B>
where A: crate::Endian, B: crate::Bits, C: crate::Endian, D: crate::Bits {
fn partial_cmp(&self, rhs: &BitSlice<C, D>) -> Option<Ordering> {
for (l, r) in self.iter().zip(rhs.iter()) {
match (l, r) {
(true, false) => return Some(Ordering::Greater),
(false, true) => return Some(Ordering::Less),
_ => continue,
}
}
self.len().partial_cmp(&rhs.len())
}
}
impl<E, T> AsMut<[T]> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
fn as_mut(&mut self) -> &mut [T] {
let (ptr, len): (*mut T, usize) = (self.as_mut_ptr(), self.raw_len());
unsafe { slice::from_raw_parts_mut(ptr, len) }
}
}
impl<E, T> AsRef<[T]> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
fn as_ref(&self) -> &[T] {
let (ptr, len): (*const T, usize) = (self.as_ptr(), self.raw_len());
unsafe { slice::from_raw_parts(ptr, len) }
}
}
impl<'a, E, T> From<&'a [T]> for &'a BitSlice<E, T>
where E: crate::Endian, T: 'a + crate::Bits {
fn from(src: &'a [T]) -> Self {
let (ptr, len): (*const T, usize) = (src.as_ptr(), src.len());
assert!(len <= T::MAX_ELT, "Source slice length out of range!");
unsafe {
#[allow(clippy::transmute_ptr_to_ptr)]
mem::transmute(
slice::from_raw_parts(ptr, len << T::BITS)
)
}
}
}
impl<'a, E, T> From<&'a mut [T]> for &'a mut BitSlice<E, T>
where E: crate::Endian, T: 'a + crate::Bits {
fn from(src: &'a mut [T]) -> Self {
let (ptr, len): (*mut T, usize) = (src.as_mut_ptr(), src.len());
assert!(len <= T::MAX_ELT, "Source slice length out of range!");
unsafe {
#[allow(clippy::transmute_ptr_to_ptr)]
mem::transmute(
slice::from_raw_parts_mut(ptr, len << T::BITS)
)
}
}
}
#[cfg(feature = "alloc")]
impl<E, T> Debug for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
let alt = fmt.alternate();
self.fmt_header(fmt)?;
fmt.write_str(" [")?;
if alt { writeln!(fmt)?; fmt.write_str(" ")?; }
self.fmt_body(fmt, true)?;
if alt { writeln!(fmt)?; }
fmt.write_str("]")
}
}
#[cfg(feature = "alloc")]
impl<E, T> Display for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.fmt_body(fmt, false)
}
}
impl<E, T> Hash for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
fn hash<H>(&self, hasher: &mut H)
where H: Hasher {
for bit in self {
hasher.write_u8(bit as u8);
}
}
}
impl<'a, E, T> IntoIterator for &'a BitSlice<E, T>
where E: crate::Endian, T: 'a + crate::Bits {
type Item = bool;
type IntoIter = Iter<'a, E, T>;
fn into_iter(self) -> Self::IntoIter {
self.into()
}
}
impl<'a, E, T> AddAssign<&'a BitSlice<E, T>> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
#[allow(clippy::many_single_char_names)]
fn add_assign(&mut self, addend: &'a BitSlice<E, T>) {
use core::iter::repeat;
let mut addend_iter = addend.into_iter().rev().chain(repeat(false));
let mut c = false;
for place in (0 .. self.len()).rev() {
static JUMP: [u8; 8] = [0, 2, 2, 1, 2, 1, 1, 3];
let a = self.get(place);
let b = addend_iter.next().unwrap(); let idx = ((c as u8) << 2) | ((a as u8) << 1) | (b as u8);
let yz = JUMP[idx as usize];
let (y, z) = (yz & 2 != 0, yz & 1 != 0);
self.set(place, y);
c = z;
}
}
}
impl<E, T, I> BitAndAssign<I> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits, I: IntoIterator<Item=bool> {
fn bitand_assign(&mut self, rhs: I) {
use core::iter::repeat;
for (idx, other) in (0 .. self.len()).zip(rhs.into_iter().chain(repeat(false))) {
let val = self.get(idx) & other;
self.set(idx, val);
}
}
}
impl<E, T, I> BitOrAssign<I> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits, I: IntoIterator<Item=bool> {
fn bitor_assign(&mut self, rhs: I) {
for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) {
let val = self.get(idx) | other;
self.set(idx, val);
}
}
}
impl<E, T, I> BitXorAssign<I> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits, I: IntoIterator<Item=bool> {
fn bitxor_assign(&mut self, rhs: I) {
use core::iter::repeat;
for (idx, other) in (0 .. self.len()).zip(rhs.into_iter().chain(repeat(false))) {
let val = self.get(idx) ^ other;
self.set(idx, val);
}
}
}
impl<'a, E, T> Index<usize> for &'a BitSlice<E, T>
where E: crate::Endian, T: 'a + crate::Bits {
type Output = bool;
fn index(&self, index: usize) -> &Self::Output {
if self.get(index) { &true} else { &false }
}
}
impl<'a, E, T> Index<(usize, u8)> for &'a BitSlice<E, T>
where E: crate::Endian, T: 'a + crate::Bits {
type Output = bool;
fn index(&self, (elt, bit): (usize, u8)) -> &Self::Output {
if self.get(T::join(elt, bit)) { &true } else { &false }
}
}
impl<'a, E, T> Neg for &'a mut BitSlice<E, T>
where E: crate::Endian, T: 'a + crate::Bits {
type Output = Self;
fn neg(self) -> Self::Output {
if self.is_empty() || self.not_any() {
return self;
}
let _ = Not::not(&mut *self);
let elt: [T; 1] = [!T::default()];
if self.any() {
let addend: &BitSlice<E, T> = {
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe { mem::transmute::<&[T], &BitSlice<E, T>>(&elt) }
};
AddAssign::add_assign(&mut *self, addend);
}
self
}
}
impl<'a, E, T> Not for &'a mut BitSlice<E, T>
where E: crate::Endian, T: 'a + crate::Bits {
type Output = Self;
fn not(self) -> Self::Output {
for elt in self.as_mut() {
*elt = !*elt;
}
self
}
}
__bitslice_shift!(u8, u16, u32, u64, i8, i16, i32, i64);
impl<E, T> ShlAssign<usize> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
#[allow(clippy::suspicious_op_assign_impl)]
fn shl_assign(&mut self, shamt: usize) {
let len = self.len();
let shamt = shamt % len;
if shamt == 0 {
return;
}
if shamt & T::MASK as usize == 0 {
let offset = shamt >> T::BITS;
let rem = self.raw_len() - offset;
let head: *mut T = self.as_mut_ptr();
let body: *const T = &self.as_ref()[offset];
let tail: *mut T = &mut self.as_mut()[rem];
unsafe {
ptr::copy(body, head, rem);
ptr::write_bytes(tail, 0, offset);
}
return;
}
for (to, from) in (shamt .. len).enumerate() {
let val = self.get(from);
self.set(to, val);
}
for bit in (len - shamt) .. len {
self.set(bit, false);
}
}
}
impl<E, T> ShrAssign<usize> for BitSlice<E, T>
where E: crate::Endian, T: crate::Bits {
#[allow(clippy::suspicious_op_assign_impl)]
fn shr_assign(&mut self, shamt: usize) {
let len = self.len();
let shamt = shamt % len;
if shamt == 0 {
return;
}
if shamt & T::MASK as usize == 0 {
let offset = shamt >> T::BITS;
let rem = self.raw_len() - offset;
let head: *mut T = self.as_mut_ptr();
let body: *mut T = &mut self.as_mut()[offset];
unsafe {
ptr::copy(head, body, rem);
ptr::write_bytes(head, 0, offset);
}
return;
}
for (from, to) in (shamt .. len).enumerate().rev() {
let val = self.get(from);
self.set(to, val);
}
for bit in 0 .. shamt {
self.set(bit, false);
}
}
}
#[doc(hidden)]
pub struct Iter<'a, E, T>
where E: 'a + crate::Endian, T: 'a + crate::Bits {
inner: &'a BitSlice<E, T>,
head: usize,
tail: usize,
}
impl<'a, E, T> Iter<'a, E, T>
where E: 'a + crate::Endian, T: 'a + crate::Bits {
fn reset(&mut self) {
self.head = 0;
self.tail = self.inner.len();
}
}
impl<'a, E, T> DoubleEndedIterator for Iter<'a, E, T>
where E: 'a + crate::Endian, T: 'a + crate::Bits {
fn next_back(&mut self) -> Option<Self::Item> {
if self.tail > self.head {
self.tail -= 1;
Some(self.inner.get(self.tail))
}
else {
self.reset();
None
}
}
}
impl<'a, E, T> ExactSizeIterator for Iter<'a, E, T>
where E: 'a + crate::Endian, T: 'a + crate::Bits {
fn len(&self) -> usize {
self.tail - self.head
}
}
impl<'a, E, T> From<&'a BitSlice<E, T>> for Iter<'a, E, T>
where E: 'a + crate::Endian, T: 'a + crate::Bits {
fn from(src: &'a BitSlice<E, T>) -> Self {
let len = src.len();
Self {
inner: src,
head: 0,
tail: len,
}
}
}
impl<'a, E, T> Iterator for Iter<'a, E, T>
where E: 'a + crate::Endian, T: 'a + crate::Bits {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if self.head < self.tail {
let ret = self.inner.get(self.head);
self.head += 1;
Some(ret)
}
else {
self.reset();
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let rem = ExactSizeIterator::len(self);
(rem, Some(rem))
}
fn count(self) -> usize {
ExactSizeIterator::len(&self)
}
fn nth(&mut self, n: usize) -> Option<bool> {
self.head = self.head.saturating_add(n);
self.next()
}
fn last(mut self) -> Option<bool> {
self.next_back()
}
}