use const_panic::concat_assert;
#[cfg(target_has_atomic = "32")]
pub type UReg = u32;
#[cfg(all(target_has_atomic = "16", not(target_has_atomic = "32")))]
pub type UReg = u16;
#[cfg(all(target_has_atomic = "8", not(target_has_atomic = "16")))]
pub type UReg = u8;
pub const trait CastFromUReg {
fn cast_from(value: UReg) -> Self;
}
impl const CastFromUReg for bool {
fn cast_from(value: UReg) -> Self { value != 0 }
}
impl const CastFromUReg for u8 {
fn cast_from(value: UReg) -> Self { value as u8 }
}
impl const CastFromUReg for u16 {
fn cast_from(value: UReg) -> Self { value as u16 }
}
impl const CastFromUReg for u32 {
fn cast_from(value: UReg) -> Self { value as u32 }
}
pub const fn flag_mask(offset: u8) -> UReg {
0b1 << offset
}
pub const fn field_mask(offset: u8, length: u8) -> UReg {
group_mask(length) << offset
}
const fn group_mask(length: u8) -> UReg {
(0b1_u32.checked_shl(length as u32)).unwrap_or(0).wrapping_sub(1)
}
#[track_caller]
pub const fn assert_flag<Type>(offset: u8) {
let type_name = core::any::type_name::<Type>();
let type_bit_size = { core::mem::size_of::<Type>() * 8} as u8;
concat_assert!(offset < type_bit_size,
"\nBit Flag offset `", offset, "` overflows target type `", display:type_name,
"` (max offset: ", type_bit_size - 1, ")");
}
#[track_caller]
pub const fn assert_field<Type>(offset: u8, size: u8) {
let type_name = core::any::type_name::<Type>();
let type_bit_size = { core::mem::size_of::<Type>() * 8} as u8;
concat_assert!(offset < type_bit_size,
"\nBit Field offset `", offset, "` overflows target type `", display:type_name,
"` (max offset: ", type_bit_size - 1, ")");
let last_offset = offset + size - 1;
concat_assert!(last_offset < type_bit_size,
"\nBit Field size `", size, "` overflows target type `", display:type_name,
"` (max size at offset `", offset, "`: ", type_bit_size - offset, ")");
}
#[track_caller]
pub const fn assert_mask<Type>(size: u8) {
let type_bit_size = { core::mem::size_of::<Type>() * 8} as u8;
let type_name = core::any::type_name::<Type>();
concat_assert!(size <= type_bit_size,
"\nBit Mask size `", size, "` overflows target type `", display:type_name,
"` (max size: ", type_bit_size, ")");
}
#[track_caller]
pub const fn assert_size(size: u8) {
concat_assert!(size > 0, "\nBit Field size cannot be `0`");
}