pub use modular_bitfield_impl::{
bitfield,
BitfieldSpecifier,
};
#[doc(hidden)]
pub mod checks;
pub mod prelude {
pub use super::{
specifiers::*,
PopBits,
PushBits,
bitfield,
BitfieldSpecifier,
Specifier,
SpecifierBase,
IntoBits,
FromBits,
};
}
pub mod specifiers {
modular_bitfield_impl::define_specifiers!();
}
#[doc(hidden)]
pub trait PushBits: checks::private::Sealed {
fn push_bits(&mut self, amount: u32, bits: u8);
}
#[doc(hidden)]
pub trait PopBits: checks::private::Sealed {
fn pop_bits(&mut self, amount: u32) -> u8;
}
macro_rules! impl_sealed_for {
( $($primitive:ty),* ) => {
$(
impl checks::private::Sealed for $primitive {}
)*
}
}
impl_sealed_for!(bool, u8, u16, u32, u64, u128);
impl PopBits for u8 {
#[inline(always)]
fn pop_bits(&mut self, amount: u32) -> u8 {
debug_assert!(amount <= 8);
let res = *self & ((0x1_u16.wrapping_shl(amount) as u8).wrapping_sub(1));
*self = self.wrapping_shr(amount);
res
}
}
macro_rules! impl_push_bits {
( $($type:ty),+ ) => {
$(
impl PushBits for $type {
#[inline(always)]
fn push_bits(&mut self, amount: u32, bits: u8) {
debug_assert!(amount <= 8);
*self <<= amount;
*self |= (bits & ((0x1_u16.wrapping_shl(amount) as u8).wrapping_sub(1))) as $type;
}
}
)+
}
}
impl_push_bits!(u8, u16, u32, u64, u128);
macro_rules! impl_pop_bits {
( $($type:ty),+ ) => {
$(
impl PopBits for $type {
#[inline(always)]
fn pop_bits(&mut self, amount: u32) -> u8 {
debug_assert!(amount <= 8);
let res = (*self & ((0x1 << amount) - 1)) as u8;
*self >>= amount;
res
}
}
)+
};
}
impl_pop_bits!(u16, u32, u64, u128);
#[doc(hidden)]
pub trait SpecifierBase: checks::private::Sealed {
type Base;
}
pub trait Specifier {
const BITS: usize;
type Base:
Default
+ PushBits
+ PopBits;
type Face:
FromBits<Self::Base>
+ IntoBits<Self::Base>;
}
#[doc(hidden)]
pub struct Bits<T>(pub T);
impl<T> Bits<T> {
#[inline(always)]
pub fn into_raw(self) -> T {
self.0
}
}
#[doc(hidden)]
pub trait IntoBits<T> {
fn into_bits(self) -> Bits<T>;
}
#[doc(hidden)]
pub trait FromBits<T> {
fn from_bits(bits: Bits<T>) -> Self;
}
impl Specifier for bool {
const BITS: usize = 1;
type Base = u8;
type Face = bool;
}
impl FromBits<u8> for bool {
#[inline(always)]
fn from_bits(bits: Bits<u8>) -> Self {
bits.into_raw() != 0
}
}
impl IntoBits<u8> for bool {
#[inline(always)]
fn into_bits(self) -> Bits<u8> {
Bits(self as u8)
}
}
macro_rules! impl_wrapper_from_naive {
( $($type:ty),* ) => {
$(
impl IntoBits<$type> for $type {
#[inline(always)]
fn into_bits(self) -> Bits<$type> {
Bits(self)
}
}
impl FromBits<$type> for $type {
#[inline(always)]
fn from_bits(bits: Bits<$type>) -> Self {
bits.into_raw()
}
}
)*
}
}
impl_wrapper_from_naive!(bool, u8, u16, u32, u64, u128);