holey-bytes/hbvm/src/value.rs

81 lines
2 KiB
Rust
Raw Normal View History

2023-06-24 17:18:31 -05:00
//! HoleyBytes register value definition
2023-06-24 17:16:14 -05:00
/// Define [`Value`] union
///
/// # Safety
/// Union variants have to be sound to byte-reinterpretate
/// between each other. Otherwise the behaviour is undefined.
macro_rules! value_def {
($($ty:ident),* $(,)?) => {
2023-06-24 17:16:14 -05:00
/// HBVM register value
#[derive(Copy, Clone)]
#[repr(packed)]
pub union Value {
2023-08-07 20:03:15 -05:00
$(
#[doc = concat!(stringify!($ty), " type")]
pub $ty: $ty
),*
}
$(
impl From<$ty> for Value {
#[inline]
fn from(value: $ty) -> Self {
Self { $ty: value }
}
}
2023-07-24 11:48:42 -05:00
2023-08-19 16:46:47 -05:00
crate::utils::static_assert_eq!(
2023-07-24 11:48:42 -05:00
core::mem::size_of::<$ty>(),
core::mem::size_of::<Value>(),
);
2023-08-19 16:24:31 -05:00
impl private::Sealed for $ty {}
2023-07-24 11:48:42 -05:00
unsafe impl ValueVariant for $ty {}
)*
};
}
2023-07-24 11:48:42 -05:00
impl Value {
2023-08-07 20:03:15 -05:00
/// Byte reinterpret value to target variant
2023-07-24 11:48:42 -05:00
#[inline]
2023-08-07 20:03:15 -05:00
pub fn cast<V: ValueVariant>(self) -> V {
/// Evil.
2023-08-19 16:24:31 -05:00
///
2023-08-07 20:03:15 -05:00
/// Transmute cannot be performed with generic type
/// as size is unknown, so union is used.
2023-08-19 16:24:31 -05:00
///
2023-08-07 20:03:15 -05:00
/// # Safety
/// If [`ValueVariant`] implemented correctly, it's fine :)
2023-08-19 16:24:31 -05:00
///
2023-08-07 20:03:15 -05:00
/// :ferrisClueless:
2023-07-24 11:48:42 -05:00
union Transmute<Variant: ValueVariant> {
2023-08-07 20:03:15 -05:00
/// Self
2023-07-24 11:48:42 -05:00
src: Value,
2023-08-07 20:03:15 -05:00
/// Target variant
2023-07-24 11:48:42 -05:00
variant: Variant,
}
unsafe { Transmute { src: self }.variant }
}
}
/// # Safety
/// - N/A, not to be implemented manually
2023-08-19 16:24:31 -05:00
pub unsafe trait ValueVariant: private::Sealed + Copy + Into<Value> {}
mod private {
pub trait Sealed {}
}
2023-07-24 11:48:42 -05:00
value_def!(u64, i64, f64);
2023-08-19 16:46:47 -05:00
crate::utils::static_assert_eq!(core::mem::size_of::<Value>(), 8);
2023-07-24 11:48:42 -05:00
impl core::fmt::Debug for Value {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2023-06-24 17:16:14 -05:00
// Print formatted as hexadecimal, unsigned integer
2023-07-24 11:48:42 -05:00
write!(f, "{:x}", self.cast::<u64>())
}
}