use funty::IsNumber;
use crate::{
mem::BitRegister,
order::BitOrder,
ptr::BitPtr,
slice::{
from_raw_parts_unchecked,
from_raw_parts_unchecked_mut,
BitSlice,
},
store::BitStore,
};
pub trait BitView {
type Store: BitStore;
fn view_bits<O>(&self) -> &BitSlice<O, Self::Store>
where O: BitOrder;
fn view_bits_mut<O>(&mut self) -> &mut BitSlice<O, Self::Store>
where O: BitOrder;
#[doc(hidden)]
#[inline]
fn const_bits() -> usize
where Self: Sized {
Self::const_elts()
* <<Self::Store as BitStore>::Mem as IsNumber>::BITS as usize
}
#[doc(hidden)]
fn const_elts() -> usize
where Self: Sized;
}
#[cfg(not(tarpaulin_include))]
impl<T> BitView for T
where T: BitStore
{
type Store = T;
#[inline(always)]
fn view_bits<O>(&self) -> &BitSlice<O, T>
where O: BitOrder {
BitSlice::from_element(self)
}
#[inline(always)]
fn view_bits_mut<O>(&mut self) -> &mut BitSlice<O, T>
where O: BitOrder {
BitSlice::from_element_mut(self)
}
#[doc(hidden)]
#[inline(always)]
fn const_elts() -> usize {
1
}
}
impl<T> BitView for [T]
where T: BitStore
{
type Store = T;
#[inline]
fn view_bits<O>(&self) -> &BitSlice<O, T>
where O: BitOrder {
BitSlice::from_slice(self).expect("slice was too long to view as bits")
}
#[inline]
fn view_bits_mut<O>(&mut self) -> &mut BitSlice<O, T>
where O: BitOrder {
BitSlice::from_slice_mut(self)
.expect("slice was too long to view as bits")
}
#[cold]
#[doc(hidden)]
#[inline(never)]
fn const_elts() -> usize {
unreachable!("This cannot be called on unsized slices")
}
}
#[cfg(not(tarpaulin_include))]
impl<T> BitView for [T; 0]
where T: BitStore
{
type Store = T;
#[inline(always)]
fn view_bits<O>(&self) -> &BitSlice<O, T>
where O: BitOrder {
BitSlice::empty()
}
#[inline(always)]
fn view_bits_mut<O>(&mut self) -> &mut BitSlice<O, T>
where O: BitOrder {
BitSlice::empty_mut()
}
#[doc(hidden)]
fn const_elts() -> usize {
0
}
}
macro_rules! view_bits {
($($n:expr),+ $(,)?) => { $(
impl<T> BitView for [T; $n]
where T: BitStore {
type Store = T;
#[inline]
fn view_bits<O>(&self) -> &BitSlice<O, T>
where O: BitOrder {
unsafe { from_raw_parts_unchecked(
BitPtr::from_slice(&self[..]),
$n * T::Mem::BITS as usize,
) }
}
#[inline]
fn view_bits_mut<O>(&mut self) -> &mut BitSlice<O, T>
where O: BitOrder {
unsafe { from_raw_parts_unchecked_mut(
BitPtr::from_mut_slice(&mut self[..]),
$n * T::Mem::BITS as usize,
) }
}
#[doc(hidden)]
#[inline(always)]
#[cfg(not(tarpaulin_include))]
fn const_elts() -> usize {
$n
}
}
)+ };
}
view_bits!(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64
);
pub trait AsBits<T>
where T: BitStore
{
fn as_bits<O>(&self) -> &BitSlice<O, T>
where O: BitOrder;
}
pub trait AsBitsMut<T>
where T: BitStore
{
fn as_bits_mut<O>(&mut self) -> &mut BitSlice<O, T>
where O: BitOrder;
}
#[cfg(not(tarpaulin_include))]
impl<A, T> AsBits<T> for A
where
A: AsRef<[T]>,
T: BitStore + BitRegister,
{
#[inline]
fn as_bits<O>(&self) -> &BitSlice<O, T>
where O: BitOrder {
self.as_ref().view_bits::<O>()
}
}
#[cfg(not(tarpaulin_include))]
impl<A, T> AsBitsMut<T> for A
where
A: AsMut<[T]>,
T: BitStore + BitRegister,
{
#[inline]
fn as_bits_mut<O>(&mut self) -> &mut BitSlice<O, T>
where O: BitOrder {
self.as_mut().view_bits_mut::<O>()
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
#[test]
fn impls() {
let mut byte = 0u8;
let mut bytes = [0u8; 2];
assert!(byte.view_bits::<LocalBits>().not_any());
assert!(byte.view_bits_mut::<LocalBits>().not_any());
assert!(bytes.view_bits::<LocalBits>().not_any());
assert!(bytes.view_bits_mut::<LocalBits>().not_any());
assert!(bytes[..].view_bits::<LocalBits>().not_any());
assert!(bytes[..].view_bits_mut::<LocalBits>().not_any());
let mut blank: [u8; 0] = [];
assert!(blank.view_bits::<LocalBits>().is_empty());
assert!(blank.view_bits_mut::<LocalBits>().is_empty());
assert_eq!(<u8 as BitView>::const_bits(), 8);
assert_eq!(<u16 as BitView>::const_bits(), 16);
assert_eq!(<u32 as BitView>::const_bits(), 32);
#[cfg(target_pointer_width = "64")]
{
assert_eq!(<u64 as BitView>::const_bits(), 64);
}
}
}