#![no_std]
#![deny(
missing_docs,
unused_extern_crates,
unused_import_braces,
unused_qualifications
)]
#[macro_export(local_inner_macros)]
macro_rules! bitfield_impl {
(Debug for struct $name:ident([$t:ty]); $($rest:tt)*) => {
impl<T: AsRef<[$t]> + $crate::fmt::Debug> $crate::fmt::Debug for $name<T> {
bitfield_debug!{struct $name; $($rest)*}
}
};
(Debug for struct $name:ident($t:ty); $($rest:tt)*) => {
impl $crate::fmt::Debug for $name {
bitfield_debug!{struct $name; $($rest)*}
}
};
(BitAnd for struct $name:ident([$t:ty]); $($rest:tt)*) => {
bitfield_impl!{@bitwise BitAnd bitand BitAndAssign bitand_assign $name([$t]) &=}
};
(BitAnd for struct $name:ident($t:ty); $($rest:tt)*) => {
bitfield_impl!{@bitwise BitAnd bitand BitAndAssign bitand_assign $name($t) &=}
};
(BitOr for struct $name:ident([$t:ty]); $($rest:tt)*) => {
bitfield_impl!{@bitwise BitOr bitor BitOrAssign bitor_assign $name([$t]) |=}
};
(BitOr for struct $name:ident($t:ty); $($rest:tt)*) => {
bitfield_impl!{@bitwise BitOr bitor BitOrAssign bitor_assign $name($t) |=}
};
(BitXor for struct $name:ident([$t:ty]); $($rest:tt)*) => {
bitfield_impl!{@bitwise BitXor bitxor BitXorAssign bitxor_assign $name([$t]) ^=}
};
(BitXor for struct $name:ident($t:ty); $($rest:tt)*) => {
bitfield_impl!{@bitwise BitXor bitxor BitXorAssign bitxor_assign $name($t) ^=}
};
(@bitwise $bitwise:ident $func:ident $bitwise_assign:ident $func_assign:ident $name:ident([$t:ty]) $op:tt) => {
impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::ops::$bitwise for $name<T> {
type Output = Self;
fn $func(mut self, rhs: Self) -> Self {
bitfield_impl!(@mutate self rhs $op);
self
}
}
impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::ops::$bitwise_assign for $name<T> {
fn $func_assign(&mut self, rhs: Self) {
bitfield_impl!(@mutate self rhs $op);
}
}
};
(@bitwise $bitwise:ident $func:ident $bitwise_assign:ident $func_assign:ident $name:ident($t:ty) $op:tt) => {
impl $crate::ops::$bitwise for $name {
type Output = Self;
fn $func(mut self, rhs: Self) -> Self {
self.0 $op rhs.0;
self
}
}
impl $crate::ops::$bitwise_assign for $name {
fn $func_assign(&mut self, rhs: Self) {
self.0 $op rhs.0;
}
}
};
(@mutate $self:ident $rhs:ident $op:tt) => {{
let as_mut = AsMut::<[_]>::as_mut(&mut $self.0);
let rhs = AsRef::<[_]>::as_ref(&$rhs.0);
for i in 0..as_mut.len() {
as_mut[i] $op rhs[i];
}
}};
(new for struct $name:ident([$t:ty]); $($rest:tt)*) => {
impl<T: AsMut<[$t]> + Default> $name<T> {
bitfield_constructor!{() -> {}; $($rest)*}
}
};
(new for struct $name:ident($t:ty); $($rest:tt)*) => {
impl $name {
bitfield_constructor!{() -> {}; $($rest)*}
}
};
(new{$new:ident ($($setter_name:ident: $setter_type:ty),*$(,)?)} for struct $name:ident([$t:ty]); $($rest:tt)*) => {
impl<T: AsMut<[$t]> + Default> $name<T> {
pub fn $new($($setter_name: $setter_type),*) -> Self {
let mut value = Self(T::default());
$(
value.$setter_name($setter_name);
)*
value
}
}
};
(new{$new:ident ($($setter_name:ident: $setter_type:ty),*$(,)?)} for struct $name:ident($t:ty); $($rest:tt)*) => {
impl $name {
pub fn $new($($setter_name: $setter_type),*) -> Self {
let mut value = Self($t::default());
$(
value.$setter_name($setter_name);
)*
value
}
}
};
($macro:ident for struct $name:ident $($rest:tt)*) => {
::std::compile_error!(::std::stringify!(Unsupported impl $macro for struct $name));
};
}
#[macro_export(local_inner_macros)]
macro_rules! bitfield_fields {
(only mask; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, _, $setter:ident: $($exprs:expr),*) => {
bitfield_fields!(only mask; @field $(#[$attribute])* ($($vis)*) $t, $mask($mask_t): $($exprs),*);
};
(only mask; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, $getter:ident, _: $($exprs:expr),*) => {
bitfield_fields!(only mask; @field $(#[$attribute])* ($($vis)*) $t, $mask($mask_t): $($exprs),*);
};
(only mask; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, __NO_MASK_FOR_FIELD($mask_t:ty): $($exprs:expr),*) => {};
(only mask; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty): $bit:expr) => {
$($vis)* const $mask: $mask_t = 1 << $bit;
};
(only mask; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty): $msb:expr, $lsb:expr) => {
$($vis)* const $mask: $mask_t = {
let msb = $msb;
let lsb = $lsb;
let mut i = lsb;
let mut acc = 0;
while i <= msb {
acc |= 1<<i;
i += 1;
}
acc
};
};
(only mask; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty): $msb:expr, $lsb:expr, $count:expr) => {
$($vis)* const $mask: $mask_t = {
let msb = $msb;
let lsb = $lsb;
let width = msb - lsb;
let full_msb = msb + width * $count;
let mut i = lsb;
let mut acc = 0;
while i <= full_msb {
acc |= 1<<i;
i += 1;
}
acc
};
};
(only setter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, _, $setter:ident: $msb:expr,
$lsb:expr, $count:expr) => {
$(#[$attribute])*
#[allow(unknown_lints)]
#[allow(eq_op)]
$($vis)* fn $setter(&mut self, index: usize, value: $from) {
use $crate::BitRangeMut;
__bitfield_debug_assert!(index < $count);
let width = $msb - $lsb + 1;
let lsb = $lsb + index*width;
let msb = lsb + width - 1;
self.set_bit_range(msb, lsb, $crate::Into::<$t>::into(value));
}
};
(only setter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, _, $setter:ident: $msb:expr,
$lsb:expr) => {
$(#[$attribute])*
$($vis)* fn $setter(&mut self, value: $from) {
use $crate::BitRangeMut;
self.set_bit_range($msb, $lsb, $crate::Into::<$t>::into(value));
}
};
(only setter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, _, $setter:ident: $bit:expr) => {
$(#[$attribute])*
$($vis)* fn $setter(&mut self, value: bool) {
use $crate::BitMut;
self.set_bit($bit, value);
}
};
(only getter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, _, $setter:ident: $($exprs:expr),*) => {};
(only getter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, $getter:ident, _: $msb:expr, $lsb:expr, $count:expr) => {
$(#[$attribute])*
#[allow(unknown_lints)]
#[allow(eq_op)]
$($vis)* fn $getter(&self, index: usize) -> $into {
use $crate::BitRange;
__bitfield_debug_assert!(index < $count);
let width = $msb - $lsb + 1;
let lsb = $lsb + index*width;
let msb = lsb + width - 1;
let raw_value: $t = self.bit_range(msb, lsb);
$crate::Into::into(raw_value)
}
};
(only getter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, $getter:ident, _: $msb:expr,
$lsb:expr) => {
$(#[$attribute])*
$($vis)* fn $getter(&self) -> $into {
use $crate::BitRange;
let raw_value: $t = self.bit_range($msb, $lsb);
$crate::Into::into(raw_value)
}
};
(only getter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, $getter:ident, _: $bit:expr) => {
$(#[$attribute])*
$($vis)* fn $getter(&self) -> bool {
use $crate::Bit;
self.bit($bit)
}
};
(only setter; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, $getter:ident, _: $($exprs:expr),*) => {};
(only $only:tt; @field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $mask:ident($mask_t:ty), $from:ty, $into:ty, $getter:ident, $setter:ident:
$($exprs:expr),*) => {
bitfield_fields!(only $only; @field $(#[$attribute])* ($($vis)*) $t, $mask($mask_t), $from, $into, $getter, _: $($exprs),*);
bitfield_fields!(only $only; @field $(#[$attribute])* ($($vis)*) $t, __NO_MASK_FOR_FIELD(u8), $from, $into, _, $setter: $($exprs),*);
};
(only $only:tt; $t:ty;) => {};
(only $only:tt; $default_ty:ty; pub $($rest:tt)*) => {
bitfield_fields!{only $only; $default_ty; () pub $($rest)*}
};
(only $only:tt; $default_ty:ty; #[$attribute:meta] $($rest:tt)*) => {
bitfield_fields!{only $only; $default_ty; (#[$attribute]) $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attributes:meta])*) #[$attribute:meta] $($rest:tt)*) => {
bitfield_fields!{only $only; $default_ty; ($(#[$attributes])* #[$attribute]) $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, mask $mask:ident($mask_t:ty), from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $t, $mask($mask_t), $into, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, mask $mask:ident($mask_t:ty), into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $t, $mask($mask_t), $t, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, mask $mask:ident($mask_t:ty), $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $t, $mask($mask_t), $t, $t, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub mask $mask:ident($mask_t:ty), from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $default_ty, $mask($mask_t), $into, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub mask $mask:ident($mask_t:ty), into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $default_ty, $mask($mask_t), $default_ty, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub mask $mask:ident($mask_t:ty), $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $default_ty, $mask($mask_t), $default_ty, $default_ty, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $t, __NO_MASK_FOR_FIELD(u8), $into, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $t, __NO_MASK_FOR_FIELD(u8), $t, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $t, __NO_MASK_FOR_FIELD(u8), $t, $t, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $default_ty, __NO_MASK_FOR_FIELD(u8), $into, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $default_ty, __NO_MASK_FOR_FIELD(u8), $default_ty, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) pub $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* (pub) $default_ty, __NO_MASK_FOR_FIELD(u8), $default_ty, $default_ty, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) $t:ty, mask $mask:ident($mask_t:ty), from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $t, $mask($mask_t), $into, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) $t:ty, mask $mask:ident($mask_t:ty), into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $t, $mask($mask_t), $t, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) $t:ty, mask $mask:ident($mask_t:ty), $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $t, $mask($mask_t), $t, $t, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) mask $mask:ident($mask_t:ty), from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $default_ty, $mask($mask_t), $into, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) mask $mask:ident($mask_t:ty), into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $default_ty, $mask($mask_t), $default_ty, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) mask $mask:ident($mask_t:ty), $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $default_ty, $mask($mask_t), $default_ty, $default_ty, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) $t:ty, from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $t, __NO_MASK_FOR_FIELD(u8), $into, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) $t:ty, into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $t, __NO_MASK_FOR_FIELD(u8), $t, $into, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) $t:ty, $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $t, __NO_MASK_FOR_FIELD(u8), $t, $t, $getter, $setter: $($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) from into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $default_ty, __NO_MASK_FOR_FIELD(u8), $into, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) into $into:ty, $getter:tt, $setter:tt:
$($exprs:expr),*; $($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $default_ty, __NO_MASK_FOR_FIELD(u8), $default_ty, $into, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; ($(#[$attribute:meta])*) $getter:tt, $setter:tt: $($exprs:expr),*;
$($rest:tt)*) => {
bitfield_fields!{only $only; @field $(#[$attribute])* () $default_ty, __NO_MASK_FOR_FIELD(u8), $default_ty, $default_ty, $getter, $setter:
$($exprs),*}
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $previous_default_ty:ty; $default_ty:ty; $($rest:tt)*) => {
bitfield_fields!{only $only; $default_ty; $($rest)*}
};
(only $only:tt; $default_ty:ty; $($rest:tt)*) => {
bitfield_fields!{only $only; $default_ty; () $($rest)*}
};
(only $only:tt; $($rest:tt)*) => {
bitfield_fields!{only $only; SET_A_DEFAULT_TYPE_OR_SPECIFY_THE_TYPE_FOR_EACH_FIELDS; $($rest)*}
};
($($rest:tt)*) => {
bitfield_fields!{only getter; $($rest)*}
bitfield_fields!{only setter; $($rest)*}
bitfield_fields!{only mask; $($rest)*}
}
}
#[macro_export(local_inner_macros)]
macro_rules! bitfield_debug {
(struct $name:ident; $($rest:tt)*) => {
fn fmt(&self, f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
let mut debug_struct = f.debug_struct(__bitfield_stringify!($name));
debug_struct.field(".0", &self.0);
bitfield_debug!{debug_struct, self, $($rest)*}
debug_struct.finish()
}
};
($debug_struct:ident, $self:ident, mask $mask:ident($mask_t:ty), $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, #[$attribute:meta] $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, pub $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, _, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, $type:ty; $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, $getter:ident, $setter:tt: $msb:expr, $lsb:expr, $count:expr;
$($rest:tt)*) => {
let mut array = [$self.$getter(0); $count];
for (i, e) in (&mut array).into_iter().enumerate() {
*e = $self.$getter(i);
}
$debug_struct.field(__bitfield_stringify!($getter), &array);
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, $getter:ident, $setter:tt: $($exprs:expr),*; $($rest:tt)*)
=> {
$debug_struct.field(__bitfield_stringify!($getter), &$self.$getter());
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, from into $into:ty, $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, into $into:ty, $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, $type:ty, $($rest:tt)*) => {
bitfield_debug!{$debug_struct, $self, $($rest)*}
};
($debug_struct:ident, $self:ident, ) => {};
}
#[macro_export(local_inner_macros)]
macro_rules! bitfield_constructor {
(() -> {}; $($rest:tt)*) => {
bitfield_constructor!{@value; () -> {let mut value = Self(Default::default());}; bool; $($rest)*}
};
(@$value:ident; ($($param:ident: $ty:ty,)*) -> {$($stmt:stmt;)*}; $old_ty:ty; impl $_trait:ident$({$($trait_arg:tt)*})?; $($rest:tt)*) => {
bitfield_constructor!{@$value; ($($param: $ty,)*) -> {$($stmt;)*}; $old_ty; $($rest)*}
};
(@$value:ident; ($($param:ident: $ty:ty,)*) -> {$($stmt:stmt;)*}; $old_ty:ty; $new_ty:ty; $($rest:tt)*) => {
bitfield_constructor!{@$value; ($($param: $ty,)*) -> {$($stmt;)*}; $new_ty; $($rest)*}
};
(@$value:ident; ($($param:ident: $ty:ty,)*) -> {$($stmt:stmt;)*}; $default_ty:ty;
$(#[$_:meta])* $(pub)? $(into $_into:ty,)?
$_getter:ident, $setter:ident: $($_expr:expr),*; $($rest:tt)* ) => {
bitfield_constructor!{@$value;
($($param: $ty,)* $setter: $default_ty,) -> {$($stmt;)* $value.$setter($setter);};
$default_ty; $($rest)*}
};
(@$value:ident; ($($param:ident: $ty:ty,)*) -> {$($stmt:stmt;)*}; $default_ty:ty;
$(#[$_:meta])* $(pub)? $field_type:ty, $(into $_into:ty,)?
$_getter:ident, $setter:ident: $($_expr:expr),*; $($rest:tt)* ) => {
bitfield_constructor!{@$value;
($($param: $ty,)* $setter: $field_type,) -> {$($stmt;)* $value.$setter($setter);};
$default_ty; $($rest)*}
};
(@$value:ident; ($($param:ident: $ty:ty,)*) -> {$($stmt:stmt;)*}; $_:ty;) => {
#[allow(clippy::too_many_arguments)]
pub fn new($($param: $ty),*) -> Self {
$($stmt;)*
$value
}
};
}
#[macro_export(local_inner_macros)]
macro_rules! bitfield_bitrange {
(@impl_bitrange_slice $name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
impl<T: AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
for $name<T> {
fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
let bit_len = $crate::size_of::<$slice_ty>()*8;
let value_bit_len = $crate::size_of::<$bitrange_ty>()*8;
let mut value = 0;
for i in (lsb..=msb).rev() {
value <<= 1;
value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as $bitrange_ty;
}
value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1))
}
}
impl<T: AsMut<[$slice_ty]>> $crate::BitRangeMut<$bitrange_ty>
for $name<T> {
fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
let bit_len = $crate::size_of::<$slice_ty>()*8;
let mut value = value;
for i in lsb..=msb {
self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len));
self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty << (i%bit_len);
value >>= 1;
}
}
}
};
(@impl_bitrange_slice_msb0 $name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
impl<T: AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
for $name<T> {
fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
let bit_len = $crate::size_of::<$slice_ty>()*8;
let value_bit_len = $crate::size_of::<$bitrange_ty>()*8;
let mut value = 0;
for i in lsb..=msb {
value <<= 1;
value |= ((self.0.as_ref()[i/bit_len] >> (bit_len - i%bit_len - 1)) & 1)
as $bitrange_ty;
}
value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1))
}
}
impl<T: AsMut<[$slice_ty]>> $crate::BitRangeMut<$bitrange_ty>
for $name<T> {
fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
let bit_len = $crate::size_of::<$slice_ty>()*8;
let mut value = value;
for i in (lsb..=msb).rev() {
self.0.as_mut()[i/bit_len] &= !(1 << (bit_len - i%bit_len - 1));
self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty
<< (bit_len - i%bit_len - 1);
value >>= 1;
}
}
}
};
(struct $name:ident([$t:ty])) => {
bitfield_bitrange!(@impl_bitrange_slice $name, $t, u8);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, u16);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, u32);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, u64);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, u128);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, i8);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, i16);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, i32);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, i64);
bitfield_bitrange!(@impl_bitrange_slice $name, $t, i128);
};
(struct $name:ident(MSB0 [$t:ty])) => {
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u8);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u16);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u32);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u64);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u128);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i8);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i16);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i32);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i64);
bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i128);
};
(struct $name:ident($t:ty)) => {
impl<T> $crate::BitRange<T> for $name where $t: $crate::BitRange<T> {
fn bit_range(&self, msb: usize, lsb: usize) -> T {
self.0.bit_range(msb, lsb)
}
}
impl<T> $crate::BitRangeMut<T> for $name where $t: $crate::BitRangeMut<T> {
fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T) {
self.0.set_bit_range(msb, lsb, value);
}
}
};
}
#[macro_export(local_inner_macros)]
macro_rules! bitfield {
($(#[$attribute:meta])* $vis:vis struct $name:ident($($type:tt)*); $(impl $trait:ident$({$($trait_arg:tt)*})?;)+ no default BitRange; $($rest:tt)*) => {
bitfield!{$(#[$attribute])* $vis struct $name($($type)*); no default BitRange; $(impl $trait$({$($trait_arg)*})?;)* $($rest)*}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); no default BitRange; impl $trait:ident$({$($trait_arg:tt)*})?; $($rest:tt)*) => {
bitfield_impl!{$trait$({$($trait_arg)*})? for struct $name([$t]); $($rest)*}
bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); no default BitRange; $($rest:tt)*) => {
$(#[$attribute])*
$vis struct $name<T>(pub T);
impl<T: AsRef<[$t]>> $name<T> {
bitfield_fields!{only getter; $($rest)*}
}
impl<T: AsMut<[$t]>> $name<T> {
bitfield_fields!{only setter; $($rest)*}
}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); $($rest:tt)*) => {
bitfield_bitrange!(struct $name([$t]));
bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident(MSB0 [$t:ty]); no default BitRange; $($rest:tt)*) => {
bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident(MSB0 [$t:ty]); $($rest:tt)*) => {
bitfield_bitrange!(struct $name(MSB0 [$t]));
bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); no default BitRange; impl $trait:ident$({$($trait_arg:tt)*})?; $($rest:tt)*) => {
bitfield_impl!{$trait$({$($trait_arg)*})? for struct $name($t); $($rest)*}
bitfield!{$(#[$attribute])* $vis struct $name($t); no default BitRange; $($rest)*}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); no default BitRange; $($rest:tt)*) => {
$(#[$attribute])*
$vis struct $name(pub $t);
impl $name {
bitfield_fields!{$t; $($rest)*}
}
};
($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); $($rest:tt)*) => {
bitfield_bitrange!(struct $name($t));
bitfield!{$(#[$attribute])* $vis struct $name($t); no default BitRange; $($rest)*}
};
}
#[doc(hidden)]
pub use core::convert::Into;
#[doc(hidden)]
pub use core::fmt;
#[doc(hidden)]
pub use core::mem::size_of;
#[doc(hidden)]
pub use core::ops;
pub trait BitRange<T> {
fn bit_range(&self, msb: usize, lsb: usize) -> T;
}
pub trait BitRangeMut<T> {
fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
}
pub trait Bit {
fn bit(&self, bit: usize) -> bool;
}
pub trait BitMut {
fn set_bit(&mut self, bit: usize, value: bool);
}
impl<T: BitRange<u8>> Bit for T {
fn bit(&self, bit: usize) -> bool {
self.bit_range(bit, bit) != 0
}
}
impl<T: BitRangeMut<u8>> BitMut for T {
fn set_bit(&mut self, bit: usize, value: bool) {
self.set_bit_range(bit, bit, value as u8);
}
}
macro_rules! impl_bitrange_for_u {
($t:ty, $bitrange_ty:ty) => {
impl BitRange<$bitrange_ty> for $t {
#[inline]
#[allow(clippy::cast_lossless)]
#[allow(clippy::manual_bits)]
fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
let bit_len = size_of::<$t>()*8;
let result_bit_len = size_of::<$bitrange_ty>()*8;
let result = ((*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb))
as $bitrange_ty;
result << (result_bit_len - (msb - lsb + 1)) >> (result_bit_len - (msb - lsb + 1))
}
}
impl BitRangeMut<$bitrange_ty> for $t {
#[inline]
#[allow(clippy::cast_lossless)]
#[allow(clippy::manual_bits)]
fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
let bit_len = size_of::<$t>()*8;
let mask: $t = !(0 as $t)
<< (bit_len - msb - 1)
>> (bit_len - msb - 1 + lsb)
<< (lsb);
*self &= !mask;
*self |= (value as $t << lsb) & mask;
}
}
}
}
macro_rules! impl_bitrange_for_u_combinations {
((),($($bitrange_ty:ty),*)) => {
};
(($t:ty),($($bitrange_ty:ty),*)) => {
$(impl_bitrange_for_u!{$t, $bitrange_ty})*
};
(($t_head:ty, $($t_rest:ty),*),($($bitrange_ty:ty),*)) => {
impl_bitrange_for_u_combinations!{($t_head), ($($bitrange_ty),*)}
impl_bitrange_for_u_combinations!{($($t_rest),*), ($($bitrange_ty),*)}
};
}
impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (u8, u16, u32, u64, u128)}
impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (i8, i16, i32, i64, i128)}
#[macro_export]
#[doc(hidden)]
macro_rules! __bitfield_stringify {
($s:ident) => {
stringify!($s)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __bitfield_debug_assert {
($e:expr) => {
debug_assert!($e)
};
}