mod scheme;
mod conversion;
mod operators;
mod iteration;
mod bytes;
pub use scheme::*;
pub use conversion::*;
pub use iteration::*;
use std::ptr::NonNull;
use std::{alloc, ptr};
use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt::{Binary, Debug, Display, Formatter};
use std::ops::{Bound, Deref, Div, RangeBounds};
use bytes::RawBytes;
#[macro_export]
macro_rules! bits {
() => { Bits::empty() };
(0; $n:expr) => { Bits::zeros($n) };
(1; $n:expr) => { Bits::ones($n) };
(8; $byte:expr; $n:expr) => { Bits::new(vec![$byte; $n]) };
($($byte:expr),+ $(,)?) => {{ Bits::new(vec![$($byte),+]) }};
($($byte:expr),+; => $n:expr) => { Bits::aligned($n, vec![$($byte),+]) };
($($byte:expr),+; %) => { Bits::packed(vec![$($byte),+]) };
}
macro_rules! bitop {
($self:expr, $op:tt, $rhs:expr) => {
unsafe {
let (mut min, mut nbytes, mut nbits) = ($self.size(), $rhs.size(), $rhs.nbits);
let (mut padding, mut mask) = ($rhs.padding, $rhs.mask);
let aptr = $self.words.as_ptr_const();
let bptr = $rhs.words.as_ptr_const();
if $rhs.nbits < $self.nbits {
(min, nbytes, nbits) = ($rhs.size(), $self.size(), $self.nbits);
(padding, mask) = ($self.padding, $self.mask);
}
let layout = Layout::array::<u8>(nbytes).unwrap();
let result = alloc::alloc(layout);
for i in 0..min { ptr::write(result.add(i), *aptr.add(i) $op *bptr.add(i)); }
match $self.size().cmp(&$rhs.size()) {
Ordering::Greater => for i in $rhs.size()..$self.size() {
ptr::write(result.add(i), *aptr.add(i))
},
Ordering::Less => for i in $self.size()..$rhs.size() {
ptr::write(result.add(i), *bptr.add(i));
},
_ => ()
}
*result.add(nbytes - 1) &= mask;
let bytes = RawBytes { bytes: NonNull::new(result).unwrap(), cap: nbytes, nbytes };
Bits { words:bytes, mask, nbits, padding }
}
};
(assign; $self:expr, $op:tt, $rhs:expr) => {
unsafe {
let aptr = $self.words.as_ptr_mut();
let bptr = $rhs.words.as_ptr_const();
let (lsize, rsize) = ($self.size(), $rhs.size());
let min = if rsize < lsize { rsize } else { lsize };
for i in 0..min { *aptr.add(i) $op *bptr.add(i); }
if $self.nbits < $rhs.nbits {
let aptr = $self.words.as_ptr_mut();
$self.words.expand_to(rsize);
for i in lsize..rsize { ptr::write(aptr.add(i), *bptr.add(i)); }
$self.mask = $rhs.mask;
$self.nbits = $rhs.nbits;
$self.words.nbytes = rsize;
$self.padding = $rhs.padding;
if lsize > 0 { *aptr.add(lsize - 1) &= $self.mask; }
}
}
};
}
macro_rules! divrem8 {
($n:expr) => { ($n >> 3, $n & 7) };
(ceil; $n:expr) => { (1 + (($n - 1) >> 3), $n & 7) };
}
macro_rules! mask {
($shift:expr) => { if $shift == 0 { 0xFF } else { ((1 << $shift) - 1) as u8 } };
}
macro_rules! pointer {
($size:expr) => {{
let layout = Layout::array::<u8>($size).unwrap();
assert!(layout.size() <= isize::MAX as usize, "Allocation too large");
let pointer = alloc::alloc(layout);
pointer
}};
($fill:expr; $size:expr) => {{
let layout = Layout::array::<u8>($size).unwrap();
assert!(layout.size() <= isize::MAX as usize, "Allocation too large");
let pointer = alloc::alloc(layout);
for i in 0..$size { ptr::write(pointer.add(i), $fill); }
pointer
}};
}
macro_rules! single_bit_pointer {
($bit:literal) => {{
let layout = Layout::array::<u8>(1).unwrap();
let pointer = alloc::alloc(layout);
ptr::write(pointer, $bit);
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap: 1, nbytes: 1 };
Bits { words: bytes, mask: 1, nbits: 1, padding: 7 }
}};
}
pub(crate) fn get_bits(src: &[u8], start: usize, length: usize) -> Vec<u8> {
let nbytes_src = src.len();
let (start_byte, start_idx) = divrem8!(start);
let (nbytes, overflow) = divrem8!(ceil; length);
let mut bytes = vec![0; nbytes];
let take_all = nbytes >= (nbytes_src - start_byte);
if start_idx > 0 {
let shift_mask = (1 << start_idx) - 1;
let upper_length = 8 - start_idx;
let end_byte = if take_all { nbytes_src - 1 } else { start_byte + nbytes };
for i in start_byte..end_byte {
bytes[i - start_byte] = src[i] >> start_idx;
bytes[i - start_byte] |= (src[i + 1] & shift_mask) << upper_length;
}
if take_all { bytes[nbytes_src - start_byte - 1] = src[nbytes_src - 1] >> start_idx; }
} else {
let end_byte = if take_all { nbytes_src } else { start_byte + nbytes };
for i in start_byte..end_byte { bytes[i - start_byte] = src[i] }
}
bytes[nbytes - 1] &= mask!(overflow);
bytes
}
fn trim(mut bytes: Vec<u8>) -> Vec<u8> {
let (mut upper_bound, mut i) = (bytes.len().saturating_sub(1), 0);
while i < upper_bound {
if bytes[i] == 0 {
bytes.remove(i);
upper_bound -= 1;
} else {
let clz = bytes[i].leading_zeros() as usize;
if clz > 0 {
let (mask, low) = ((1 << clz) - 1, 8 - clz);
bytes[i] |= (bytes[i + 1] & mask) << low;
bytes[i + 1] >>= clz;
if bytes[i + 1] == 0 {
bytes.remove(i + 1);
upper_bound -= 1;
if bytes[i].leading_zeros() == 0 { i += 1; }
} else {
i += 1;
}
} else {
i += 1;
}
}
}
bytes
}
pub struct Bits {
words: RawBytes,
mask: u8,
nbits: usize,
padding: usize,
}
impl Bits {
pub fn new<I: IntoIterator<Item = u8>>(bits: I) -> Self {
let mut bytes = bits.into_iter().collect::<Vec<u8>>();
match bytes.len() {
0 => Bits::empty(),
nbytes => {
bytes.shrink_to(nbytes);
let cap = bytes.capacity();
let pointer = bytes.as_mut_ptr();
std::mem::forget(bytes);
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap, nbytes };
Bits { words: bytes, mask: 0xFF, nbits: nbytes << 3, padding: 0 }
}
}
}
pub fn aligned<I: IntoIterator<Item = u8>>(units: usize, bits: I) -> Self {
match units {
0 => Bits::empty(),
1 => Bits::from_iter(bits),
8 => Bits::new(bits),
units => {
let mut bytes = bits.into_iter().collect::<Vec<u8>>();
let mut nbits = bytes.len() << 3;
let overflow = nbits % units;
if overflow > 0 {
nbits += units - overflow;
for _ in 0..(1 + ((units - 1) >> 3)) { bytes.push(0); }
}
let nbytes = bytes.len();
if nbytes == 0 {
Bits::empty()
} else {
bytes.shrink_to(nbytes);
let cap = bytes.capacity();
let pointer = bytes.as_mut_ptr();
std::mem::forget(bytes);
let overflow = nbits & 7;
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap, nbytes };
Bits { words: bytes, mask: mask!(overflow), nbits, padding: (8 - overflow) & 7 }
}
}
}
}
pub fn empty() -> Self {
let bytes = RawBytes { bytes: NonNull::dangling(), cap: 0, nbytes: 0 };
Bits { words: bytes, mask: 0xFF, nbits: 0, padding: 0 }
}
pub fn one() -> Self { unsafe { single_bit_pointer!(1) } }
pub fn ones(length: usize) -> Self {
match length {
0 => Bits::empty(),
length => {
let nbytes = 1 + ((length - 1) >> 3);
let overflow = length & 7;
let padding = (8 - overflow) & 7;
let mask = mask!(overflow);
unsafe {
let pointer = pointer![0xFFu8; nbytes];
*pointer.add(nbytes - 1) &= mask;
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap: nbytes, nbytes };
Bits { words: bytes, mask, nbits: length, padding }
}
}
}
}
pub fn packed<I: IntoIterator<Item = u8>>(bytes: I) -> Self {
Bits::from(trim(bytes.into_iter().collect::<Vec<u8>>()))
}
pub fn slice(src: &[u8], length: usize) -> Self { Bits::take(src, 0, length) }
pub fn take(src: &[u8], start: usize, length: usize) -> Self {
if length == 0 { return Bits::empty(); }
let nbytes_src = src.len();
if nbytes_src == 0 || start >= (nbytes_src << 3) {
return Bits::zeros(length);
}
let (nbytes, overflow) = divrem8!(ceil; length);
let mut bytes = get_bits(src, start, length);
let pointer = bytes.as_mut_ptr();
std::mem::forget(bytes);
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap: nbytes, nbytes };
Bits { words: bytes, mask: mask!(overflow), nbits: length, padding: (8 - overflow) & 7 }
}
pub fn zero() -> Self { unsafe { single_bit_pointer!(0) } }
pub fn zeros(length: usize) -> Self {
match length {
0 => Bits::empty(),
length => unsafe {
let nbytes = 1 + ((length - 1) >> 3);
let overflow = length & 7;
let padding = (8 - overflow) & 7;
let mask = mask!(overflow);
let pointer = pointer![0u8; nbytes];
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap: nbytes, nbytes };
Bits { words: bytes, mask, nbits: length, padding }
}
}
}
pub fn align(&mut self, unit: usize) {
match unit {
0 | 1 => (),
8 => {
self.nbits = self.size() << 3;
self.padding = 0;
},
unit if (self.nbits % unit) == 0 => (),
unit => self.push_zeros(unit - (self.nbits % unit))
}
}
pub fn all(&self) -> bool {
match self.size() {
0 => true,
n => unsafe {
let pointer = self.words.as_ptr_const();
for i in 0..(n - 1) {
if *pointer.add(i) != 0xFF { return false; }
}
(*pointer.add(n - 1) & self.mask) == self.mask
}
}
}
pub fn and(&self, rhs: &Bits) -> Bits {
unsafe {
let (mut min, mut nbytes) = (self.size(), rhs.size());
let mut nbits = rhs.nbits;
let (mut padding, mut mask) = (rhs.padding, rhs.mask);
let aptr = self.words.as_ptr_const();
let bptr = rhs.words.as_ptr_const();
if rhs.nbits < self.nbits {
(min, nbytes, nbits) = (rhs.size(), self.size(), self.nbits);
(padding, mask) = (self.padding, self.mask);
}
let layout = Layout::array::<u8>(nbytes).unwrap();
let result = alloc::alloc(layout);
for i in 0..min {
ptr::write(result.add(i), *aptr.add(i) & *bptr.add(i));
}
for i in min..nbytes { ptr::write(result.add(i), 0); }
*result.add(nbytes - 1) &= mask;
let bytes = RawBytes { bytes: NonNull::new(result).unwrap(), cap: nbytes, nbytes };
Bits { words: bytes, mask, nbits, padding }
}
}
pub fn and_mut(&mut self, rhs: &Bits) {
match self.size().cmp(&rhs.size()) {
Ordering::Equal => unsafe {
let aptr = self.words.as_ptr_mut();
let bptr = self.words.as_ptr_const();
let last_a = *aptr.add(self.size() - 1) & self.mask;
let last_b = *bptr.add(rhs.size() - 1) & rhs.mask;
for i in 0..(self.size() - 1) { *aptr.add(i) &= *bptr.add(i); }
*aptr.add(self.size() - 1) = last_a & last_b;
},
Ordering::Less => unsafe {
self.words.expand_to(rhs.size());
let aptr = self.words.as_ptr_mut();
let bptr = self.words.as_ptr_const();
let last_a = *aptr.add(self.size() - 1) & self.mask;
for i in 0..(self.size() - 1) { *aptr.add(i) &= *bptr.add(i); }
*aptr.add(self.size() - 1) = last_a & *bptr.add(self.size() - 1);
for i in self.size()..rhs.size() { ptr::write(aptr.add(i), 0); }
},
Ordering::Greater => unsafe {
let aptr = self.words.as_ptr_mut();
let bptr = self.words.as_ptr_const();
for i in 0..(rhs.size() - 1) { *aptr.add(i) &= *bptr.add(i); }
*aptr.add(rhs.size() - 1) &= *bptr.add(rhs.size() - 1) & rhs.mask;
for i in rhs.size()..self.size() { *aptr.add(i) = 0; }
}
}
if self.nbits < rhs.nbits {
self.nbits = rhs.nbits;
self.words.nbytes = rhs.size();
self.padding = rhs.padding;
self.mask = rhs.mask;
}
}
pub fn any(&self) -> bool { self.nbits > 0 && self.bytes().iter().any(|&b| b > 0u8) }
pub fn byte(&self, i: usize) -> u8 {
assert!(i < self.size(), "Index out of bounds");
unsafe { *self.words.as_ptr_const().add(i) }
}
pub fn bytes(&self) -> &[u8] { self.words.deref() }
pub fn complement(&self) -> Bits {
match self.size() {
0 => Bits::empty(),
nbytes => unsafe {
let pointer = self.words.as_ptr_mut();
let layout = Layout::array::<u8>(nbytes).unwrap();
let clone = alloc::alloc(layout);
for i in 0..nbytes { ptr::write(clone.add(i), !*pointer.add(i)); }
*clone.add(nbytes - 1) &= self.mask;
let bytes = RawBytes { bytes: NonNull::new(clone).unwrap(), cap: nbytes, nbytes };
Bits { words: bytes, mask: self.mask, nbits: self.nbits, padding: self.padding }
}
}
}
pub fn complement_mut(&mut self) {
unsafe {
let aptr = self.words.as_ptr_mut();
for i in 0..self.size() { *aptr.add(i) = !*aptr.add(i); }
*aptr.add(self.size() - 1) &= self.mask;
}
}
pub fn consume_left(&mut self, count: usize) {
match (self.size(), count) {
(0, _) | (_, 0) => (),
(n, count) if count >= self.nbits => unsafe {
let pointer = self.words.as_ptr_mut();
for i in 0..n { *pointer.add(i) = 0; }
},
(n, count) => {
let (extra, byte_len) = (count & 7, count >> 3);
if byte_len > 0 {
unsafe {
let pointer = self.words.as_ptr_mut();
for i in (n - byte_len)..n { ptr::read(pointer.add(i)); }
self.words.nbytes -= byte_len;
*pointer.add(self.size() - 1) &= self.mask;
}
}
if extra > 0 {
unsafe {
let overflow = 8 - self.padding;
let pointer = self.words.as_ptr_mut();
let mask = match extra.cmp(&overflow) {
Ordering::Less => (1 << (overflow - extra)) - 1,
Ordering::Greater => (1 << (8 + overflow - extra)) - 1,
Ordering::Equal => 0,
};
*pointer.add(self.size() - 1) &= mask;
}
}
self.nbits -= count;
let overflow = self.nbits & 7;
self.padding = (8 - overflow) & 7;
self.mask = mask!(overflow);
self.shrink_to_fit();
unsafe { *self.words.as_ptr_mut().add(self.size() - 1) &= self.mask; }
}
}
}
pub fn consume_right(&mut self, count: usize) {
match (self.size(), count) {
(0, _) | (_, 0) => (),
(_, count) if count >= self.nbits => {
self.words.shrink_to(0);
self.nbits = 0;
self.padding = 0;
},
(_, count) => {
unsafe {
let shift_bytes = count >> 3;
let pointer = self.words.as_ptr_mut();
ptr::copy(pointer.add(shift_bytes), pointer, self.size() - shift_bytes);
self.words.shrink_to(self.size() - shift_bytes);
self.words.nbytes -= shift_bytes;
self.nbits -= count;
let new_overflow = self.nbits & 7;
self.padding = 8 - new_overflow;
self.mask = mask!(new_overflow);
let count_overflow = count & 7;
if count_overflow > 0 {
self.words.shift_right(
self.size(),
(1 << count_overflow) - 1,
8 - count_overflow,
count_overflow
);
self.shrink_to_fit();
}
}
}
}
}
pub fn count_zeros(&self) -> usize {
match self.size() {
0 => 0,
n => unsafe {
let pointer = self.words.as_ptr_const();
let mut sum = (*pointer.add(n - 1) & self.mask).count_zeros();
for i in 0..(n - 1) { sum += (*pointer.add(i)).count_zeros(); }
(sum as usize) - self.padding
}
}
}
pub fn copy_range<R: RangeBounds<usize>>(&self, bounds: R) -> Self {
if let Bound::Excluded(&usize::MAX) = bounds.start_bound() {
return Bits::empty();
} else if let Bound::Excluded(&0) = bounds.end_bound() {
return Bits::empty();
}
let start = match bounds.start_bound() {
Bound::Included(n) if *n < self.nbits => *n,
Bound::Unbounded => 0,
Bound::Excluded(n) if *n < self.nbits => *n + 1,
_ => self.nbits,
};
let end = match bounds.end_bound() {
Bound::Excluded(n) if *n < self.nbits => *n,
Bound::Included(n) if *n < self.nbits => *n + 1,
_ => self.nbits,
};
if start >= end {
Bits::empty()
} else {
Bits::take(self.bytes(), start, end - start)
}
}
pub fn extend_left(&mut self, bytes: &[u8]) {
let mut nbytes = bytes.len();
while nbytes > 0 && bytes[nbytes - 1] == 0 { nbytes -= 1; }
if nbytes == 0 { return; }
unsafe {
self.words.expand_to(self.size() + nbytes);
let pointer = self.words.as_ptr_mut().add(self.size());
for i in 0..nbytes { ptr::write(pointer.add(i), bytes[i]); }
if self.padding > 0 {
let overflow = (8 - self.padding) & 7;
let mask = mask!(self.padding);
let end = self.size() + nbytes;
self.words.shift_right_from(self.size(), end, mask, overflow, self.padding);
}
self.words.nbytes += nbytes;
self.nbits += nbytes << 3;
*pointer.add(self.size() - 1) &= self.mask;
}
}
pub fn extend_right(&mut self, bytes: &[u8]) {
unsafe {
let nbytes_padding = bytes.len();
let nbytes = self.size() + nbytes_padding;
self.words.expand_to(nbytes);
let pointer = self.words.as_ptr_mut();
ptr::copy(pointer, pointer.add(nbytes_padding), self.size());
for i in 0..nbytes_padding { ptr::write(pointer.add(i), bytes[i]); }
self.words.nbytes = nbytes;
self.nbits += nbytes_padding << 3;
*pointer.add(self.size() - 1) &= self.mask;
}
}
pub fn hamming_weight(&self) -> usize {
match self.size() {
0 => 0,
n => unsafe {
let pointer = self.words.as_ptr_const();
let mut sum = (*pointer.add(n - 1) & self.mask).count_ones();
for i in 0..(n - 1) { sum += (*pointer.add(i)).count_ones(); }
sum as usize
}
}
}
pub fn i(&self, i: usize) -> u8 {
assert!(i < self.nbits, "Index out of bounds");
unsafe { (*self.words.as_ptr_mut().add(i >> 3) >> (i & 7)) & 1 }
}
pub fn into_bytes(self) -> IntoBytes {
let (iter, bytes) = unsafe {
(Bytes::new(self.bytes()), ptr::read(&self.words))
};
std::mem::forget(self);
IntoBytes::new(iter, bytes)
}
pub fn iter(&'_ self) -> Iter<'_> { Iter::new(self, 0) }
pub fn iter_from(&'_ self, index: usize) -> Iter<'_> {
assert!(index <= self.nbits, "Index out of bounds");
Iter::new(self, index)
}
pub fn leading_ones(&self) -> usize {
match self.size() {
0 => 0,
n => unsafe {
let pointer = self.words.as_ptr_const();
let last_byte = *pointer.add(n - 1) & self.mask;
let ones = (last_byte << self.padding).leading_ones() as usize;
if ones < (8 - self.padding) { return ones; }
let mut i = n - 2;
while i > 0 && *pointer.add(i) == 0xFF { i -= 1; }
ones + ((self.size() - i - 2) << 3) + ((*pointer.add(i)).leading_ones() as usize)
}
}
}
pub fn leading_zeros(&self) -> usize {
match self.size() {
0 => 0,
1 => unsafe {
let byte = *self.words.as_ptr_const() & self.mask;
(byte.leading_zeros() as usize) - self.padding
},
n => unsafe {
let pointer = self.words.as_ptr_const();
let last_byte = *pointer.add(n - 1) & self.mask;
let zeros = (last_byte.leading_zeros() as usize) - self.padding;
if (zeros + self.padding) < 8 { return zeros; }
let mut i = n - 2;
while i > 0 && *pointer.add(i) == 0 { i -= 1; }
zeros + ((n - i - 2) << 3) + ((*pointer.add(i)).leading_zeros() as usize)
}
}
}
pub fn len(&self) -> usize { self.nbits }
pub fn none(&self) -> bool {
unsafe {
let pointer = self.words.as_ptr_const();
for i in 0..(self.size() - 1) {
if *pointer.add(i) != 0 { return false; }
}
(*pointer.add(self.size() - 1) & self.mask) == 0
}
}
pub fn or(&self, rhs: &Bits) -> Bits { bitop!(self, |, rhs) }
pub fn or_mut(&mut self, rhs: &Bits) { bitop!(assign; self, |=, rhs) }
pub fn pop_left(&mut self) -> u8 {
match self.size() {
0 => 0,
n => unsafe {
let pointer = self.words.as_ptr_mut();
self.nbits -= 1;
match self.padding {
0 => {
let bit = *pointer.add(n - 1) >> 7;
*pointer.add(n - 1) &= 0x7F;
bit
},
7 => {
let bit = ptr::read(pointer.add(n - 1)) & 1;
self.words.nbytes -= 1;
self.padding = 0;
bit
},
alignment => {
let shift = 8 - alignment - 1;
let bit = *pointer.add(n- 1) >> shift;
*pointer.add(n - 1) &= mask!(shift);
self.padding += 1;
bit
}
}
}
}
}
pub fn pop_right(&mut self) -> u8 {
match self.size() {
0 => 0,
_ => {
self.nbits -= 1;
self.padding = (self.padding + 1) & 7;
unsafe {
let pointer = self.words.as_ptr_mut();
let bit = *pointer & 1;
self.words.shift_right(self.size(), 1, 7, 1);
if self.nbits == 0 {
ptr::read(pointer);
self.words.nbytes = 0;
}
bit
}
}
}
}
pub fn push_left(&mut self, bit: bool, count: usize) {
if bit { self.push_ones(count); } else { self.push_zeros(count); }
}
pub fn push_byte_left(&mut self, word: u8, count: usize) {
if count == 0 { return; }
match word {
0 => self.push_zeros(count << 3),
0xFF => self.push_ones(count << 3),
word => unsafe {
self.words.expand_to(self.size() + count);
let pointer = self.words.as_ptr_mut().add(self.size());
for i in 0..count { ptr::write(pointer.add(i), word); }
*pointer.add(self.size() - 1) &= self.mask;
if self.padding > 0 && word != 0 {
self.words.shift_right_from(
self.size(),
self.size() + count,
mask!(self.padding),
(8 - self.padding) & 7,
self.padding
);
}
self.words.nbytes += count;
self.nbits += count << 3;
self.shrink_to_fit()
}
}
}
pub fn push_right(&mut self, bit: bool, count: usize) {
match count {
0 => (),
n => if bit { self.cons_bit(n, 0xFF); } else { self.cons_bit(n, 0) }
}
}
pub fn push_byte_right(&mut self, word: u8, count: usize) {
let nbytes = self.size() + count;
self.words.expand_to(nbytes);
unsafe {
let pointer = self.words.as_ptr_mut();
ptr::copy(pointer, pointer.add(count), self.size());
for i in 0..count { ptr::write(pointer.add(i), word); }
}
self.words.nbytes = nbytes;
self.nbits += count << 3;
}
pub fn reset(&mut self, i: usize) {
if i < self.nbits {
unsafe { *self.words.as_ptr_mut().add(i >> 3) &= !(1 << (i & 7)); }
}
}
pub fn reset_bits(&mut self, start: usize, count: usize) {
assert!(count <= self.nbits && start <= self.nbits - count, "Invalid range");
let end = if count > (self.nbits - start) { self.nbits } else { start + count };
let mut start = start;
let low_overflow = 8 - (start & 7);
unsafe {
let pointer = self.words.as_ptr_mut();
if low_overflow < 8 {
*pointer.add(start >> 3) &= !(((1 << low_overflow) - 1) << (start & 7));
start = start + low_overflow;
}
let bytes = (end - start) >> 3;
let start_byte = start >> 3;
for i in start_byte..(start_byte + bytes) { *pointer.add(i) = 0 }
let overflow = (end - start) & 7;
if overflow > 0 { *pointer.add(start_byte + bytes) &= !((1 << overflow) - 1); }
if self.size() > 0 { *pointer.add(self.words.nbytes - 1) &= self.mask; }
}
}
pub fn reset_byte(&mut self, i: usize) {
assert!(i < self.size(), "Index out of range");
unsafe {
let pointer = self.words.as_ptr_mut();
*pointer.add(i) = 0;
if self.size() > 0 { *pointer.add(self.words.nbytes - 1) &= self.mask; }
}
}
pub fn reset_bytes(&mut self, start: usize, count: usize) {
assert!(count <= self.size() && start <= self.size() - count, "Invalid range");
unsafe {
let pointer = self.words.as_ptr_mut();
let end = if count > (self.size() - start) { self.size() } else { start + count };
for i in start..end { *pointer.add(i) = 0; }
if end == self.size() && self.padding > 0 { *pointer.add(end - 1) &= self.mask; }
}
}
pub fn reverse(&mut self) {
match self.size() {
0 => (),
n => unsafe {
let aptr = self.words.as_ptr_mut();
*aptr.add(n - 1) &= self.mask;
let mid = n >> 1;
let upper_bound = n - 1;
for i in 0..mid {
let a = (*aptr.add(i)).reverse_bits();
*aptr.add(i) = (*aptr.add(upper_bound - i)).reverse_bits();
*aptr.add(upper_bound - i) = a;
}
if (n & 1) == 1 { *aptr.add(mid) = (*aptr.add(mid)).reverse_bits() }
if self.padding > 0 {
let overflow = 8 - self.padding;
let mask = (1 << overflow) - 1;
self.words.shift_right(self.size(), mask, self.padding, overflow);
}
}
}
}
pub fn reversed(&self) -> Self {
let mut cloned = self.clone();
cloned.reverse();
cloned
}
pub fn rotate_left(&mut self, count: usize) {
match (self.size(), count) {
(0, _) | (_, 0) => (),
(n, count) => {
unsafe { *self.words.as_ptr_mut().add(n - 1) &= self.mask; }
let reduced_count = count % self.nbits;
let other = self.shifted_right(self.nbits - reduced_count);
self.shift_left(reduced_count);
self.or_mut(&other);
}
}
}
pub fn rotated_left(&self, count: usize) -> Self {
match (self.size(), count) {
(0, _) | (_, 0) => self.clone(),
(n, count) => {
unsafe { *self.words.as_ptr_mut().add(n - 1) &= self.mask; }
let reduced_count = count % self.nbits;
let mut other = self.shifted_left(reduced_count);
other |= self.shifted_right(self.nbits - reduced_count);
other
}
}
}
pub fn rotate_right(&mut self, count: usize) {
match (self.size(), count) {
(0, _) | (_, 0) => (),
(n, count) => {
unsafe { *self.words.as_ptr_mut().add(n - 1) &= self.mask; }
let reduced_count = count % self.nbits;
let other = self.shifted_left(self.nbits - reduced_count);
self.shift_right(reduced_count);
self.or_mut(&other);
}
}
}
pub fn rotated_right(&self, count: usize) -> Self {
match (self.size(), count) {
(0, _) | (_, 0) => self.clone(),
(n, count) => {
unsafe { *self.words.as_ptr_mut().add(n - 1) &= self.mask; }
let reduced_count = count % self.nbits;
let mut other = self.shifted_right(reduced_count);
other |= self.shifted_left(self.nbits - reduced_count);
other
}
}
}
pub fn set(&mut self, i: usize) {
assert!(i < self.nbits, "Index out of range");
unsafe { *self.words.as_ptr_mut().add(i >> 3) |= 1 << (i & 7); }
}
pub fn set_bits(&mut self, start: usize, count: usize) {
assert!(count <= self.nbits && start <= self.nbits - count, "Invalid range");
let end = if count > (self.nbits - start) { self.nbits } else { start + count };
let mut start = start;
let low_overflow = 8 - (start & 7);
unsafe {
let pointer = self.words.as_ptr_mut();
if low_overflow < 8 {
*pointer.add(start >> 3) |= ((1 << low_overflow) - 1) << (start & 7);
start = start + low_overflow;
}
let bytes = (end - start) >> 3;
let start_byte = start >> 3;
for i in start_byte..(start_byte + bytes) { *pointer.add(i) = 0xFF }
let overflow = (end - start) & 7;
if overflow > 0 { *pointer.add(start_byte + bytes) |= (1 << overflow) - 1; }
}
}
pub fn set_byte(&mut self, i: usize) {
assert!(i < self.size(), "Index out of range");
unsafe {
let pointer = self.words.as_ptr_mut();
*pointer.add(i) = 0xFF;
*pointer.add(self.size() - 1) &= self.mask;
}
}
pub fn set_bytes(&mut self, start: usize, count: usize) {
assert!(count <= self.size() && start <= self.size() - count, "Invalid range");
unsafe {
let pointer = self.words.as_ptr_mut();
let end = if count > (self.size() - start) { self.size() } else { start + count };
for i in start..end { *pointer.add(i) = 0xFF; }
if end == self.size() && self.padding > 0 { *pointer.add(end - 1) &= self.mask; }
}
}
pub fn shift_left(&mut self, count: usize) {
self.shift_bytes_left_with(count, 0);
}
pub fn shift_left_with(&mut self, count: usize, bit: bool) {
self.shift_bytes_left_with(count, if bit { 0xFF } else { 0 });
}
pub fn shifted_left(&self, count: usize) -> Self {
let mut clone = self.clone();
clone.shift_bytes_left_with(count, 0);
clone
}
pub fn shift_right(&mut self, count: usize) {
self.shift_bytes_right_with(count, 0)
}
pub fn shift_right_with(&mut self, count: usize, bit: bool) {
self.shift_bytes_right_with(count, if bit { 0xFF } else { 0 })
}
pub fn shifted_right(&self, count: usize) -> Self {
let mut clone = self.clone();
clone.shift_bytes_right_with(count, 0);
clone
}
pub fn sticky_shift_left(&mut self, count: usize) {
match self.size() {
0 => (),
_ => {
let bit = self.words[0] & 1;
self.shift_bytes_left_with(count, ((!bit as u16) + 1) as u8);
}
}
}
pub fn sticky_shift_right(&mut self, count: usize) {
match self.size() {
0 => (),
n => {
let bit = (self.words[n - 1] >> (8 - self.padding - 1)) & 1;
self.shift_bytes_right_with(count, ((!bit as u16) + 1) as u8);
}
}
}
pub fn size(&self) -> usize { self.words.nbytes }
pub fn split(&self, i: usize) -> (Bits, Bits) {
if i >= self.nbits { return (self.clone(), Bits::empty()) }
if i == 0 { return (Bits::empty(), self.clone()) }
let rlen = self.nbits - i;
let (lsize, loverflow) = divrem8!(ceil; i);
let idiv8 = i >> 3;
let (rsize, roverflow) = (self.size() - idiv8, rlen & 7);
let (lmask, rmask) = (mask!(loverflow), mask!(roverflow));
unsafe {
let pointer = self.words.as_ptr_mut();
let l = pointer![lsize];
let r = pointer![rsize];
for i in 0..lsize { *l.add(i) = *pointer.add(i); }
for i in 0..rsize { *r.add(i) = *pointer.add(idiv8 + i); }
let rbytes = RawBytes { bytes: NonNull::new(r).unwrap(), cap: rsize, nbytes: rsize };
let mut rbits = Bits {
words: rbytes,
mask: rmask,
nbits: self.nbits - i,
padding: (8 - roverflow) & 7
};
if loverflow > 0 {
*l.add(lsize - 1) &= lmask;
rbits.words.shift_right(rsize, lmask, 8 - loverflow, loverflow);
}
let lbytes = RawBytes { bytes: NonNull::new(l).unwrap(), cap: lsize, nbytes: lsize };
let lbits = Bits {
words: lbytes,
mask: lmask,
nbits: i,
padding: (8 - loverflow) & 7
};
(lbits, rbits)
}
}
pub fn test(&self, i: usize) -> bool {
unsafe {
i < self.nbits && (*self.words.as_ptr_mut().add(i >> 3) & (1 << (i & 7))) > 0
}
}
pub fn toggle(&mut self, i: usize) {
assert!(i < self.nbits, "Index out of range");
unsafe { *self.words.as_ptr_mut().add(i >> 3) ^= 1 << (i & 7); }
}
pub fn toggle_bits(&mut self, start: usize, count: usize) {
assert!(count <= self.nbits && start <= self.nbits - count, "Invalid range");
let end = if count > (self.nbits - start) { self.nbits } else { start + count };
let mut start = start;
let low_overflow = 8 - (start & 7);
unsafe {
let pointer = self.words.as_ptr_mut();
if low_overflow < 8 {
*pointer.add(start >> 3) ^= ((1 << low_overflow) - 1) << (start & 7);
start = start + low_overflow;
}
let bytes = (end - start) >> 3;
let start_byte = start >> 3;
for i in start_byte..(start_byte + bytes) { *pointer.add(i) = !*pointer.add(i); }
let overflow = (end - start) & 7;
if overflow > 0 { *pointer.add(start_byte + bytes) ^= (1 << overflow) - 1; }
}
}
pub fn toggle_byte(&mut self, i: usize) {
assert!(i < self.size(), "Index out of range");
unsafe {
let pointer = self.words.as_ptr_mut();
*pointer.add(i) = !*pointer.add(i);
*pointer.add(self.size() - 1) &= self.mask;
}
}
pub fn toggle_bytes(&mut self, start: usize, count: usize) {
assert!(count <= self.size() && start <= self.size() - count, "Invalid range");
unsafe {
let pointer = self.words.as_ptr_mut();
let end = if count > (self.size() - start) { self.size() } else { start + count };
for i in start..end { *pointer.add(i) = !*pointer.add(i); }
if end == self.size() && self.padding > 0 { *pointer.add(end - 1) &= self.mask; }
}
}
pub fn trailing_ones(&self) -> usize {
match self.size() {
0 => 0,
n => unsafe {
let pointer = self.words.as_ptr_const();
let mut i = 1;
while i < (n - 1) && *pointer.add(i - 1) == 0xFF { i += 1; }
((i - 1) << 3) + ((*pointer.add(i - 1) & self.mask).trailing_ones() as usize)
}
}
}
pub fn trailing_zeros(&self) -> usize {
match self.size() {
0 => 0,
n => unsafe {
let pointer = self.words.as_ptr_const();
let mut i = 0;
while i < (n - 1) && *pointer.add(i) == 0 { i += 1; }
let zeros = if i == (n - 1) {
let mut trailing = (*pointer.add(i) & self.mask).trailing_zeros() as usize;
if *pointer.add(i) == 0 { trailing -= self.padding; }
trailing
} else {
(*pointer.add(i)).trailing_zeros() as usize
};
zeros + (i << 3)
}
}
}
pub fn trim_end(&mut self, bit: bool) {
unsafe {
let pointer = self.words.as_ptr_mut();
*pointer.add(self.size() - 1) &= self.mask;
let mut i = self.size();
if self.padding > 0 {
let last_byte = pointer.add(self.size() - 1);
if bit && *last_byte != self.mask {
*last_byte <<= self.padding;
let clo = (*last_byte).leading_ones() as usize;
*last_byte <<= clo;
*last_byte >>= self.padding + clo;
self.nbits-= clo;
let overflow = self.nbits & 7;
self.padding = (8 - overflow) & 7;
self.mask = mask!(overflow);
return;
} else if !bit && *last_byte != 0 {
let clz = (*last_byte).leading_zeros() as usize;
self.nbits = self.nbits + self.padding - clz;
let overflow = self.nbits & 7;
self.padding = (8 - overflow) & 7;
self.mask = mask!(overflow);
return;
}
i -= 1;
}
let match_byte = if bit { 0xFF } else { 0 };
while i > 0 && *pointer.add(i - 1) == match_byte { i -= 1; }
if i == 0 {
for i in 0..self.size() { *pointer.add(i) = 0; }
self.words.nbytes = 0;
self.nbits = 0;
self.padding = 0;
self.mask = 0xFF;
self.words.shrink_to(0);
return;
}
self.words.shrink_to(i);
let trailing = if bit {
(*pointer.add(i - 1)).leading_ones() as usize
} else {
(*pointer.add(i - 1)).leading_zeros() as usize
};
self.words.nbytes = i;
self.nbits = (i << 3) - trailing;
let overflow = self.nbits & 7;
self.padding = (8 - overflow) & 7;
self.mask = mask!(overflow);
*pointer.add(i - 1) &= self.mask;
}
}
pub fn trim_start(&mut self, bit: bool) {
unsafe {
let pointer = self.words.as_ptr_mut();
let last = pointer.add(self.size() - 1);
*last &= self.mask;
let mut i = 0;
let match_byte = if bit { 0xFF } else { 0 };
while i < (self.size() - 1) && *pointer.add(i) == match_byte { i += 1; }
if i == (self.size() - 1) {
if (bit && *last == self.mask) || (!bit && *last == 0)
{
for i in 0..self.size() { *pointer.add(i) = 0; }
self.words.nbytes = 0;
self.nbits = 0;
self.padding = 0;
self.mask = 0xFF;
self.words.shrink_to(0);
return;
}
let trailing = if bit {
(*last).trailing_ones()
} else {
(*last).trailing_zeros()
} as usize;
*pointer = *last >> trailing;
self.padding += trailing;
self.words.nbytes = 1;
self.nbits = 8 - self.padding - trailing;
self.mask = mask!(self.nbits & 7);
self.words.shrink_to(1);
return;
}
ptr::copy(pointer.add(i), pointer, self.size() - i);
self.words.nbytes -= i;
self.nbits -= i << 3;
let trailing = if bit {
(*pointer).trailing_ones()
} else {
(*pointer).trailing_zeros()
} as usize;
if trailing > 0 {
let mask = (1 << trailing) - 1;
let low = 8 - trailing;
self.words.shift_right(self.size(), mask, low, trailing);
self.nbits -= trailing;
let overflow = self.nbits & 7;
self.padding = (8 - overflow) & 7;
self.mask = mask!(overflow);
}
self.shrink_to_fit()
}
}
pub fn xor(&self, rhs: &Bits) -> Bits { bitop!(self, ^, rhs) }
pub fn xor_mut(&mut self, rhs: &Bits) { bitop!(assign; self, ^=, rhs) }
fn cons_bit(&mut self, nbits: usize, fill: u8) {
unsafe {
let (nbytes_padding, overflow) = divrem8!(ceil; nbits);
let nbytes = self.size() + nbytes_padding;
self.words.expand_to(nbytes);
let pointer = self.words.as_ptr_mut();
if self.size() > 0 { *pointer.add(self.size() - 1) &= self.mask; }
ptr::copy(pointer, pointer.add(nbytes_padding), self.size());
for i in 0..nbytes_padding { ptr::write(pointer.add(i), fill); }
*pointer.add(nbytes_padding - 1) &= mask!(overflow);
if overflow > 0 {
let clz = 8 - overflow;
let mask = (1 << clz) - 1;
self.words.shift_right_from(nbytes_padding, nbytes, mask, overflow, clz);
}
self.words.nbytes = nbytes;
self.nbits += nbits;
let new_overflow = self.nbits & 7;
self.padding = (8 - new_overflow) & 7;
self.mask = mask!(new_overflow);
self.shrink_to_fit();
}
}
fn push_ones(&mut self, count: usize) {
unsafe {
let pointer = self.words.as_ptr_mut();
*pointer.add(self.size() - 1) &= self.mask;
let overflow = self.nbits & 7;
if self.padding > 0 && count <= self.padding {
*pointer.add(self.size() - 1) |= ((1 << count) - 1) << overflow;
} else {
*pointer.add(self.size() - 1) |= ((1 << self.padding) - 1) << overflow;
let (byte_len, overflow) = divrem8!(ceil; count - self.padding);
self.words.expand_to(self.size() + byte_len);
let pointer = self.words.as_ptr_mut().add(self.size());
for i in 0..(byte_len - 1) { ptr::write(pointer.add(i), 0xFF); }
ptr::write(pointer.add(byte_len - 1), mask!(overflow));
self.words.nbytes += byte_len;
}
self.nbits += count;
let overflow = self.nbits & 7;
self.padding = (8 - overflow) & 7;
self.mask = mask!(overflow);
}
}
fn push_zeros(&mut self, count: usize) {
unsafe {
let pointer = self.words.as_ptr_mut();
*pointer.add(self.size() - 1) &= self.mask;
if self.padding == 0 || count > self.padding {
let byte_len = 1 + ((count - self.padding - 1) >> 3);
self.words.expand_to(self.size() + byte_len);
let pointer = self.words.as_ptr_mut().add(self.size());
for i in 0..byte_len { ptr::write(pointer.add(i), 0); }
self.words.nbytes += byte_len;
}
self.nbits += count;
let overflow = self.nbits & 7;
self.padding = (8 - overflow) & 7;
self.mask = mask!(overflow);
}
}
fn shift_bytes_left_with(&mut self, count: usize, constant: u8) {
match (self.size(), count) {
(0, _) | (_, 0) => (),
(_, count) if count >= self.nbits => unsafe {
let pointer = self.words.as_ptr_mut();
for i in 0..self.size() { *pointer.add(i) = constant }
},
(n, count) => unsafe {
let pointer = self.words.as_ptr_mut();
let shift_overflow = count & 7;
let shift_bytes = count >> 3;
if shift_bytes > 0 {
ptr::copy(pointer, pointer.add(shift_bytes), self.size() - shift_bytes);
for i in 0..shift_bytes { *pointer.add(i) = constant; }
*pointer.add(n - 1) &= self.mask;
}
if shift_overflow > 0 {
let low = 8 - shift_overflow;
for i in 1..n {
*pointer.add(n - i) <<= shift_overflow;
*pointer.add(n - i) |= *pointer.add(n - i - 1) >> low;
}
let low_mask = ((1 << shift_overflow) - 1) & constant;
*pointer = (*pointer << shift_overflow) | low_mask;
}
*pointer.add(n - 1) &= self.mask;
}
}
}
fn shift_bytes_right_with(&mut self, count: usize, constant: u8) {
match (self.size(), count) {
(0, _) | (_, 0) => (),
(_, count) if count >= self.nbits => unsafe {
let pointer = self.words.as_ptr_mut();
for i in 0..self.size() { *pointer.add(i) = constant }
},
(n, count) => unsafe {
let upper_mask = ((constant as u16) << (8 - self.padding)) as u8;
let pointer = self.words.as_ptr_mut();
*pointer.add(n - 1) = (*pointer.add(n - 1) & self.mask) | upper_mask;
let byte_shift = count >> 3;
ptr::copy(pointer.add(byte_shift), pointer, self.size() - byte_shift);
for i in (self.size() - byte_shift)..self.size() {
*pointer.add(i) = constant;
}
let overflow = count & 7;
if overflow > 0 {
let mask = (1 << overflow) - 1;
let low = 8 - overflow;
let end = self.size() - byte_shift;
self.words.shift_right(end, mask, low, overflow);
let upper_mask = ((constant as u16) << low) as u8;
*pointer.add(end - 1) |= upper_mask;
}
}
}
}
fn shrink_to_fit(&mut self) { self.words.shrink_to(1 + ((self.nbits - 1) >> 3)); }
}
impl Binary for Bits {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
unsafe {
let aptr = self.words.as_ptr_const();
if self.padding == 0 {
for i in (0..self.size()).rev() { write!(f, "{:08b}", *aptr.add(i))?; }
} else {
write!(
f,
"{:01$b}",
*aptr.add(self.size() - 1) & self.mask,
8 - self.padding
)?;
for i in (0..(self.size() - 1)).rev() {
write!(f, "{:08b}", *aptr.add(i))?;
}
}
Ok(())
}
}
}
impl Clone for Bits {
fn clone(&self) -> Self {
match self.size() {
0 => Bits::empty(),
nbytes => unsafe {
let pointer = self.words.as_ptr_mut();
let layout = Layout::array::<u8>(nbytes).unwrap();
let clone = alloc::alloc(layout);
for i in 0..nbytes { ptr::write(clone.add(i), *pointer.add(i)); }
*clone.add(nbytes - 1) &= self.mask;
let bytes = RawBytes { bytes: NonNull::new(clone).unwrap(), cap: nbytes, nbytes };
Bits { words: bytes, mask: self.mask, nbits: self.nbits, padding: self.padding }
}
}
}
}
impl Debug for Bits {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Bits<")?;
Binary::fmt(&self, f)?;
write!(f, ": {}>", self.nbits)
}
}
impl Display for Bits {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { Binary::fmt(&self, f) }
}
impl Div<usize> for &Bits {
type Output = (Bits, Bits);
fn div(self, index: usize) -> Self::Output { self.split(index) }
}
impl Div<usize> for Bits {
type Output = (Bits, Bits);
fn div(self, index: usize) -> Self::Output { self.split(index) }
}
impl Drop for Bits {
fn drop(&mut self) {
if self.words.nbytes > 0 {
unsafe {
let pointer = self.words.as_ptr_mut();
for i in 0..self.words.nbytes { ptr::read(pointer.add(i)); }
}
}
}
}
impl Eq for Bits {}
impl From<&[u8]> for Bits {
fn from(data: &[u8]) -> Self { Self::from(data.to_vec()) }
}
impl<const N: usize> From<[u8; N]> for Bits {
fn from(bytes: [u8; N]) -> Self {
let mut nbytes = N;
while nbytes > 0 && bytes[nbytes - 1] == 0 { nbytes -= 1; }
if nbytes == 0 {
Bits::empty()
} else {
let nbits = (nbytes << 3) - (bytes[nbytes - 1].leading_zeros() as usize);
let mut truncated_bytes = bytes[..nbytes].to_vec();
let pointer = truncated_bytes.as_mut_ptr();
std::mem::forget(truncated_bytes);
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap: nbytes, nbytes };
let overflow = nbits & 7;
Bits { words: bytes, mask: mask!(overflow), nbits, padding: (8 - overflow) & 7 }
}
}
}
impl From<Vec<u8>> for Bits {
fn from(mut bytes: Vec<u8>) -> Self {
let mut nbytes = bytes.len();
while nbytes > 0 && bytes[nbytes - 1] == 0 { nbytes -= 1; }
match nbytes {
0 => Bits::empty(),
nbytes => {
let nbits = (nbytes << 3) - (bytes[nbytes - 1].leading_zeros() as usize);
bytes.truncate(nbytes);
let cap = bytes.capacity();
let pointer = bytes.as_mut_ptr();
let overflow = nbits & 7;
std::mem::forget(bytes);
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap, nbytes };
Bits { words: bytes, mask: mask!(overflow), nbits, padding: (8 - overflow) & 7 }
}
}
}
}
impl From<&[bool]> for Bits {
fn from(bits: &[bool]) -> Self {
match bits.len() {
0 => Bits::empty(),
nbits => unsafe {
let (nbytes, overflow) = divrem8!(ceil; nbits);
let padding = (8 - overflow) & 7;
let mask = mask!(overflow);
let layout = Layout::array::<u8>(nbytes).unwrap();
let pointer = alloc::alloc(layout);
for i in 0..(nbytes - 1) {
let mut b = 0;
let j = i << 3;
if bits[j + 0] { b |= 1; }
if bits[j + 1] { b |= 2; }
if bits[j + 2] { b |= 4; }
if bits[j + 3] { b |= 8; }
if bits[j + 4] { b |= 16; }
if bits[j + 5] { b |= 32; }
if bits[j + 6] { b |= 64; }
if bits[j + 7] { b |= 128; }
ptr::write(pointer.add(i), b);
}
let mut b = 0;
for i in 0..(8 - padding) {
if bits[nbits - overflow + i] { b |= 1 << i; }
}
ptr::write(pointer.add(nbytes - 1), b);
let bytes = RawBytes { bytes: NonNull::new(pointer).unwrap(), cap: nbytes, nbytes };
Bits { words: bytes, mask, nbits, padding }
}
}
}
}
impl<const N: usize> From<[bool; N]> for Bits {
fn from(bits: [bool; N]) -> Self { Bits::from(bits.as_slice()) }
}
impl From<Vec<bool>> for Bits {
fn from(bits: Vec<bool>) -> Self { Bits::from(bits.as_slice()) }
}
impl FromIterator<u8> for Bits {
fn from_iter<I: IntoIterator<Item=u8>>(iter: I) -> Self {
Bits::from(iter.into_iter().collect::<Vec<u8>>())
}
}
impl FromIterator<bool> for Bits {
fn from_iter<I: IntoIterator<Item=bool>>(iter: I) -> Self {
Bits::from(iter.into_iter().collect::<Vec<bool>>())
}
}
impl Ord for Bits {
fn cmp(&self, other: &Self) -> Ordering {
match other.leading_zeros().cmp(&self.leading_zeros()) {
Ordering::Equal => unsafe {
let aptr= self.words.as_ptr_const();
let bptr = other.words.as_ptr_const();
for i in (0..self.size()).rev() {
match (*aptr.add(i)).cmp(&*bptr.add(i)) {
Ordering::Equal => (),
ord => return ord,
}
}
Ordering::Equal
},
ord => ord,
}
}
}
impl PartialEq for Bits {
fn eq(&self, other: &Self) -> bool {
match (self.nbits, other.nbits) {
(0, 0) => true,
(a, b) if a != b => false,
_ => unsafe {
let aptr = self.words.as_ptr_const();
let bptr = other.words.as_ptr_const();
for i in 0..(self.size() - 1) {
if *aptr.add(i) != *bptr.add(i) { return false; }
}
let last_a = *aptr.add(self.size() - 1) & self.mask;
let last_b = *bptr.add(other.size() - 1) & other.mask;
last_a == last_b
}
}
}
}
impl PartialOrd for Bits {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}
unsafe impl Send for Bits {}
unsafe impl Sync for Bits {}