use core::mem;
use funty::IsUnsigned;
use radium::marker::BitOps;
pub trait BitMemory: IsUnsigned + seal::Sealed {
const INDX: u8 = Self::BITS.trailing_zeros() as u8;
const MASK: u8 = Self::BITS as u8 - 1;
}
pub trait BitRegister: BitMemory + BitOps {
const ONE: Self;
const ALL: Self;
}
macro_rules! memory {
($($t:ident),+ $(,)?) => { $(
impl BitMemory for $t {}
impl seal::Sealed for $t {}
)+ };
}
memory!(u8, u16, u32, u64, u128, usize);
macro_rules! register {
($($t:ident),+ $(,)?) => { $(
impl BitRegister for $t {
const ONE: Self = 1;
const ALL: Self = !0;
}
)+ };
}
register!(u8, u16, u32);
#[cfg(target_pointer_width = "64")]
impl BitRegister for u64 {
const ALL: Self = !0;
const ONE: Self = 1;
}
register!(usize);
#[doc(hidden)]
pub const fn elts<T>(bits: usize) -> usize {
let width = mem::size_of::<T>() * 8;
bits / width + (bits % width != 0) as usize
}
#[doc(hidden)]
pub(crate) const fn aligned_to_size<T>() -> usize {
(mem::align_of::<T>() < mem::size_of::<T>()) as usize
}
#[doc(hidden)]
pub(crate) const fn cmp_layout<A, B>() -> usize {
(mem::align_of::<A>() != mem::align_of::<B>()) as usize
+ (mem::size_of::<A>() != mem::size_of::<B>()) as usize
}
#[doc(hidden)]
mod seal {
#[doc(hidden)]
pub trait Sealed {}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::access::*;
#[test]
fn integer_properties() {
assert_eq!(aligned_to_size::<u8>(), 0);
assert_eq!(aligned_to_size::<BitSafeU8>(), 0);
assert_eq!(cmp_layout::<u8, BitSafeU8>(), 0);
assert_eq!(aligned_to_size::<u16>(), 0);
assert_eq!(aligned_to_size::<BitSafeU16>(), 0);
assert_eq!(cmp_layout::<u16, BitSafeU16>(), 0);
assert_eq!(aligned_to_size::<u32>(), 0);
assert_eq!(aligned_to_size::<BitSafeU32>(), 0);
assert_eq!(cmp_layout::<u32, BitSafeU32>(), 0);
assert_eq!(aligned_to_size::<usize>(), 0);
assert_eq!(aligned_to_size::<BitSafeUsize>(), 0);
assert_eq!(cmp_layout::<usize, BitSafeUsize>(), 0);
#[cfg(target_pointer_width = "64")]
{
assert_eq!(aligned_to_size::<u64>(), 0);
assert_eq!(aligned_to_size::<BitSafeU64>(), 0);
assert_eq!(cmp_layout::<u64, BitSafeU64>(), 0);
}
}
}