1use crate::account::{FixedLayout, Pod};
35
36macro_rules! impl_le_unsigned {
39 ($name:ident, $inner:ty, $size:literal) => {
40 #[doc = concat!("Alignment-1, little-endian `", stringify!($inner), "` for on-chain ABI fields.")]
41 #[repr(transparent)]
42 #[derive(Clone, Copy, PartialEq, Eq)]
43 pub struct $name(pub [u8; $size]);
44
45 const _: () = assert!(core::mem::size_of::<$name>() == $size);
46 const _: () = assert!(core::mem::align_of::<$name>() == 1);
47
48 impl $name {
49 pub const ZERO: Self = Self([0u8; $size]);
51
52 #[inline(always)]
54 pub const fn new(v: $inner) -> Self {
55 Self(v.to_le_bytes())
56 }
57
58 #[inline(always)]
60 pub const fn get(&self) -> $inner {
61 <$inner>::from_le_bytes(self.0)
62 }
63
64 #[inline(always)]
66 pub fn set(&mut self, v: $inner) {
67 self.0 = v.to_le_bytes();
68 }
69 }
70
71 impl Default for $name {
72 #[inline(always)]
73 fn default() -> Self {
74 Self::ZERO
75 }
76 }
77
78 impl core::fmt::Debug for $name {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 write!(f, "{}({})", stringify!($name), self.get())
81 }
82 }
83
84 impl core::fmt::Display for $name {
85 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
86 write!(f, "{}", self.get())
87 }
88 }
89
90 impl PartialOrd for $name {
91 #[inline(always)]
92 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
93 Some(self.cmp(other))
94 }
95 }
96
97 impl Ord for $name {
98 #[inline(always)]
99 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
100 self.get().cmp(&other.get())
101 }
102 }
103
104 impl From<$inner> for $name {
105 #[inline(always)]
106 fn from(v: $inner) -> Self {
107 Self::new(v)
108 }
109 }
110
111 impl From<$name> for $inner {
112 #[inline(always)]
113 fn from(v: $name) -> Self {
114 v.get()
115 }
116 }
117
118 unsafe impl Pod for $name {}
120 impl FixedLayout for $name {
121 const SIZE: usize = $size;
122 }
123 };
124}
125
126macro_rules! impl_le_signed {
129 ($name:ident, $inner:ty, $size:literal) => {
130 #[doc = concat!("Alignment-1, little-endian `", stringify!($inner), "` for on-chain ABI fields.")]
131 #[repr(transparent)]
132 #[derive(Clone, Copy, PartialEq, Eq)]
133 pub struct $name(pub [u8; $size]);
134
135 const _: () = assert!(core::mem::size_of::<$name>() == $size);
136 const _: () = assert!(core::mem::align_of::<$name>() == 1);
137
138 impl $name {
139 pub const ZERO: Self = Self([0u8; $size]);
141
142 #[inline(always)]
144 pub const fn new(v: $inner) -> Self {
145 Self(v.to_le_bytes())
146 }
147
148 #[inline(always)]
150 pub const fn get(&self) -> $inner {
151 <$inner>::from_le_bytes(self.0)
152 }
153
154 #[inline(always)]
156 pub fn set(&mut self, v: $inner) {
157 self.0 = v.to_le_bytes();
158 }
159 }
160
161 impl Default for $name {
162 #[inline(always)]
163 fn default() -> Self {
164 Self::ZERO
165 }
166 }
167
168 impl core::fmt::Debug for $name {
169 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
170 write!(f, "{}({})", stringify!($name), self.get())
171 }
172 }
173
174 impl core::fmt::Display for $name {
175 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
176 write!(f, "{}", self.get())
177 }
178 }
179
180 impl PartialOrd for $name {
181 #[inline(always)]
182 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
183 Some(self.cmp(other))
184 }
185 }
186
187 impl Ord for $name {
188 #[inline(always)]
189 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
190 self.get().cmp(&other.get())
191 }
192 }
193
194 impl From<$inner> for $name {
195 #[inline(always)]
196 fn from(v: $inner) -> Self {
197 Self::new(v)
198 }
199 }
200
201 impl From<$name> for $inner {
202 #[inline(always)]
203 fn from(v: $name) -> Self {
204 v.get()
205 }
206 }
207
208 unsafe impl Pod for $name {}
210 impl FixedLayout for $name {
211 const SIZE: usize = $size;
212 }
213 };
214}
215
216impl_le_unsigned!(LeU16, u16, 2);
219impl_le_unsigned!(LeU32, u32, 4);
220impl_le_unsigned!(LeU64, u64, 8);
221impl_le_unsigned!(LeU128, u128, 16);
222
223impl_le_signed!(LeI16, i16, 2);
226impl_le_signed!(LeI32, i32, 4);
227impl_le_signed!(LeI64, i64, 8);
228impl_le_signed!(LeI128, i128, 16);
229
230#[repr(transparent)]
236#[derive(Clone, Copy, PartialEq, Eq)]
237pub struct LeBool(pub [u8; 1]);
238
239const _: () = assert!(core::mem::size_of::<LeBool>() == 1);
240const _: () = assert!(core::mem::align_of::<LeBool>() == 1);
241
242impl LeBool {
243 pub const FALSE: Self = Self([0]);
245 pub const TRUE: Self = Self([1]);
247
248 #[inline(always)]
250 pub const fn new(v: bool) -> Self {
251 Self([v as u8])
252 }
253
254 #[inline(always)]
256 pub const fn get(&self) -> bool {
257 self.0[0] != 0
258 }
259
260 #[inline(always)]
262 pub fn set(&mut self, v: bool) {
263 self.0[0] = v as u8;
264 }
265}
266
267impl Default for LeBool {
268 #[inline(always)]
269 fn default() -> Self {
270 Self::FALSE
271 }
272}
273
274impl core::fmt::Debug for LeBool {
275 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
276 write!(f, "LeBool({})", self.get())
277 }
278}
279
280impl core::fmt::Display for LeBool {
281 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
282 write!(f, "{}", self.get())
283 }
284}
285
286impl From<bool> for LeBool {
287 #[inline(always)]
288 fn from(v: bool) -> Self {
289 Self::new(v)
290 }
291}
292
293impl From<LeBool> for bool {
294 #[inline(always)]
295 fn from(v: LeBool) -> Self {
296 v.get()
297 }
298}
299
300unsafe impl Pod for LeBool {}
302impl FixedLayout for LeBool {
303 const SIZE: usize = 1;
304}
305
306pub struct FieldRef<'a> {
313 data: &'a [u8],
314}
315
316impl<'a> FieldRef<'a> {
317 #[inline(always)]
319 pub const fn new(data: &'a [u8]) -> Self {
320 Self { data }
321 }
322
323 #[inline(always)]
325 pub const fn len(&self) -> usize {
326 self.data.len()
327 }
328
329 #[inline(always)]
331 pub const fn is_empty(&self) -> bool {
332 self.data.is_empty()
333 }
334
335 #[inline(always)]
337 pub const fn as_bytes(&self) -> &[u8] {
338 self.data
339 }
340
341 #[inline(always)]
345 pub fn read_address(&self) -> pinocchio::Address {
346 let mut addr = [0u8; 32];
347 addr.copy_from_slice(&self.data[..32]);
348 pinocchio::Address::from(addr)
349 }
350
351 #[inline(always)]
357 pub fn as_address(&self) -> &pinocchio::Address {
358 let ptr = self.data[..32].as_ptr() as *const pinocchio::Address;
361 unsafe { &*ptr }
362 }
363
364 #[inline(always)]
366 pub fn read_u64(&self) -> u64 {
367 u64::from_le_bytes([
368 self.data[0],
369 self.data[1],
370 self.data[2],
371 self.data[3],
372 self.data[4],
373 self.data[5],
374 self.data[6],
375 self.data[7],
376 ])
377 }
378
379 #[inline(always)]
381 pub fn read_u32(&self) -> u32 {
382 u32::from_le_bytes([self.data[0], self.data[1], self.data[2], self.data[3]])
383 }
384
385 #[inline(always)]
387 pub fn read_u16(&self) -> u16 {
388 u16::from_le_bytes([self.data[0], self.data[1]])
389 }
390
391 #[inline(always)]
393 pub fn read_u8(&self) -> u8 {
394 self.data[0]
395 }
396
397 #[inline(always)]
399 pub fn read_bool(&self) -> bool {
400 self.data[0] != 0
401 }
402
403 #[inline(always)]
405 pub fn read_i64(&self) -> i64 {
406 i64::from_le_bytes([
407 self.data[0],
408 self.data[1],
409 self.data[2],
410 self.data[3],
411 self.data[4],
412 self.data[5],
413 self.data[6],
414 self.data[7],
415 ])
416 }
417
418 #[inline(always)]
420 pub fn read_i32(&self) -> i32 {
421 i32::from_le_bytes([self.data[0], self.data[1], self.data[2], self.data[3]])
422 }
423
424 #[inline(always)]
426 pub fn read_i16(&self) -> i16 {
427 i16::from_le_bytes([self.data[0], self.data[1]])
428 }
429
430 #[inline(always)]
432 pub fn read_u128(&self) -> u128 {
433 u128::from_le_bytes([
434 self.data[0], self.data[1], self.data[2], self.data[3],
435 self.data[4], self.data[5], self.data[6], self.data[7],
436 self.data[8], self.data[9], self.data[10], self.data[11],
437 self.data[12], self.data[13], self.data[14], self.data[15],
438 ])
439 }
440
441 #[inline(always)]
443 pub fn read_i128(&self) -> i128 {
444 i128::from_le_bytes([
445 self.data[0], self.data[1], self.data[2], self.data[3],
446 self.data[4], self.data[5], self.data[6], self.data[7],
447 self.data[8], self.data[9], self.data[10], self.data[11],
448 self.data[12], self.data[13], self.data[14], self.data[15],
449 ])
450 }
451
452 #[inline(always)]
454 pub fn read_i8(&self) -> i8 {
455 self.data[0] as i8
456 }
457}
458
459pub struct FieldMut<'a> {
464 data: &'a mut [u8],
465}
466
467impl<'a> FieldMut<'a> {
468 #[inline(always)]
470 pub fn new(data: &'a mut [u8]) -> Self {
471 Self { data }
472 }
473
474 #[inline(always)]
476 pub fn len(&self) -> usize {
477 self.data.len()
478 }
479
480 #[inline(always)]
482 pub fn is_empty(&self) -> bool {
483 self.data.is_empty()
484 }
485
486 #[inline(always)]
488 pub fn as_bytes(&self) -> &[u8] {
489 self.data
490 }
491
492 #[inline(always)]
494 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
495 self.data
496 }
497
498 #[inline(always)]
500 pub fn read_address(&self) -> pinocchio::Address {
501 let mut addr = [0u8; 32];
502 addr.copy_from_slice(&self.data[..32]);
503 pinocchio::Address::from(addr)
504 }
505
506 #[inline(always)]
508 pub fn as_address(&self) -> &pinocchio::Address {
509 let ptr = self.data[..32].as_ptr() as *const pinocchio::Address;
511 unsafe { &*ptr }
512 }
513
514 #[inline(always)]
516 pub fn write_address(&mut self, addr: &pinocchio::Address) {
517 self.data[..32].copy_from_slice(addr.as_ref());
518 }
519
520 #[inline(always)]
522 pub fn write_u64(&mut self, v: u64) {
523 self.data[..8].copy_from_slice(&v.to_le_bytes());
524 }
525
526 #[inline(always)]
528 pub fn write_u32(&mut self, v: u32) {
529 self.data[..4].copy_from_slice(&v.to_le_bytes());
530 }
531
532 #[inline(always)]
534 pub fn write_u16(&mut self, v: u16) {
535 self.data[..2].copy_from_slice(&v.to_le_bytes());
536 }
537
538 #[inline(always)]
540 pub fn write_u8(&mut self, v: u8) {
541 self.data[0] = v;
542 }
543
544 #[inline(always)]
546 pub fn write_bool(&mut self, v: bool) {
547 self.data[0] = v as u8;
548 }
549
550 #[inline(always)]
552 pub fn write_i64(&mut self, v: i64) {
553 self.data[..8].copy_from_slice(&v.to_le_bytes());
554 }
555
556 #[inline(always)]
558 pub fn write_i32(&mut self, v: i32) {
559 self.data[..4].copy_from_slice(&v.to_le_bytes());
560 }
561
562 #[inline(always)]
564 pub fn write_i16(&mut self, v: i16) {
565 self.data[..2].copy_from_slice(&v.to_le_bytes());
566 }
567
568 #[inline(always)]
570 pub fn write_i8(&mut self, v: i8) {
571 self.data[0] = v as u8;
572 }
573
574 #[inline(always)]
576 pub fn write_u128(&mut self, v: u128) {
577 self.data[..16].copy_from_slice(&v.to_le_bytes());
578 }
579
580 #[inline(always)]
582 pub fn write_i128(&mut self, v: i128) {
583 self.data[..16].copy_from_slice(&v.to_le_bytes());
584 }
585
586 #[inline(always)]
588 pub fn read_u64(&self) -> u64 {
589 u64::from_le_bytes([
590 self.data[0],
591 self.data[1],
592 self.data[2],
593 self.data[3],
594 self.data[4],
595 self.data[5],
596 self.data[6],
597 self.data[7],
598 ])
599 }
600
601 #[inline(always)]
603 pub fn read_u32(&self) -> u32 {
604 u32::from_le_bytes([self.data[0], self.data[1], self.data[2], self.data[3]])
605 }
606
607 #[inline(always)]
609 pub fn read_u16(&self) -> u16 {
610 u16::from_le_bytes([self.data[0], self.data[1]])
611 }
612
613 #[inline(always)]
615 pub fn read_u8(&self) -> u8 {
616 self.data[0]
617 }
618
619 #[inline(always)]
621 pub fn read_bool(&self) -> bool {
622 self.data[0] != 0
623 }
624
625 #[inline(always)]
627 pub fn read_i64(&self) -> i64 {
628 i64::from_le_bytes([
629 self.data[0],
630 self.data[1],
631 self.data[2],
632 self.data[3],
633 self.data[4],
634 self.data[5],
635 self.data[6],
636 self.data[7],
637 ])
638 }
639
640 #[inline(always)]
642 pub fn read_i32(&self) -> i32 {
643 i32::from_le_bytes([self.data[0], self.data[1], self.data[2], self.data[3]])
644 }
645
646 #[inline(always)]
648 pub fn read_i16(&self) -> i16 {
649 i16::from_le_bytes([self.data[0], self.data[1]])
650 }
651
652 #[inline(always)]
654 pub fn read_i8(&self) -> i8 {
655 self.data[0] as i8
656 }
657
658 #[inline(always)]
660 pub fn read_u128(&self) -> u128 {
661 u128::from_le_bytes([
662 self.data[0], self.data[1], self.data[2], self.data[3],
663 self.data[4], self.data[5], self.data[6], self.data[7],
664 self.data[8], self.data[9], self.data[10], self.data[11],
665 self.data[12], self.data[13], self.data[14], self.data[15],
666 ])
667 }
668
669 #[inline(always)]
671 pub fn read_i128(&self) -> i128 {
672 i128::from_le_bytes([
673 self.data[0], self.data[1], self.data[2], self.data[3],
674 self.data[4], self.data[5], self.data[6], self.data[7],
675 self.data[8], self.data[9], self.data[10], self.data[11],
676 self.data[12], self.data[13], self.data[14], self.data[15],
677 ])
678 }
679
680 #[inline(always)]
682 pub fn copy_from(&mut self, src: &[u8]) {
683 self.data[..src.len()].copy_from_slice(src);
684 }
685}