use crate::*;
#[derive(Debug)]
pub enum BitPieceStorageMutRef<'a> {
U64(&'a mut u64),
U32(&'a mut u32),
U16(&'a mut u16),
U8(&'a mut u8),
}
impl<'a> BitPieceStorageMutRef<'a> {
#[inline(always)]
pub const fn get(&self) -> u64 {
match self {
BitPieceStorageMutRef::U64(x) => **x as u64,
BitPieceStorageMutRef::U32(x) => **x as u64,
BitPieceStorageMutRef::U16(x) => **x as u64,
BitPieceStorageMutRef::U8(x) => **x as u64,
}
}
#[inline(always)]
pub const fn set(&mut self, new_value: u64) {
match self {
BitPieceStorageMutRef::U64(x) => **x = new_value as u64,
BitPieceStorageMutRef::U32(x) => **x = new_value as u32,
BitPieceStorageMutRef::U16(x) => **x = new_value as u16,
BitPieceStorageMutRef::U8(x) => **x = new_value as u8,
}
}
pub const fn reborrow(&mut self) -> BitPieceStorageMutRef<'_> {
match self {
BitPieceStorageMutRef::U64(x) => BitPieceStorageMutRef::U64(x),
BitPieceStorageMutRef::U32(x) => BitPieceStorageMutRef::U32(x),
BitPieceStorageMutRef::U16(x) => BitPieceStorageMutRef::U16(x),
BitPieceStorageMutRef::U8(x) => BitPieceStorageMutRef::U8(x),
}
}
}
#[derive(Debug)]
pub struct BitsMut<'s> {
pub storage: BitPieceStorageMutRef<'s>,
pub start_bit_index: usize,
}
impl<'s> BitsMut<'s> {
#[inline(always)]
pub const fn new(storage: BitPieceStorageMutRef<'s>, start_bit_index: usize) -> Self {
Self {
storage,
start_bit_index,
}
}
#[inline(always)]
pub const fn get_bits(&self, rel_bit_index: usize, len: usize) -> u64 {
extract_bits(
self.storage.get(),
self.start_bit_index + rel_bit_index,
len,
)
}
#[inline(always)]
pub const fn get_bits_noshift(&self, rel_bit_index: usize, len: usize) -> u64 {
extract_bits_noshift(
self.storage.get(),
self.start_bit_index + rel_bit_index,
len,
)
}
#[inline(always)]
pub const fn set_bits(&mut self, rel_bit_index: usize, len: usize, new_value: u64) {
self.storage.set(modify_bits(
self.storage.get(),
self.start_bit_index + rel_bit_index,
len,
new_value,
));
}
}
pub trait BitPieceMutRef<'s> {
type BitPiece: BitPiece;
fn new(storage: BitPieceStorageMutRef<'s>, start_bit_index: usize) -> Self;
fn get(&self) -> Self::BitPiece;
fn set(&mut self, new_value: Self::BitPiece);
}
#[macro_export]
macro_rules! bitpiece_define_mut_ref_type {
{$t: ty, $mut_ref_ty_name: ident, $($vis: tt)?} => {
#[derive(Debug)]
$($vis)? struct $mut_ref_ty_name<'s>(pub $crate::BitsMut<'s>);
impl<'s> $mut_ref_ty_name<'s> {
pub const fn new(storage: $crate::BitPieceStorageMutRef<'s>, start_bit_index: usize) -> Self {
Self($crate::BitsMut::new(storage, start_bit_index))
}
$($vis)? const fn get(&self) -> $t {
let bits = self.0.get_bits(0, <$t as $crate::BitPiece>::BITS) as <$t as $crate::BitPiece>::Bits;
<$t as $crate::BitPiece>::Converter::from_bits(bits)
}
$($vis)? const fn set(&mut self, new_value: $t) {
let bits = <$t as $crate::BitPiece>::Converter::to_bits(new_value);
self.0
.set_bits(0, <$t as $crate::BitPiece>::BITS, bits as u64);
}
}
impl<'s> $crate::BitPieceMutRef<'s> for $mut_ref_ty_name<'s> {
type BitPiece = $t;
fn new(storage: $crate::BitPieceStorageMutRef<'s>, start_bit_index: usize) -> Self {
Self::new(storage, start_bit_index)
}
fn get(&self) -> $t {
self.get()
}
fn set(&mut self, new_value: $t) {
self.set(new_value)
}
}
};
}