use std::num::NonZeroU8;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
#[repr(packed(1))]
pub struct ScalarInt {
pub data: u128,
pub size: NonZeroU8,
}
impl ScalarInt {
#[inline]
pub fn size(self) -> u64 {
self.size.get().into()
}
#[inline]
pub fn try_from_int(i: impl Into<i128>, size_in_bytes: u64) -> Option<Self> {
let i = i.into();
let truncated = truncate(size_in_bytes, i as u128);
if sign_extend(size_in_bytes, truncated) as i128 == i {
Some(Self {
data: truncated,
size: NonZeroU8::new(size_in_bytes as u8).unwrap(),
})
} else {
None
}
}
}
#[inline]
pub fn sign_extend(size: u64, value: u128) -> u128 {
let size = size * 8;
if size == 0 {
return 0;
}
let shift = 128 - size;
(((value << shift) as i128) >> shift) as u128
}
#[inline]
pub fn truncate(size: u64, value: u128) -> u128 {
let size = size * 8;
if size == 0 {
return 0;
}
let shift = 128 - size;
(value << shift) >> shift
}