pub trait TruncateNum {
fn truncated(self, bit_count: u8) -> Self;
fn lsb(self) -> u8;
}
macro_rules! unsigned_truncate {
($t:ty) => {
impl TruncateNum for $t {
fn truncated(self, bit_count: u8) -> Self {
self & !((!<$t>::MIN).checked_shl(bit_count.into()).unwrap_or(0))
}
fn lsb(self) -> u8 {
self as u8
}
}
};
}
unsigned_truncate!(u8);
unsigned_truncate!(u16);
unsigned_truncate!(u32);
unsigned_truncate!(u64);
unsigned_truncate!(usize);
impl TruncateNum for i64 {
fn truncated(self, bit_count: u8) -> Self {
let Some(ref_bit) = bit_count.checked_sub(1) else {
return 0;
};
let upper_bits = (!0i64).checked_shl(bit_count.into()).unwrap_or(0);
if self & (1 << ref_bit) == 0 {
self & !upper_bits
} else {
self | upper_bits
}
}
fn lsb(self) -> u8 {
self as u8
}
}