use funty::IsNumber;
use crate::{
order::BitOrder,
slice::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;
}
#[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)
}
}
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")
}
}
impl<T, const N: usize> BitView for [T; N]
where T: BitStore
{
type Store = T;
#[inline]
fn view_bits<O>(&self) -> &BitSlice<O, T>
where O: BitOrder {
BitSlice::from_slice(&self[..])
.expect("array 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(&mut self[..])
.expect("array was too long to view as bits")
}
}
pub trait BitViewSized: BitView + Sized {
const ELTS: usize;
const BITS: usize =
Self::ELTS * <<Self::Store as BitStore>::Mem as IsNumber>::BITS as usize;
}
impl<T> BitViewSized for T
where T: BitStore
{
const ELTS: usize = 1;
}
impl<T, const N: usize> BitViewSized for [T; N]
where T: BitStore
{
const ELTS: usize = N;
}
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,
{
#[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,
{
#[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::*,
view::BitViewSized,
};
#[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 BitViewSized>::BITS, 8);
assert_eq!(<u16 as BitViewSized>::BITS, 16);
assert_eq!(<u32 as BitViewSized>::BITS, 32);
#[cfg(target_pointer_width = "64")]
{
assert_eq!(<u64 as BitViewSized>::BITS, 64);
}
}
}