1use crate::project::Projectable;
25
26macro_rules! le_integer {
29 (
30 $(#[$meta:meta])*
31 $name:ident, $native:ty, $size:expr, unsigned
32 ) => {
33 $(#[$meta])*
34 #[repr(transparent)]
35 #[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
36 pub struct $name([u8; $size]);
37
38 impl $name {
39 pub const ZERO: Self = Self([0; $size]);
41
42 pub const MAX: Self = Self(<$native>::MAX.to_le_bytes());
44
45 #[inline(always)]
47 pub const fn new(v: $native) -> Self {
48 Self(v.to_le_bytes())
49 }
50
51 #[inline(always)]
53 pub const fn get(self) -> $native {
54 <$native>::from_le_bytes(self.0)
55 }
56
57 #[inline(always)]
59 pub const fn to_le_bytes(self) -> [u8; $size] {
60 self.0
61 }
62
63 #[inline(always)]
65 pub const fn from_le_bytes(bytes: [u8; $size]) -> Self {
66 Self(bytes)
67 }
68
69 #[inline(always)]
71 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
72 match self.get().checked_add(rhs.get()) {
73 Some(v) => Some(Self::new(v)),
74 None => None,
75 }
76 }
77
78 #[inline(always)]
80 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
81 match self.get().checked_sub(rhs.get()) {
82 Some(v) => Some(Self::new(v)),
83 None => None,
84 }
85 }
86
87 #[inline(always)]
89 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
90 match self.get().checked_mul(rhs.get()) {
91 Some(v) => Some(Self::new(v)),
92 None => None,
93 }
94 }
95
96 #[inline(always)]
98 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
99 match self.get().checked_div(rhs.get()) {
100 Some(v) => Some(Self::new(v)),
101 None => None,
102 }
103 }
104
105 #[inline(always)]
107 pub const fn saturating_add(self, rhs: Self) -> Self {
108 Self::new(self.get().saturating_add(rhs.get()))
109 }
110
111 #[inline(always)]
113 pub const fn saturating_sub(self, rhs: Self) -> Self {
114 Self::new(self.get().saturating_sub(rhs.get()))
115 }
116
117 #[inline(always)]
119 pub const fn wrapping_add(self, rhs: Self) -> Self {
120 Self::new(self.get().wrapping_add(rhs.get()))
121 }
122
123 #[inline(always)]
125 pub const fn wrapping_sub(self, rhs: Self) -> Self {
126 Self::new(self.get().wrapping_sub(rhs.get()))
127 }
128
129 #[inline(always)]
131 pub const fn is_zero(self) -> bool {
132 self.get() == 0
133 }
134 }
135
136 impl From<$native> for $name {
137 #[inline(always)]
138 fn from(v: $native) -> Self { Self::new(v) }
139 }
140
141 impl From<$name> for $native {
142 #[inline(always)]
143 fn from(v: $name) -> Self { v.get() }
144 }
145
146 impl PartialOrd for $name {
147 #[inline(always)]
148 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
149 Some(self.cmp(other))
150 }
151 }
152
153 impl Ord for $name {
154 #[inline(always)]
155 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
156 self.get().cmp(&other.get())
157 }
158 }
159
160 impl core::fmt::Debug for $name {
161 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
162 write!(f, "{}({})", stringify!($name), self.get())
163 }
164 }
165
166 impl core::fmt::Display for $name {
167 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
168 write!(f, "{}", self.get())
169 }
170 }
171
172 unsafe impl Projectable for $name {}
175 unsafe impl $crate::pod::Zeroable for $name {}
179 unsafe impl $crate::pod::Pod for $name {}
180
181 $crate::__wire_arith_ops!($name, $native);
182 };
183
184 (
186 $(#[$meta:meta])*
187 $name:ident, $native:ty, $size:expr, signed
188 ) => {
189 $(#[$meta])*
190 #[repr(transparent)]
191 #[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
192 pub struct $name([u8; $size]);
193
194 impl $name {
195 pub const ZERO: Self = Self([0; $size]);
197
198 pub const MAX: Self = Self(<$native>::MAX.to_le_bytes());
200
201 pub const MIN: Self = Self(<$native>::MIN.to_le_bytes());
203
204 #[inline(always)]
206 pub const fn new(v: $native) -> Self {
207 Self(v.to_le_bytes())
208 }
209
210 #[inline(always)]
212 pub const fn get(self) -> $native {
213 <$native>::from_le_bytes(self.0)
214 }
215
216 #[inline(always)]
218 pub const fn to_le_bytes(self) -> [u8; $size] {
219 self.0
220 }
221
222 #[inline(always)]
224 pub const fn from_le_bytes(bytes: [u8; $size]) -> Self {
225 Self(bytes)
226 }
227
228 #[inline(always)]
230 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
231 match self.get().checked_add(rhs.get()) {
232 Some(v) => Some(Self::new(v)),
233 None => None,
234 }
235 }
236
237 #[inline(always)]
239 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
240 match self.get().checked_sub(rhs.get()) {
241 Some(v) => Some(Self::new(v)),
242 None => None,
243 }
244 }
245
246 #[inline(always)]
248 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
249 match self.get().checked_mul(rhs.get()) {
250 Some(v) => Some(Self::new(v)),
251 None => None,
252 }
253 }
254
255 #[inline(always)]
257 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
258 match self.get().checked_div(rhs.get()) {
259 Some(v) => Some(Self::new(v)),
260 None => None,
261 }
262 }
263
264 #[inline(always)]
266 pub const fn saturating_add(self, rhs: Self) -> Self {
267 Self::new(self.get().saturating_add(rhs.get()))
268 }
269
270 #[inline(always)]
272 pub const fn saturating_sub(self, rhs: Self) -> Self {
273 Self::new(self.get().saturating_sub(rhs.get()))
274 }
275
276 #[inline(always)]
278 pub const fn is_zero(self) -> bool {
279 self.get() == 0
280 }
281
282 #[inline(always)]
284 pub const fn is_negative(self) -> bool {
285 self.get() < 0
286 }
287
288 #[inline(always)]
290 pub const fn abs(self) -> Self {
291 Self::new(self.get().wrapping_abs())
292 }
293 }
294
295 impl From<$native> for $name {
296 #[inline(always)]
297 fn from(v: $native) -> Self { Self::new(v) }
298 }
299
300 impl From<$name> for $native {
301 #[inline(always)]
302 fn from(v: $name) -> Self { v.get() }
303 }
304
305 impl PartialOrd for $name {
306 #[inline(always)]
307 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
308 Some(self.cmp(other))
309 }
310 }
311
312 impl Ord for $name {
313 #[inline(always)]
314 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
315 self.get().cmp(&other.get())
316 }
317 }
318
319 impl core::fmt::Debug for $name {
320 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
321 write!(f, "{}({})", stringify!($name), self.get())
322 }
323 }
324
325 impl core::fmt::Display for $name {
326 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
327 write!(f, "{}", self.get())
328 }
329 }
330
331 unsafe impl Projectable for $name {}
332 unsafe impl $crate::pod::Zeroable for $name {}
335 unsafe impl $crate::pod::Pod for $name {}
336
337 $crate::__wire_arith_ops!($name, $native);
338 };
339}
340
341#[doc(hidden)]
347#[macro_export]
348macro_rules! __wire_arith_ops {
349 ($name:ident, $native:ty) => {
350 impl core::ops::Add for $name {
351 type Output = Self;
352 #[inline(always)]
353 fn add(self, rhs: Self) -> Self {
354 Self::new(self.get() + rhs.get())
355 }
356 }
357 impl core::ops::Sub for $name {
358 type Output = Self;
359 #[inline(always)]
360 fn sub(self, rhs: Self) -> Self {
361 Self::new(self.get() - rhs.get())
362 }
363 }
364 impl core::ops::Mul for $name {
365 type Output = Self;
366 #[inline(always)]
367 fn mul(self, rhs: Self) -> Self {
368 Self::new(self.get() * rhs.get())
369 }
370 }
371 impl core::ops::Div for $name {
372 type Output = Self;
373 #[inline(always)]
374 fn div(self, rhs: Self) -> Self {
375 Self::new(self.get() / rhs.get())
376 }
377 }
378 impl core::ops::Rem for $name {
379 type Output = Self;
380 #[inline(always)]
381 fn rem(self, rhs: Self) -> Self {
382 Self::new(self.get() % rhs.get())
383 }
384 }
385 impl core::ops::Add<$native> for $name {
386 type Output = Self;
387 #[inline(always)]
388 fn add(self, rhs: $native) -> Self {
389 Self::new(self.get() + rhs)
390 }
391 }
392 impl core::ops::Sub<$native> for $name {
393 type Output = Self;
394 #[inline(always)]
395 fn sub(self, rhs: $native) -> Self {
396 Self::new(self.get() - rhs)
397 }
398 }
399 impl core::ops::Mul<$native> for $name {
400 type Output = Self;
401 #[inline(always)]
402 fn mul(self, rhs: $native) -> Self {
403 Self::new(self.get() * rhs)
404 }
405 }
406 impl core::ops::Div<$native> for $name {
407 type Output = Self;
408 #[inline(always)]
409 fn div(self, rhs: $native) -> Self {
410 Self::new(self.get() / rhs)
411 }
412 }
413 impl core::ops::Rem<$native> for $name {
414 type Output = Self;
415 #[inline(always)]
416 fn rem(self, rhs: $native) -> Self {
417 Self::new(self.get() % rhs)
418 }
419 }
420 impl core::ops::AddAssign for $name {
421 #[inline(always)]
422 fn add_assign(&mut self, rhs: Self) {
423 *self = *self + rhs;
424 }
425 }
426 impl core::ops::SubAssign for $name {
427 #[inline(always)]
428 fn sub_assign(&mut self, rhs: Self) {
429 *self = *self - rhs;
430 }
431 }
432 impl core::ops::MulAssign for $name {
433 #[inline(always)]
434 fn mul_assign(&mut self, rhs: Self) {
435 *self = *self * rhs;
436 }
437 }
438 impl core::ops::DivAssign for $name {
439 #[inline(always)]
440 fn div_assign(&mut self, rhs: Self) {
441 *self = *self / rhs;
442 }
443 }
444 impl core::ops::RemAssign for $name {
445 #[inline(always)]
446 fn rem_assign(&mut self, rhs: Self) {
447 *self = *self % rhs;
448 }
449 }
450 impl core::ops::AddAssign<$native> for $name {
451 #[inline(always)]
452 fn add_assign(&mut self, rhs: $native) {
453 *self = *self + rhs;
454 }
455 }
456 impl core::ops::SubAssign<$native> for $name {
457 #[inline(always)]
458 fn sub_assign(&mut self, rhs: $native) {
459 *self = *self - rhs;
460 }
461 }
462 impl core::ops::MulAssign<$native> for $name {
463 #[inline(always)]
464 fn mul_assign(&mut self, rhs: $native) {
465 *self = *self * rhs;
466 }
467 }
468 impl core::ops::DivAssign<$native> for $name {
469 #[inline(always)]
470 fn div_assign(&mut self, rhs: $native) {
471 *self = *self / rhs;
472 }
473 }
474 impl core::ops::RemAssign<$native> for $name {
475 #[inline(always)]
476 fn rem_assign(&mut self, rhs: $native) {
477 *self = *self % rhs;
478 }
479 }
480 impl PartialEq<$native> for $name {
481 #[inline(always)]
482 fn eq(&self, other: &$native) -> bool {
483 self.get() == *other
484 }
485 }
486 impl PartialOrd<$native> for $name {
487 #[inline(always)]
488 fn partial_cmp(&self, other: &$native) -> Option<core::cmp::Ordering> {
489 Some(self.get().cmp(other))
490 }
491 }
492 };
493}
494
495le_integer! {
498 LeU64, u64, 8, unsigned
504}
505
506le_integer! {
507 LeU32, u32, 4, unsigned
509}
510
511le_integer! {
512 LeU16, u16, 2, unsigned
514}
515
516le_integer! {
519 LeI64, i64, 8, signed
524}
525
526le_integer! {
527 LeI32, i32, 4, signed
529}
530
531le_integer! {
532 LeI16, i16, 2, signed
534}
535
536#[repr(transparent)]
544#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
545pub struct LeBool(u8);
546
547impl LeBool {
548 pub const TRUE: Self = Self(1);
550
551 pub const FALSE: Self = Self(0);
553
554 #[inline(always)]
556 pub const fn new(v: bool) -> Self {
557 Self(v as u8)
558 }
559
560 #[inline(always)]
562 pub const fn get(self) -> bool {
563 self.0 != 0
564 }
565
566 #[inline(always)]
568 pub const fn raw(self) -> u8 {
569 self.0
570 }
571
572 #[inline(always)]
577 pub const fn is_canonical(self) -> bool {
578 self.0 == 0 || self.0 == 1
579 }
580}
581
582impl From<bool> for LeBool {
583 #[inline(always)]
584 fn from(v: bool) -> Self {
585 Self::new(v)
586 }
587}
588
589impl From<LeBool> for bool {
590 #[inline(always)]
591 fn from(v: LeBool) -> Self {
592 v.get()
593 }
594}
595
596impl core::fmt::Debug for LeBool {
597 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
598 write!(f, "LeBool({})", self.get())
599 }
600}
601
602impl core::fmt::Display for LeBool {
603 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
604 write!(f, "{}", self.get())
605 }
606}
607
608unsafe impl Projectable for LeBool {}
611unsafe impl crate::pod::Zeroable for LeBool {}
613unsafe impl crate::pod::Pod for LeBool {}
614
615#[repr(transparent)]
622#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
623pub struct LeU128([u8; 16]);
624
625impl LeU128 {
626 pub const ZERO: Self = Self([0; 16]);
627 pub const MAX: Self = Self(u128::MAX.to_le_bytes());
628
629 #[inline(always)]
630 pub const fn new(v: u128) -> Self {
631 Self(v.to_le_bytes())
632 }
633
634 #[inline(always)]
635 pub const fn get(self) -> u128 {
636 u128::from_le_bytes(self.0)
637 }
638
639 #[inline(always)]
640 pub const fn to_le_bytes(self) -> [u8; 16] {
641 self.0
642 }
643
644 #[inline(always)]
645 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
646 match self.get().checked_add(rhs.get()) {
647 Some(v) => Some(Self::new(v)),
648 None => None,
649 }
650 }
651
652 #[inline(always)]
653 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
654 match self.get().checked_sub(rhs.get()) {
655 Some(v) => Some(Self::new(v)),
656 None => None,
657 }
658 }
659
660 #[inline(always)]
661 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
662 match self.get().checked_mul(rhs.get()) {
663 Some(v) => Some(Self::new(v)),
664 None => None,
665 }
666 }
667
668 #[inline(always)]
669 pub const fn saturating_add(self, rhs: Self) -> Self {
670 Self::new(self.get().saturating_add(rhs.get()))
671 }
672
673 #[inline(always)]
674 pub const fn saturating_sub(self, rhs: Self) -> Self {
675 Self::new(self.get().saturating_sub(rhs.get()))
676 }
677
678 #[inline(always)]
679 pub const fn is_zero(self) -> bool {
680 self.get() == 0
681 }
682}
683
684impl From<u128> for LeU128 {
685 #[inline(always)]
686 fn from(v: u128) -> Self {
687 Self::new(v)
688 }
689}
690
691impl From<LeU128> for u128 {
692 #[inline(always)]
693 fn from(v: LeU128) -> Self {
694 v.get()
695 }
696}
697
698impl PartialOrd for LeU128 {
699 #[inline(always)]
700 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
701 Some(self.cmp(other))
702 }
703}
704
705impl Ord for LeU128 {
706 #[inline(always)]
707 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
708 self.get().cmp(&other.get())
709 }
710}
711
712impl core::fmt::Debug for LeU128 {
713 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
714 write!(f, "LeU128({})", self.get())
715 }
716}
717
718impl core::fmt::Display for LeU128 {
719 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
720 write!(f, "{}", self.get())
721 }
722}
723
724unsafe impl Projectable for LeU128 {}
725unsafe impl crate::pod::Zeroable for LeU128 {}
728unsafe impl crate::pod::Pod for LeU128 {}
729
730__wire_arith_ops!(LeU128, u128);
731
732#[cfg(test)]
733mod tests {
734 use super::*;
735
736 fn require_pod<T: crate::pod::Pod>() {}
737
738 #[test]
742 fn wire_types_satisfy_substrate_pod() {
743 require_pod::<LeU64>();
744 require_pod::<LeU32>();
745 require_pod::<LeU16>();
746 require_pod::<LeI64>();
747 require_pod::<LeI32>();
748 require_pod::<LeI16>();
749 require_pod::<LeBool>();
750 require_pod::<LeU128>();
751 }
752
753 #[test]
754 fn wire_roundtrip_and_checked_math() {
755 let a = LeU64::new(u64::MAX - 1);
756 assert_eq!(a.get(), u64::MAX - 1);
757 assert_eq!(a.checked_add(LeU64::new(1)), Some(LeU64::MAX));
758 assert_eq!(LeU64::MAX.checked_add(LeU64::new(1)), None);
759 assert_eq!(LeU64::ZERO.checked_sub(LeU64::new(1)), None);
760 assert!(LeBool::new(true).get());
761 assert!(!LeBool::FALSE.get());
762 assert!(LeBool::TRUE.is_canonical());
763 }
764}