hopper_core/abi/
integers.rs1use core::fmt;
4
5macro_rules! wire_int {
11 (
12 $(#[$meta:meta])*
13 $name:ident, $native:ty, $size:literal, $canonical:literal
14 ) => {
15 $(#[$meta])*
16 #[derive(Clone, Copy, PartialEq, Eq, Default)]
17 #[repr(transparent)]
18 pub struct $name([u8; $size]);
19
20 const _: () = assert!(core::mem::size_of::<$name>() == $size);
22 const _: () = assert!(core::mem::align_of::<$name>() == 1);
23
24 impl $name {
25 pub const ZERO: Self = Self([0u8; $size]);
27
28 pub const MAX: Self = Self(<$native>::MAX.to_le_bytes());
30
31 pub const MIN: Self = Self(<$native>::MIN.to_le_bytes());
33
34 #[inline(always)]
36 pub const fn new(v: $native) -> Self {
37 Self(v.to_le_bytes())
38 }
39
40 #[inline(always)]
42 pub const fn get(self) -> $native {
43 <$native>::from_le_bytes(self.0)
44 }
45
46 #[inline(always)]
48 pub fn set(&mut self, v: $native) {
49 self.0 = v.to_le_bytes();
50 }
51
52 #[inline(always)]
54 pub const fn as_bytes(&self) -> &[u8; $size] {
55 &self.0
56 }
57
58 #[inline(always)]
60 pub fn as_bytes_mut(&mut self) -> &mut [u8; $size] {
61 &mut self.0
62 }
63 }
64
65 impl From<$native> for $name {
66 #[inline(always)]
67 fn from(v: $native) -> Self {
68 Self::new(v)
69 }
70 }
71
72 impl From<$name> for $native {
73 #[inline(always)]
74 fn from(w: $name) -> Self {
75 w.get()
76 }
77 }
78
79 impl PartialOrd for $name {
80 #[inline(always)]
81 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
82 Some(self.cmp(other))
83 }
84 }
85
86 impl Ord for $name {
87 #[inline(always)]
88 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
89 self.get().cmp(&other.get())
90 }
91 }
92
93 impl fmt::Debug for $name {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "{}({})", stringify!($name), self.get())
96 }
97 }
98
99 impl fmt::Display for $name {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 write!(f, "{}", self.get())
102 }
103 }
104
105 unsafe impl crate::abi::WireType for $name {
107 const WIRE_SIZE: usize = $size;
108 const CANONICAL_NAME: &'static str = $canonical;
109 }
110
111 #[cfg(feature = "hopper-native-backend")]
117 unsafe impl ::hopper_runtime::__hopper_native::bytemuck::Zeroable for $name {}
118 #[cfg(feature = "hopper-native-backend")]
119 unsafe impl ::hopper_runtime::__hopper_native::bytemuck::Pod for $name {}
120
121 unsafe impl crate::account::Pod for $name {}
123
124 unsafe impl ::hopper_runtime::__sealed::HopperZeroCopySealed for $name {}
129
130 impl crate::account::FixedLayout for $name {
131 const SIZE: usize = $size;
132 }
133 };
134}
135
136wire_int!(
137 WireU16, u16, 2, "u16"
139);
140
141wire_int!(
142 WireU32, u32, 4, "u32"
144);
145
146wire_int!(
147 WireU64, u64, 8, "u64"
149);
150
151wire_int!(
152 WireU128, u128, 16, "u128"
154);
155
156wire_int!(
157 WireI16, i16, 2, "i16"
159);
160
161wire_int!(
162 WireI32, i32, 4, "i32"
164);
165
166wire_int!(
167 WireI64, i64, 8, "i64"
169);
170
171wire_int!(
172 WireI128, i128, 16, "i128"
174);
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn wire_u64_roundtrip() {
182 let w = WireU64::new(0xDEAD_BEEF_CAFE_BABE);
183 assert_eq!(w.get(), 0xDEAD_BEEF_CAFE_BABE);
184 }
185
186 #[test]
187 fn wire_i64_negative() {
188 let w = WireI64::new(-42);
189 assert_eq!(w.get(), -42);
190 }
191
192 #[test]
193 fn wire_ordering() {
194 let a = WireU32::new(10);
195 let b = WireU32::new(20);
196 assert!(a < b);
197 }
198
199 #[test]
200 fn wire_default_is_zero() {
201 let w = WireU64::default();
202 assert_eq!(w.get(), 0);
203 }
204}