use core::{
any,
convert::TryFrom,
fmt::{
self,
Binary,
Debug,
Display,
Formatter,
},
iter::{
FusedIterator,
Sum,
},
marker::PhantomData,
ops::{
BitAnd,
BitOr,
Not,
},
};
use crate::{
mem::BitRegister,
order::BitOrder,
};
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitIdx<R>
where R: BitRegister
{
idx: u8,
_ty: PhantomData<R>,
}
impl<R> BitIdx<R>
where R: BitRegister
{
pub const LAST: Self = Self {
idx: R::MASK,
_ty: PhantomData,
};
pub const ZERO: Self = Self {
idx: 0,
_ty: PhantomData,
};
pub fn new(value: u8) -> Result<Self, BitIdxError<R>> {
if value >= R::BITS as u8 {
return Err(BitIdxError::new(value));
}
Ok(unsafe { Self::new_unchecked(value) })
}
pub unsafe fn new_unchecked(value: u8) -> Self {
debug_assert!(
value < R::BITS as u8,
"Bit index {} cannot exceed type width {}",
value,
R::BITS,
);
Self {
idx: value,
_ty: PhantomData,
}
}
pub fn cast<S>(self) -> Result<BitIdx<S>, BitIdxError<S>>
where S: BitRegister {
BitIdx::new(self.value())
}
#[cfg(not(tarpaulin_include))]
pub fn value(self) -> u8 {
self.idx
}
pub fn next(self) -> (Self, bool) {
let next = self.idx + 1;
(
unsafe { Self::new_unchecked(next & R::MASK) },
next == R::BITS as u8,
)
}
pub fn prev(self) -> (Self, bool) {
let prev = self.idx.wrapping_sub(1);
(
unsafe { Self::new_unchecked(prev & R::MASK) },
self.idx == 0,
)
}
#[cfg(not(tarpaulin_include))]
pub fn position<O>(self) -> BitPos<R>
where O: BitOrder {
O::at::<R>(self)
}
#[cfg(not(tarpaulin_include))]
pub fn select<O>(self) -> BitSel<R>
where O: BitOrder {
O::select::<R>(self)
}
#[cfg(not(tarpaulin_include))]
pub fn mask<O>(self) -> BitMask<R>
where O: BitOrder {
self.select::<O>().mask()
}
pub fn range(
self,
upto: BitTail<R>,
) -> impl Iterator<Item = Self>
+ DoubleEndedIterator
+ ExactSizeIterator
+ FusedIterator {
let (from, upto) = (self.value(), upto.value());
debug_assert!(from <= upto, "Ranges must run from low to high");
(from .. upto).map(|val| unsafe { Self::new_unchecked(val) })
}
pub fn range_all() -> impl Iterator<Item = Self>
+ DoubleEndedIterator
+ ExactSizeIterator
+ FusedIterator {
BitIdx::ZERO.range(BitTail::LAST)
}
pub fn offset(self, by: isize) -> (isize, Self) {
let val = self.value();
let (far, ovf) = by.overflowing_add(val as isize);
if !ovf {
if (0 .. R::BITS as isize).contains(&far) {
(0, unsafe { Self::new_unchecked(far as u8) })
}
else {
(far >> R::INDX, unsafe {
Self::new_unchecked(far as u8 & R::MASK)
})
}
}
else {
let far = far as usize;
((far >> R::INDX) as isize, unsafe {
Self::new_unchecked(far as u8 & R::MASK)
})
}
}
pub fn span(self, len: usize) -> (usize, BitTail<R>) {
unsafe { BitTail::<R>::new_unchecked(self.value()) }.span(len)
}
}
impl<R> TryFrom<u8> for BitIdx<R>
where R: BitRegister
{
type Error = BitIdxError<R>;
fn try_from(value: u8) -> Result<Self, Self::Error> {
Self::new(value)
}
}
impl<R> Binary for BitIdx<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{:0>1$b}", self.idx, R::INDX as usize)
}
}
impl<R> Debug for BitIdx<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "BitIdx<{}>({})", any::type_name::<R>(), self)
}
}
#[cfg(not(tarpaulin_include))]
impl<R> Display for BitIdx<R>
where R: BitRegister
{
#[inline(always)]
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
Binary::fmt(&self, fmt)
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitIdxError<R>
where R: BitRegister
{
err: u8,
_ty: PhantomData<R>,
}
impl<R> BitIdxError<R>
where R: BitRegister
{
pub(crate) fn new(value: u8) -> Self {
debug_assert!(
value >= R::BITS as u8,
"Bit index {} is valid for type width {}",
value,
R::BITS
);
Self {
err: value,
_ty: PhantomData,
}
}
#[cfg(not(tarpaulin_include))]
pub fn value(self) -> u8 {
self.err
}
}
impl<R> Debug for BitIdxError<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "BitIdxErr<{}>({})", any::type_name::<R>(), self.err)
}
}
#[cfg(not(tarpaulin_include))]
impl<R> Display for BitIdxError<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(
fmt,
"The value {} is too large to index into {} ({} bits)",
self.err,
any::type_name::<R>(),
R::BITS
)
}
}
#[cfg(feature = "std")]
impl<R> std::error::Error for BitIdxError<R> where R: BitRegister
{
}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitTail<R>
where R: BitRegister
{
end: u8,
_ty: PhantomData<R>,
}
impl<R> BitTail<R>
where R: BitRegister
{
pub const LAST: Self = Self {
end: R::BITS as u8,
_ty: PhantomData,
};
pub const ZERO: Self = Self {
end: 0,
_ty: PhantomData,
};
pub fn new(value: u8) -> Option<Self> {
if value > R::BITS as u8 {
return None;
}
Some(unsafe { Self::new_unchecked(value) })
}
pub(crate) unsafe fn new_unchecked(value: u8) -> Self {
debug_assert!(
value <= R::BITS as u8,
"Bit tail {} cannot exceed type width {}",
value,
R::BITS,
);
Self {
end: value,
_ty: PhantomData,
}
}
#[cfg(not(tarpaulin_include))]
pub fn value(self) -> u8 {
self.end
}
pub fn range_from(
from: BitIdx<R>,
) -> impl Iterator<Item = Self>
+ DoubleEndedIterator
+ ExactSizeIterator
+ FusedIterator {
(from.idx ..= Self::LAST.end)
.map(|tail| unsafe { BitTail::new_unchecked(tail) })
}
pub(crate) fn span(self, len: usize) -> (usize, Self) {
if len == 0 {
return (0, self);
}
let val = self.end;
let head = val & R::MASK;
let bits_in_head = (R::BITS as u8 - head) as usize;
if len <= bits_in_head {
return (1, unsafe { Self::new_unchecked(head + len as u8) });
}
let bits_after_head = len - bits_in_head;
let elts = bits_after_head >> R::INDX;
let tail = bits_after_head as u8 & R::MASK;
let is_zero = (tail == 0) as u8;
let edges = 2 - is_zero as usize;
(elts + edges, unsafe {
Self::new_unchecked((is_zero << R::INDX) | tail)
})
}
}
impl<R> Binary for BitTail<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{:0>1$b}", self.end, R::INDX as usize + 1)
}
}
impl<R> Debug for BitTail<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "BitTail<{}>({})", any::type_name::<R>(), self)
}
}
#[cfg(not(tarpaulin_include))]
impl<R> Display for BitTail<R>
where R: BitRegister
{
#[inline(always)]
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
Binary::fmt(&self, fmt)
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitPos<R>
where R: BitRegister
{
pos: u8,
_ty: PhantomData<R>,
}
impl<R> BitPos<R>
where R: BitRegister
{
pub fn new(value: u8) -> Option<Self> {
if value >= R::BITS as u8 {
return None;
}
Some(unsafe { Self::new_unchecked(value) })
}
pub unsafe fn new_unchecked(value: u8) -> Self {
debug_assert!(
value < R::BITS as u8,
"Bit position {} cannot exceed type width {}",
value,
R::BITS,
);
Self {
pos: value,
_ty: PhantomData,
}
}
#[cfg(not(tarpaulin_include))]
pub fn value(self) -> u8 {
self.pos
}
pub fn select(self) -> BitSel<R> {
unsafe { BitSel::new_unchecked(R::ONE << self.pos) }
}
#[cfg(not(tarpaulin_include))]
pub fn mask(self) -> BitMask<R> {
self.select().mask()
}
pub(crate) fn range_all() -> impl Iterator<Item = Self>
+ DoubleEndedIterator
+ ExactSizeIterator
+ FusedIterator {
BitIdx::<R>::range_all()
.map(|idx| unsafe { Self::new_unchecked(idx.value()) })
}
}
impl<R> Binary for BitPos<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{:0>1$b}", self.pos, R::INDX as usize)
}
}
impl<R> Debug for BitPos<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "BitPos<{}>({})", any::type_name::<R>(), self)
}
}
#[cfg(not(tarpaulin_include))]
impl<R> Display for BitPos<R>
where R: BitRegister
{
#[inline(always)]
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
Binary::fmt(&self, fmt)
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitSel<R>
where R: BitRegister
{
sel: R,
}
impl<R> BitSel<R>
where R: BitRegister
{
pub fn new(value: R) -> Option<Self> {
if value.count_ones() != 1 {
return None;
}
Some(unsafe { Self::new_unchecked(value) })
}
pub unsafe fn new_unchecked(value: R) -> Self {
debug_assert!(
value.count_ones() == 1,
"Selections are required to have exactly one set bit: {:0>1$b}",
value,
R::BITS as usize,
);
Self { sel: value }
}
#[cfg(not(tarpaulin_include))]
pub fn value(self) -> R {
self.sel
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn mask(self) -> BitMask<R> {
BitMask::new(self.sel)
}
pub fn range_all() -> impl Iterator<Item = Self>
+ DoubleEndedIterator
+ ExactSizeIterator
+ FusedIterator {
BitPos::<R>::range_all().map(BitPos::select)
}
}
impl<R> Binary for BitSel<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{:0>1$b}", self.sel, R::BITS as usize)
}
}
impl<R> Debug for BitSel<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "BitSel<{}>({})", any::type_name::<R>(), self)
}
}
#[cfg(not(tarpaulin_include))]
impl<R> Display for BitSel<R>
where R: BitRegister
{
#[inline(always)]
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
Binary::fmt(&self, fmt)
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitMask<R>
where R: BitRegister
{
mask: R,
}
impl<R> BitMask<R>
where R: BitRegister
{
pub const ALL: Self = Self { mask: R::ALL };
pub const ZERO: Self = Self { mask: R::ZERO };
pub fn new(value: R) -> Self {
Self { mask: value }
}
#[cfg(not(tarpaulin_include))]
pub fn value(self) -> R {
self.mask
}
pub fn test(&self, sel: BitSel<R>) -> bool {
self.mask & sel.sel != R::ZERO
}
pub fn insert(&mut self, sel: BitSel<R>) {
self.mask |= sel.sel;
}
pub fn combine(self, sel: BitSel<R>) -> Self {
Self {
mask: self.mask | sel.sel,
}
}
}
impl<R> Binary for BitMask<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{:0>1$b}", self.mask, R::BITS as usize)
}
}
impl<R> Debug for BitMask<R>
where R: BitRegister
{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "BitMask<{}>({})", any::type_name::<R>(), self)
}
}
#[cfg(not(tarpaulin_include))]
impl<R> Display for BitMask<R>
where R: BitRegister
{
#[inline(always)]
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
Binary::fmt(&self, fmt)
}
}
impl<R> Sum<BitSel<R>> for BitMask<R>
where R: BitRegister
{
fn sum<I>(iter: I) -> Self
where I: Iterator<Item = BitSel<R>> {
iter.fold(Self::ZERO, Self::combine)
}
}
impl<R> BitAnd<R> for BitMask<R>
where R: BitRegister
{
type Output = Self;
fn bitand(self, rhs: R) -> Self::Output {
Self {
mask: self.mask & rhs,
}
}
}
impl<R> BitOr<R> for BitMask<R>
where R: BitRegister
{
type Output = Self;
fn bitor(self, rhs: R) -> Self::Output {
Self {
mask: self.mask | rhs,
}
}
}
impl<R> Not for BitMask<R>
where R: BitRegister
{
type Output = Self;
fn not(self) -> Self::Output {
Self { mask: !self.mask }
}
}
#[cfg(test)]
mod tests {
use tap::conv::TryConv;
use super::*;
use crate::order::Lsb0;
#[test]
fn index_ctors() {
for n in 0 .. 8 {
assert!(BitIdx::<u8>::new(n).is_ok());
assert!(n.try_conv::<BitIdx<u8>>().is_ok());
}
assert!(BitIdx::<u8>::new(8).is_err());
assert!(8u8.try_conv::<BitIdx<u8>>().is_err());
for n in 0 .. 16 {
assert!(BitIdx::<u16>::new(n).is_ok());
}
assert!(BitIdx::<u16>::new(16).is_err());
for n in 0 .. 32 {
assert!(BitIdx::<u32>::new(n).is_ok());
}
assert!(BitIdx::<u32>::new(32).is_err());
#[cfg(target_pointer_width = "64")]
{
for n in 0 .. 64 {
assert!(BitIdx::<u64>::new(n).is_ok());
}
assert!(BitIdx::<u64>::new(64).is_err());
}
if cfg!(target_pointer_width = "32") {
for n in 0 .. 32 {
assert!(BitIdx::<usize>::new(n).is_ok());
}
assert!(BitIdx::<usize>::new(32).is_err());
}
else if cfg!(target_pointer_width = "64") {
for n in 0 .. 64 {
assert!(BitIdx::<usize>::new(n).is_ok());
}
assert!(BitIdx::<usize>::new(64).is_err());
}
}
#[test]
fn tail_ctors() {
for n in 0 ..= 8 {
assert!(BitTail::<u8>::new(n).is_some());
}
assert!(BitTail::<u8>::new(9).is_none());
for n in 0 ..= 16 {
assert!(BitTail::<u16>::new(n).is_some());
}
assert!(BitTail::<u16>::new(17).is_none());
for n in 0 ..= 32 {
assert!(BitTail::<u32>::new(n).is_some());
}
assert!(BitTail::<u32>::new(33).is_none());
#[cfg(target_pointer_width = "64")]
{
for n in 0 ..= 64 {
assert!(BitTail::<u64>::new(n).is_some());
}
assert!(BitTail::<u64>::new(65).is_none());
}
if cfg!(target_pointer_width = "32") {
for n in 0 ..= 32 {
assert!(BitTail::<usize>::new(n).is_some());
}
assert!(BitTail::<usize>::new(33).is_none());
}
else if cfg!(target_pointer_width = "64") {
for n in 0 ..= 64 {
assert!(BitTail::<usize>::new(n).is_some());
}
assert!(BitTail::<usize>::new(65).is_none());
}
}
#[test]
fn position_ctors() {
for n in 0 .. 8 {
assert!(BitPos::<u8>::new(n).is_some());
}
assert!(BitPos::<u8>::new(8).is_none());
for n in 0 .. 16 {
assert!(BitPos::<u16>::new(n).is_some());
}
assert!(BitPos::<u16>::new(16).is_none());
for n in 0 .. 32 {
assert!(BitPos::<u32>::new(n).is_some());
}
assert!(BitPos::<u32>::new(32).is_none());
#[cfg(target_pointer_width = "64")]
{
for n in 0 .. 64 {
assert!(BitPos::<u64>::new(n).is_some());
}
assert!(BitPos::<u64>::new(64).is_none());
}
if cfg!(target_pointer_width = "32") {
for n in 0 .. 32 {
assert!(BitPos::<usize>::new(n).is_some());
}
assert!(BitPos::<usize>::new(32).is_none());
}
else if cfg!(target_pointer_width = "64") {
for n in 0 .. 64 {
assert!(BitPos::<usize>::new(n).is_some());
}
assert!(BitPos::<usize>::new(64).is_none());
}
}
#[test]
fn select_ctors() {
for n in 0 .. 8 {
assert!(BitSel::<u8>::new(1 << n).is_some());
}
assert!(BitSel::<u8>::new(3).is_none());
for n in 0 .. 16 {
assert!(BitSel::<u16>::new(1 << n).is_some());
}
assert!(BitSel::<u16>::new(3).is_none());
for n in 0 .. 32 {
assert!(BitSel::<u32>::new(1 << n).is_some());
}
assert!(BitSel::<u32>::new(3).is_none());
#[cfg(target_pointer_width = "64")]
{
for n in 0 .. 64 {
assert!(BitSel::<u64>::new(1 << n).is_some());
}
assert!(BitSel::<u64>::new(3).is_none());
}
if cfg!(target_pointer_width = "32") {
for n in 0 .. 32 {
assert!(BitSel::<usize>::new(1 << n).is_some());
}
assert!(BitSel::<usize>::new(3).is_none());
}
else if cfg!(target_pointer_width = "64") {
for n in 0 .. 64 {
assert!(BitSel::<usize>::new(1 << n).is_some());
}
assert!(BitSel::<usize>::new(3).is_none());
}
}
#[test]
fn ranges() {
let mut range = BitIdx::<u16>::range_all();
assert_eq!(range.next(), BitIdx::new(0).ok());
assert_eq!(range.next_back(), BitIdx::new(15).ok());
assert_eq!(range.count(), 14);
let mut range = BitTail::<u8>::range_from(BitIdx::new(1).unwrap());
assert_eq!(range.next(), BitTail::new(1));
assert_eq!(range.next_back(), BitTail::new(8));
assert_eq!(range.count(), 6);
let mut range = BitPos::<u8>::range_all();
assert_eq!(range.next(), BitPos::new(0));
assert_eq!(range.next_back(), BitPos::new(7));
assert_eq!(range.count(), 6);
let mut range = BitSel::<u8>::range_all();
assert_eq!(range.next(), BitSel::new(1));
assert_eq!(range.next_back(), BitSel::new(128));
assert_eq!(range.count(), 6);
}
#[test]
fn index_cycle() {
let six = BitIdx::<u8>::new(6).unwrap();
let (seven, step) = six.next();
assert_eq!(seven, BitIdx::new(7).unwrap());
assert!(!step);
let (zero, step) = seven.next();
assert_eq!(zero, BitIdx::ZERO);
assert!(step);
let (seven, step) = zero.prev();
assert_eq!(seven, BitIdx::new(7).unwrap());
assert!(step);
let (six, step) = seven.prev();
assert_eq!(six, BitIdx::new(6).unwrap());
assert!(!step);
let fourteen = BitIdx::<u16>::new(14).unwrap();
let (fifteen, step) = fourteen.next();
assert_eq!(fifteen, BitIdx::new(15).unwrap());
assert!(!step);
let (zero, step) = fifteen.next();
assert_eq!(zero, BitIdx::ZERO);
assert!(step);
let (fifteen, step) = zero.prev();
assert_eq!(fifteen, BitIdx::new(15).unwrap());
assert!(step);
let (fourteen, step) = fifteen.prev();
assert_eq!(fourteen, BitIdx::new(14).unwrap());
assert!(!step);
}
#[test]
fn jumps() {
let (jump, head) = BitIdx::<u8>::new(1).unwrap().offset(2);
assert_eq!(jump, 0);
assert_eq!(head, BitIdx::new(3).unwrap());
let (jump, head) = BitIdx::<u8>::LAST.offset(1);
assert_eq!(jump, 1);
assert_eq!(head, BitIdx::ZERO);
let (jump, head) = BitIdx::<u16>::new(10).unwrap().offset(40);
assert_eq!(jump, 3);
assert_eq!(head, BitIdx::new(2).unwrap());
let (jump, head) = BitIdx::<u8>::LAST.offset(isize::MAX);
assert_eq!(jump, ((isize::MAX as usize + 1) >> 3) as isize);
assert_eq!(head, BitIdx::LAST.prev().0);
let (elts, tail) = BitIdx::<u8>::new(4).unwrap().span(0);
assert_eq!(elts, 0);
assert_eq!(tail, BitTail::new(4).unwrap());
let (elts, tail) = BitIdx::<u8>::new(3).unwrap().span(3);
assert_eq!(elts, 1);
assert_eq!(tail, BitTail::new(6).unwrap());
let (elts, tail) = BitIdx::<u16>::new(10).unwrap().span(40);
assert_eq!(elts, 4);
assert_eq!(tail, BitTail::new(2).unwrap());
}
#[test]
fn mask_operators() {
let mut mask = BitIdx::<u8>::new(2)
.unwrap()
.range(BitTail::new(5).unwrap())
.map(BitIdx::select::<Lsb0>)
.sum::<BitMask<u8>>();
assert_eq!(mask, BitMask::new(28));
assert_eq!(mask & 25, BitMask::new(24));
assert_eq!(mask | 32, BitMask::new(60));
assert_eq!(!mask, BitMask::new(!28));
let yes = BitSel::<u8>::new(16).unwrap();
let no = BitSel::<u8>::new(64).unwrap();
assert!(mask.test(yes));
assert!(!mask.test(no));
mask.insert(no);
assert!(mask.test(no));
}
#[test]
#[cfg(feature = "alloc")]
fn render() {
#[cfg(not(feature = "std"))]
use alloc::format;
use crate::order::Msb0;
assert_eq!(format!("{:?}", BitIdx::<u8>::LAST), "BitIdx<u8>(111)");
assert_eq!(format!("{:?}", BitIdx::<u16>::LAST), "BitIdx<u16>(1111)");
assert_eq!(format!("{:?}", BitIdx::<u32>::LAST), "BitIdx<u32>(11111)");
assert_eq!(
format!("{:?}", BitIdx::<u8>::new(8).unwrap_err()),
"BitIdxErr<u8>(8)",
);
assert_eq!(
format!("{:?}", BitIdx::<u16>::new(16).unwrap_err()),
"BitIdxErr<u16>(16)",
);
assert_eq!(
format!("{:?}", BitIdx::<u32>::new(32).unwrap_err()),
"BitIdxErr<u32>(32)",
);
assert_eq!(format!("{:?}", BitTail::<u8>::LAST), "BitTail<u8>(1000)");
assert_eq!(format!("{:?}", BitTail::<u16>::LAST), "BitTail<u16>(10000)");
assert_eq!(
format!("{:?}", BitTail::<u32>::LAST),
"BitTail<u32>(100000)",
);
assert_eq!(
format!("{:?}", BitIdx::<u8>::LAST.position::<Msb0>()),
"BitPos<u8>(000)",
);
assert_eq!(
format!("{:?}", BitIdx::<u16>::LAST.position::<Lsb0>()),
"BitPos<u16>(1111)",
);
assert_eq!(
format!("{:?}", BitIdx::<u32>::LAST.position::<Msb0>()),
"BitPos<u32>(00000)",
);
assert_eq!(
format!("{:?}", BitIdx::<u8>::LAST.select::<Msb0>()),
"BitSel<u8>(00000001)",
);
assert_eq!(
format!("{:?}", BitIdx::<u16>::LAST.select::<Lsb0>()),
"BitSel<u16>(1000000000000000)",
);
assert_eq!(
format!("{:?}", BitIdx::<u32>::LAST.select::<Msb0>()),
"BitSel<u32>(00000000000000000000000000000001)",
);
assert_eq!(
format!("{:?}", BitMask::<u8>::new(1 | 4 | 32)),
"BitMask<u8>(00100101)",
);
assert_eq!(
format!("{:?}", BitMask::<u16>::new(1 | 4 | 32)),
"BitMask<u16>(0000000000100101)",
);
assert_eq!(
format!("{:?}", BitMask::<u32>::new(1 | 4 | 32)),
"BitMask<u32>(00000000000000000000000000100101)",
);
#[cfg(target_pointer_width = "64")]
{
assert_eq!(
format!("{:?}", BitIdx::<u64>::LAST),
"BitIdx<u64>(111111)",
);
assert_eq!(
format!("{:?}", BitIdx::<u64>::new(64).unwrap_err()),
"BitIdxErr<u64>(64)",
);
assert_eq!(
format!("{:?}", BitTail::<u64>::LAST),
"BitTail<u64>(1000000)",
);
assert_eq!(
format!("{:?}", BitIdx::<u64>::LAST.position::<Lsb0>()),
"BitPos<u64>(111111)",
);
assert_eq!(
format!("{:?}",BitIdx::<u64>::LAST.select::<Lsb0>()),
"BitSel<u64>(1000000000000000000000000000000000000000000000000000000000000000)",
);
assert_eq!(
format!("{:?}", BitMask::<u64>::new(1 | 4 | 32)),
"BitMask<u64>(0000000000000000000000000000000000000000000000000000000000100101)",
);
}
}
}