mod cmp;
mod consts;
mod fmt;
mod ops;
use num_traits::{PrimInt, Unsigned};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct BitUint<T: Unsigned + PrimInt, const N: u32>(T);
macro_rules! impl_bit_uint {
($T:ty, $alias:ident) => {
impl<const N: u32> BitUint<$T, N> {
#[doc = concat!("let n = BitUint::<", stringify!($T), ", 6>::new(42);")]
#[doc = ""]
#[doc = concat!("let m = BitUint::<", stringify!($T), ", 5>::new(42);")]
#[must_use]
#[inline]
pub const fn new(n: $T) -> Option<Self> {
debug_assert!(n >= Self::MIN.get());
if n <= Self::MAX.get() {
let n = unsafe { Self::new_unchecked(n) };
Some(n)
} else {
None
}
}
}
#[doc = concat!("[`", stringify!($T), "`].")]
#[doc = concat!("The largest size of `N` is equal to [`", stringify!($T), "::BITS`].")]
pub type $alias<const N: u32> = BitUint<$T, N>;
};
}
impl_bit_uint!(u8, BitU8);
impl_bit_uint!(u16, BitU16);
impl_bit_uint!(u32, BitU32);
impl_bit_uint!(u64, BitU64);
impl_bit_uint!(u128, BitU128);
impl_bit_uint!(usize, BitUsize);
impl<T: Unsigned + PrimInt, const N: u32> BitUint<T, N> {
#[must_use]
#[inline]
pub const unsafe fn new_unchecked(n: T) -> Self {
Self(n)
}
#[must_use]
#[inline]
pub const fn get(self) -> T {
self.0
}
}
#[cfg(test)]
mod tests {
use core::{any, mem};
use super::*;
#[test]
fn alias() {
assert_eq!(
any::type_name::<BitU8::<7>>(),
any::type_name::<BitUint::<u8, 7>>()
);
assert_eq!(
any::type_name::<BitU16::<15>>(),
any::type_name::<BitUint::<u16, 15>>()
);
assert_eq!(
any::type_name::<BitU32::<31>>(),
any::type_name::<BitUint::<u32, 31>>()
);
assert_eq!(
any::type_name::<BitU64::<63>>(),
any::type_name::<BitUint::<u64, 63>>()
);
assert_eq!(
any::type_name::<BitU128::<127>>(),
any::type_name::<BitUint::<u128, 127>>()
);
assert_eq!(
any::type_name::<BitUsize::<31>>(),
any::type_name::<BitUint::<usize, 31>>()
);
}
#[test]
fn layout() {
assert_eq!(mem::size_of::<BitU32::<31>>(), mem::size_of::<u32>());
assert_eq!(mem::align_of::<BitU32::<31>>(), mem::align_of::<u32>());
}
#[test]
fn clone() {
assert_eq!(BitU32::<31>::MIN.clone(), BitU32::<31>::MIN);
}
#[test]
fn copy() {
let a = BitU32::<31>::MIN;
let b = a;
assert_eq!(a, b);
}
#[test]
fn default() {
assert_eq!(
BitU32::<31>::default(),
BitU32::<31>::new(u32::default()).unwrap()
);
}
#[test]
fn new() {
assert_eq!(
BitU8::<7>::new(u8::MAX >> 1).map(BitU8::get),
Some(u8::MAX >> 1)
);
assert_eq!(
BitU16::<15>::new(u16::MAX >> 1).map(BitU16::get),
Some(u16::MAX >> 1)
);
assert_eq!(
BitU32::<31>::new(u32::MAX >> 1).map(BitU32::get),
Some(u32::MAX >> 1)
);
assert_eq!(
BitU64::<63>::new(u64::MAX >> 1).map(BitU64::get),
Some(u64::MAX >> 1)
);
assert_eq!(
BitU128::<127>::new(u128::MAX >> 1).map(BitU128::get),
Some(u128::MAX >> 1)
);
}
#[test]
fn new_with_invalid_value() {
assert!(BitU8::<7>::new((u8::MAX >> 1) + 1).is_none());
assert!(BitU16::<15>::new((u16::MAX >> 1) + 1).is_none());
assert!(BitU32::<31>::new((u32::MAX >> 1) + 1).is_none());
assert!(BitU64::<63>::new((u64::MAX >> 1) + 1).is_none());
assert!(BitU128::<127>::new((u128::MAX >> 1) + 1).is_none());
}
#[test]
fn get() {
assert_eq!(BitU8::<7>::MAX.get(), u8::MAX >> 1);
assert_eq!(BitU16::<15>::MAX.get(), u16::MAX >> 1);
assert_eq!(BitU32::<31>::MAX.get(), u32::MAX >> 1);
assert_eq!(BitU64::<63>::MAX.get(), u64::MAX >> 1);
assert_eq!(BitU128::<127>::MAX.get(), u128::MAX >> 1);
}
}