use core::fmt;
macro_rules! wire_int {
(
$(#[$meta:meta])*
$name:ident, $native:ty, $size:literal, $canonical:literal
) => {
$(#[$meta])*
#[derive(Clone, Copy, PartialEq, Eq, Default)]
#[repr(transparent)]
pub struct $name([u8; $size]);
const _: () = assert!(core::mem::size_of::<$name>() == $size);
const _: () = assert!(core::mem::align_of::<$name>() == 1);
impl $name {
pub const ZERO: Self = Self([0u8; $size]);
pub const MAX: Self = Self(<$native>::MAX.to_le_bytes());
pub const MIN: Self = Self(<$native>::MIN.to_le_bytes());
#[inline(always)]
pub const fn new(v: $native) -> Self {
Self(v.to_le_bytes())
}
#[inline(always)]
pub const fn get(self) -> $native {
<$native>::from_le_bytes(self.0)
}
#[inline(always)]
pub fn set(&mut self, v: $native) {
self.0 = v.to_le_bytes();
}
#[inline(always)]
pub const fn as_bytes(&self) -> &[u8; $size] {
&self.0
}
#[inline(always)]
pub fn as_bytes_mut(&mut self) -> &mut [u8; $size] {
&mut self.0
}
}
impl From<$native> for $name {
#[inline(always)]
fn from(v: $native) -> Self {
Self::new(v)
}
}
impl From<$name> for $native {
#[inline(always)]
fn from(w: $name) -> Self {
w.get()
}
}
impl PartialOrd for $name {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for $name {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.get().cmp(&other.get())
}
}
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}({})", stringify!($name), self.get())
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.get())
}
}
unsafe impl crate::abi::WireType for $name {
const WIRE_SIZE: usize = $size;
const CANONICAL_NAME: &'static str = $canonical;
}
#[cfg(feature = "hopper-native-backend")]
unsafe impl ::hopper_runtime::__hopper_native::bytemuck::Zeroable for $name {}
#[cfg(feature = "hopper-native-backend")]
unsafe impl ::hopper_runtime::__hopper_native::bytemuck::Pod for $name {}
unsafe impl crate::account::Pod for $name {}
unsafe impl ::hopper_runtime::__sealed::HopperZeroCopySealed for $name {}
impl crate::account::FixedLayout for $name {
const SIZE: usize = $size;
}
};
}
wire_int!(
WireU16, u16, 2, "u16"
);
wire_int!(
WireU32, u32, 4, "u32"
);
wire_int!(
WireU64, u64, 8, "u64"
);
wire_int!(
WireU128, u128, 16, "u128"
);
wire_int!(
WireI16, i16, 2, "i16"
);
wire_int!(
WireI32, i32, 4, "i32"
);
wire_int!(
WireI64, i64, 8, "i64"
);
wire_int!(
WireI128, i128, 16, "i128"
);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn wire_u64_roundtrip() {
let w = WireU64::new(0xDEAD_BEEF_CAFE_BABE);
assert_eq!(w.get(), 0xDEAD_BEEF_CAFE_BABE);
}
#[test]
fn wire_i64_negative() {
let w = WireI64::new(-42);
assert_eq!(w.get(), -42);
}
#[test]
fn wire_ordering() {
let a = WireU32::new(10);
let b = WireU32::new(20);
assert!(a < b);
}
#[test]
fn wire_default_is_zero() {
let w = WireU64::default();
assert_eq!(w.get(), 0);
}
}