use std::{
marker::PhantomData,
ops::{BitAndAssign, BitOrAssign, BitXorAssign},
ptr::NonNull,
};
use crate::{
BitRead, Iter,
traits::{BitWord, BitWrite},
util::{
bitset_all, bitset_any, bitset_clear, bitset_count_ones, bitset_fill, bitset_flip,
bitset_reset, bitset_set, bitset_test, bitset_test_and_set,
},
};
pub struct BitView<'a, T: BitWord> {
ptr: NonNull<T>,
len: usize,
_marker: PhantomData<&'a T>,
}
pub struct BitViewMut<'a, T: BitWord> {
ptr: NonNull<T>,
len: usize,
_marker: PhantomData<&'a mut T>,
}
impl<'a, T: BitWord> BitViewMut<'a, T> {
#[inline]
pub(crate) fn new(ptr: NonNull<T>, len: usize) -> Self {
Self {
ptr,
len,
_marker: PhantomData,
}
}
#[inline]
pub unsafe fn from_raw_parts(ptr: *const T, len: usize) -> Self {
Self {
ptr: NonNull::new(ptr as *mut T).unwrap(),
len,
_marker: PhantomData,
}
}
}
impl<'a, T: BitWord> BitView<'a, T> {
#[inline]
pub(crate) fn new(ptr: NonNull<T>, len: usize) -> Self {
Self {
ptr,
len,
_marker: PhantomData,
}
}
#[inline]
pub unsafe fn from_raw_parts(ptr: *const T, len: usize) -> Self {
Self {
ptr: NonNull::new(ptr as *mut T).unwrap(),
len,
_marker: PhantomData,
}
}
}
impl<'a, W: BitWord> BitRead for BitView<'a, W> {
type Iter<'b>
= Iter<'b, W>
where
Self: 'b;
#[inline]
fn len(&self) -> usize {
self.len
}
#[inline]
fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
fn test(&self, idx: usize) -> bool {
unsafe { bitset_test(self.ptr, self.len, idx) }
}
#[inline]
fn count_ones(&self) -> usize {
unsafe { bitset_count_ones(self.ptr, self.len) }
}
#[inline]
fn all(&self) -> bool {
unsafe { bitset_all(self.ptr, self.len) }
}
#[inline]
fn any(&self) -> bool {
unsafe { bitset_any(self.ptr, self.len) }
}
#[inline]
fn iter(&self) -> Self::Iter<'_> {
Iter::from_raw_parts(self.ptr.as_ptr(), self.len)
}
}
impl<'a, T: BitWord> BitRead for BitViewMut<'a, T> {
type Iter<'b>
= Iter<'b, T>
where
Self: 'b;
#[inline]
fn len(&self) -> usize {
self.len
}
#[inline]
fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
fn test(&self, idx: usize) -> bool {
unsafe { bitset_test(self.ptr, self.len, idx) }
}
#[inline]
fn count_ones(&self) -> usize {
unsafe { bitset_count_ones(self.ptr, self.len) }
}
#[inline]
fn all(&self) -> bool {
unsafe { bitset_all(self.ptr, self.len) }
}
#[inline]
fn any(&self) -> bool {
unsafe { bitset_any(self.ptr, self.len) }
}
#[inline]
fn iter(&self) -> Self::Iter<'_> {
Iter::from_raw_parts(self.ptr.as_ptr(), self.len)
}
}
impl<'a, T: BitWord> BitWrite for BitViewMut<'a, T> {
#[inline]
fn set(&mut self, idx: usize) {
unsafe { bitset_set(self.ptr, self.len, idx) };
}
#[inline]
fn reset(&mut self, idx: usize) {
unsafe { bitset_reset(self.ptr, self.len, idx) };
}
#[inline]
fn flip(&mut self, idx: usize) {
unsafe { bitset_flip(self.ptr, self.len, idx) };
}
#[inline]
fn test_and_set(&mut self, idx: usize) -> bool {
unsafe { bitset_test_and_set(self.ptr, self.len, idx) }
}
#[inline]
fn fill(&mut self) {
unsafe { bitset_fill(self.ptr, self.len) };
}
#[inline]
fn clear(&mut self) {
unsafe { bitset_clear(self.ptr, self.len) };
}
}
impl<'a, 'b, T: BitWord> BitAndAssign<&'b BitView<'b, T>> for BitViewMut<'a, T> {
fn bitand_assign(&mut self, rhs: &'b BitView<'b, T>) {
for index in self.iter().collect::<Vec<_>>() {
if !rhs.test(index) {
self.reset(index);
}
}
}
}
impl<'a, 'b, T: BitWord> BitOrAssign<&'b BitView<'b, T>> for BitViewMut<'a, T> {
fn bitor_assign(&mut self, rhs: &'b BitView<'b, T>) {
for index in rhs.iter() {
self.set(index);
}
}
}
impl<'a, 'b, T: BitWord> BitXorAssign<&'b BitView<'b, T>> for BitViewMut<'a, T> {
fn bitxor_assign(&mut self, rhs: &'b BitView<'b, T>) {
for index in self.iter().collect::<Vec<_>>() {
if rhs.test(index) {
self.reset(index);
}
}
for index in rhs.iter() {
if self.test(index) {
self.reset(index);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bitview_basic() {
let data: [u8; 2] = [0b10101010, 0b01010101];
let bv = unsafe { BitView::from_raw_parts(data.as_ptr(), 16) };
assert_eq!(bv.test(0), false);
assert_eq!(bv.test(1), true);
assert_eq!(bv.test(2), false);
assert_eq!(bv.test(3), true);
assert_eq!(bv.test(8), true);
assert_eq!(bv.test(9), false);
assert_eq!(bv.count_ones(), 8);
assert!(!bv.all());
assert!(bv.any());
assert!(!bv.is_empty());
}
#[test]
fn test_bitview_empty() {
let data: [u8; 1] = [0];
let bv = BitView {
ptr: NonNull::new(data.as_ptr() as *const u8 as *mut u8).unwrap(),
len: 0,
_marker: PhantomData,
};
assert_eq!(bv.len(), 0);
assert!(bv.is_empty());
assert!(!bv.any());
assert!(bv.all());
assert_eq!(bv.count_ones(), 0);
}
#[test]
fn test_bitview_all_ones() {
let data: [u8; 2] = [0xFF, 0xFF];
let bv = BitView {
ptr: NonNull::new(data.as_ptr() as *const u8 as *mut u8).unwrap(),
len: 16,
_marker: PhantomData,
};
assert!(bv.all());
assert!(bv.any());
assert_eq!(bv.count_ones(), 16);
}
#[test]
fn test_bitview_partial_last_word() {
let data: [u8; 2] = [0xFF, 0x0F]; let bv = BitView {
ptr: NonNull::new(data.as_ptr() as *const u8 as *mut u8).unwrap(),
len: 12, _marker: PhantomData,
};
assert!(bv.all());
assert!(bv.any());
assert_eq!(bv.count_ones(), 12);
}
#[test]
fn test_bitview_iter() {
let data: [u8; 1] = [0b10110010];
let bv = BitView {
ptr: NonNull::new(data.as_ptr() as *const u8 as *mut u8).unwrap(),
len: 8,
_marker: PhantomData,
};
let bits: Vec<_> = bv.iter().collect();
assert_eq!(bits, vec![1, 4, 5, 7]);
}
#[test]
fn test_bitview_single_bit() {
let data: [u8; 1] = [0b00000010];
let bv = unsafe { BitView::from_raw_parts(data.as_ptr(), 8) };
assert_eq!(bv.count_ones(), 1);
assert!(bv.test(1));
for i in 0..8 {
if i != 1 {
assert!(!bv.test(i));
}
}
}
#[test]
fn test_bitview_zero_bits() {
let data: [u8; 1] = [0];
let bv = unsafe { BitView::from_raw_parts(data.as_ptr(), 0) };
assert_eq!(bv.len(), 0);
assert!(bv.is_empty());
assert!(!bv.any());
assert!(bv.all());
assert_eq!(bv.count_ones(), 0);
}
#[test]
fn test_bitview_iter_empty() {
let data: [u8; 1] = [0];
let bv = unsafe { BitView::from_raw_parts(data.as_ptr(), 0) };
let bits: Vec<_> = bv.iter().collect();
assert!(bits.is_empty());
}
#[test]
fn test_bitview_iter_partial_word() {
let data: [u8; 2] = [0b11110000, 0b00001111];
let bv = unsafe { BitView::from_raw_parts(data.as_ptr(), 12) };
let bits: Vec<_> = bv.iter().collect();
assert_eq!(bits, vec![4, 5, 6, 7, 8, 9, 10, 11]);
}
#[test]
fn test_bitview_mut() {
let mut v = [123, 0, 1, usize::MAX];
let len = v.len() * usize::BITS as usize - 3;
let mut r = unsafe { BitViewMut::from_raw_parts(v.as_mut_ptr(), len) };
r.set(0);
r.set(1);
r.set(7);
assert_eq!(v, [251, 0, 1, usize::MAX]);
r.clear();
assert_eq!(v, [0, 0, 0, 0]);
}
}