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 if $size == 8 && <$native>::MIN == 0 {
97 match $crate::arith::checked_mul_u64(self.get() as u64, rhs.get() as u64) {
98 Some(v) => Some(Self::new(v as $native)),
99 None => None,
100 }
101 } else {
102 match self.get().checked_mul(rhs.get()) {
103 Some(v) => Some(Self::new(v)),
104 None => None,
105 }
106 }
107 }
108
109 #[inline(always)]
111 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
112 match self.get().checked_div(rhs.get()) {
113 Some(v) => Some(Self::new(v)),
114 None => None,
115 }
116 }
117
118 #[inline(always)]
120 pub const fn saturating_add(self, rhs: Self) -> Self {
121 Self::new(self.get().saturating_add(rhs.get()))
122 }
123
124 #[inline(always)]
126 pub const fn saturating_sub(self, rhs: Self) -> Self {
127 Self::new(self.get().saturating_sub(rhs.get()))
128 }
129
130 #[inline(always)]
132 pub const fn wrapping_add(self, rhs: Self) -> Self {
133 Self::new(self.get().wrapping_add(rhs.get()))
134 }
135
136 #[inline(always)]
138 pub const fn wrapping_sub(self, rhs: Self) -> Self {
139 Self::new(self.get().wrapping_sub(rhs.get()))
140 }
141
142 #[inline(always)]
144 pub const fn is_zero(self) -> bool {
145 self.get() == 0
146 }
147 }
148
149 impl From<$native> for $name {
150 #[inline(always)]
151 fn from(v: $native) -> Self { Self::new(v) }
152 }
153
154 impl From<$name> for $native {
155 #[inline(always)]
156 fn from(v: $name) -> Self { v.get() }
157 }
158
159 impl PartialOrd for $name {
160 #[inline(always)]
161 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
162 Some(self.cmp(other))
163 }
164 }
165
166 impl Ord for $name {
167 #[inline(always)]
168 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
169 self.get().cmp(&other.get())
170 }
171 }
172
173 impl core::fmt::Debug for $name {
174 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175 write!(f, "{}({})", stringify!($name), self.get())
176 }
177 }
178
179 impl core::fmt::Display for $name {
180 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181 write!(f, "{}", self.get())
182 }
183 }
184
185 unsafe impl Projectable for $name {}
188 unsafe impl $crate::pod::Zeroable for $name {}
192 unsafe impl $crate::pod::Pod for $name {}
193
194 $crate::__wire_arith_ops!($name, $native);
195 };
196
197 (
199 $(#[$meta:meta])*
200 $name:ident, $native:ty, $size:expr, signed
201 ) => {
202 $(#[$meta])*
203 #[repr(transparent)]
204 #[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
205 pub struct $name([u8; $size]);
206
207 impl $name {
208 pub const ZERO: Self = Self([0; $size]);
210
211 pub const MAX: Self = Self(<$native>::MAX.to_le_bytes());
213
214 pub const MIN: Self = Self(<$native>::MIN.to_le_bytes());
216
217 #[inline(always)]
219 pub const fn new(v: $native) -> Self {
220 Self(v.to_le_bytes())
221 }
222
223 #[inline(always)]
225 pub const fn get(self) -> $native {
226 <$native>::from_le_bytes(self.0)
227 }
228
229 #[inline(always)]
231 pub const fn to_le_bytes(self) -> [u8; $size] {
232 self.0
233 }
234
235 #[inline(always)]
237 pub const fn from_le_bytes(bytes: [u8; $size]) -> Self {
238 Self(bytes)
239 }
240
241 #[inline(always)]
243 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
244 match self.get().checked_add(rhs.get()) {
245 Some(v) => Some(Self::new(v)),
246 None => None,
247 }
248 }
249
250 #[inline(always)]
252 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
253 match self.get().checked_sub(rhs.get()) {
254 Some(v) => Some(Self::new(v)),
255 None => None,
256 }
257 }
258
259 #[inline(always)]
261 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
262 if $size == 8 && <$native>::MIN == 0 {
269 match $crate::arith::checked_mul_u64(self.get() as u64, rhs.get() as u64) {
270 Some(v) => Some(Self::new(v as $native)),
271 None => None,
272 }
273 } else {
274 match self.get().checked_mul(rhs.get()) {
275 Some(v) => Some(Self::new(v)),
276 None => None,
277 }
278 }
279 }
280
281 #[inline(always)]
283 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
284 match self.get().checked_div(rhs.get()) {
285 Some(v) => Some(Self::new(v)),
286 None => None,
287 }
288 }
289
290 #[inline(always)]
292 pub const fn saturating_add(self, rhs: Self) -> Self {
293 Self::new(self.get().saturating_add(rhs.get()))
294 }
295
296 #[inline(always)]
298 pub const fn saturating_sub(self, rhs: Self) -> Self {
299 Self::new(self.get().saturating_sub(rhs.get()))
300 }
301
302 #[inline(always)]
304 pub const fn is_zero(self) -> bool {
305 self.get() == 0
306 }
307
308 #[inline(always)]
310 pub const fn is_negative(self) -> bool {
311 self.get() < 0
312 }
313
314 #[inline(always)]
316 pub const fn abs(self) -> Self {
317 Self::new(self.get().wrapping_abs())
318 }
319 }
320
321 impl From<$native> for $name {
322 #[inline(always)]
323 fn from(v: $native) -> Self { Self::new(v) }
324 }
325
326 impl From<$name> for $native {
327 #[inline(always)]
328 fn from(v: $name) -> Self { v.get() }
329 }
330
331 impl PartialOrd for $name {
332 #[inline(always)]
333 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
334 Some(self.cmp(other))
335 }
336 }
337
338 impl Ord for $name {
339 #[inline(always)]
340 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
341 self.get().cmp(&other.get())
342 }
343 }
344
345 impl core::fmt::Debug for $name {
346 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
347 write!(f, "{}({})", stringify!($name), self.get())
348 }
349 }
350
351 impl core::fmt::Display for $name {
352 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
353 write!(f, "{}", self.get())
354 }
355 }
356
357 unsafe impl Projectable for $name {}
358 unsafe impl $crate::pod::Zeroable for $name {}
361 unsafe impl $crate::pod::Pod for $name {}
362
363 $crate::__wire_arith_ops!($name, $native);
364 };
365}
366
367#[doc(hidden)]
373#[macro_export]
374macro_rules! __wire_arith_ops {
375 ($name:ident, $native:ty) => {
376 impl core::ops::Add for $name {
377 type Output = Self;
378 #[inline(always)]
379 fn add(self, rhs: Self) -> Self {
380 Self::new(self.get() + rhs.get())
381 }
382 }
383 impl core::ops::Sub for $name {
384 type Output = Self;
385 #[inline(always)]
386 fn sub(self, rhs: Self) -> Self {
387 Self::new(self.get() - rhs.get())
388 }
389 }
390 impl core::ops::Mul for $name {
391 type Output = Self;
392 #[inline(always)]
393 fn mul(self, rhs: Self) -> Self {
394 Self::new(self.get() * rhs.get())
395 }
396 }
397 impl core::ops::Div for $name {
398 type Output = Self;
399 #[inline(always)]
400 fn div(self, rhs: Self) -> Self {
401 Self::new(self.get() / rhs.get())
402 }
403 }
404 impl core::ops::Rem for $name {
405 type Output = Self;
406 #[inline(always)]
407 fn rem(self, rhs: Self) -> Self {
408 Self::new(self.get() % rhs.get())
409 }
410 }
411 impl core::ops::Add<$native> for $name {
412 type Output = Self;
413 #[inline(always)]
414 fn add(self, rhs: $native) -> Self {
415 Self::new(self.get() + rhs)
416 }
417 }
418 impl core::ops::Sub<$native> for $name {
419 type Output = Self;
420 #[inline(always)]
421 fn sub(self, rhs: $native) -> Self {
422 Self::new(self.get() - rhs)
423 }
424 }
425 impl core::ops::Mul<$native> for $name {
426 type Output = Self;
427 #[inline(always)]
428 fn mul(self, rhs: $native) -> Self {
429 Self::new(self.get() * rhs)
430 }
431 }
432 impl core::ops::Div<$native> for $name {
433 type Output = Self;
434 #[inline(always)]
435 fn div(self, rhs: $native) -> Self {
436 Self::new(self.get() / rhs)
437 }
438 }
439 impl core::ops::Rem<$native> for $name {
440 type Output = Self;
441 #[inline(always)]
442 fn rem(self, rhs: $native) -> Self {
443 Self::new(self.get() % rhs)
444 }
445 }
446 impl core::ops::AddAssign for $name {
447 #[inline(always)]
448 fn add_assign(&mut self, rhs: Self) {
449 *self = *self + rhs;
450 }
451 }
452 impl core::ops::SubAssign for $name {
453 #[inline(always)]
454 fn sub_assign(&mut self, rhs: Self) {
455 *self = *self - rhs;
456 }
457 }
458 impl core::ops::MulAssign for $name {
459 #[inline(always)]
460 fn mul_assign(&mut self, rhs: Self) {
461 *self = *self * rhs;
462 }
463 }
464 impl core::ops::DivAssign for $name {
465 #[inline(always)]
466 fn div_assign(&mut self, rhs: Self) {
467 *self = *self / rhs;
468 }
469 }
470 impl core::ops::RemAssign for $name {
471 #[inline(always)]
472 fn rem_assign(&mut self, rhs: Self) {
473 *self = *self % rhs;
474 }
475 }
476 impl core::ops::AddAssign<$native> for $name {
477 #[inline(always)]
478 fn add_assign(&mut self, rhs: $native) {
479 *self = *self + rhs;
480 }
481 }
482 impl core::ops::SubAssign<$native> for $name {
483 #[inline(always)]
484 fn sub_assign(&mut self, rhs: $native) {
485 *self = *self - rhs;
486 }
487 }
488 impl core::ops::MulAssign<$native> for $name {
489 #[inline(always)]
490 fn mul_assign(&mut self, rhs: $native) {
491 *self = *self * rhs;
492 }
493 }
494 impl core::ops::DivAssign<$native> for $name {
495 #[inline(always)]
496 fn div_assign(&mut self, rhs: $native) {
497 *self = *self / rhs;
498 }
499 }
500 impl core::ops::RemAssign<$native> for $name {
501 #[inline(always)]
502 fn rem_assign(&mut self, rhs: $native) {
503 *self = *self % rhs;
504 }
505 }
506 impl PartialEq<$native> for $name {
507 #[inline(always)]
508 fn eq(&self, other: &$native) -> bool {
509 self.get() == *other
510 }
511 }
512 impl PartialOrd<$native> for $name {
513 #[inline(always)]
514 fn partial_cmp(&self, other: &$native) -> Option<core::cmp::Ordering> {
515 Some(self.get().cmp(other))
516 }
517 }
518 };
519}
520
521le_integer! {
524 LeU64, u64, 8, unsigned
530}
531
532le_integer! {
533 LeU32, u32, 4, unsigned
535}
536
537le_integer! {
538 LeU16, u16, 2, unsigned
540}
541
542le_integer! {
545 LeI64, i64, 8, signed
550}
551
552le_integer! {
553 LeI32, i32, 4, signed
555}
556
557le_integer! {
558 LeI16, i16, 2, signed
560}
561
562#[repr(transparent)]
570#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
571pub struct LeBool(u8);
572
573impl LeBool {
574 pub const TRUE: Self = Self(1);
576
577 pub const FALSE: Self = Self(0);
579
580 #[inline(always)]
582 pub const fn new(v: bool) -> Self {
583 Self(v as u8)
584 }
585
586 #[inline(always)]
588 pub const fn get(self) -> bool {
589 self.0 != 0
590 }
591
592 #[inline(always)]
594 pub const fn raw(self) -> u8 {
595 self.0
596 }
597
598 #[inline(always)]
603 pub const fn is_canonical(self) -> bool {
604 self.0 == 0 || self.0 == 1
605 }
606}
607
608impl From<bool> for LeBool {
609 #[inline(always)]
610 fn from(v: bool) -> Self {
611 Self::new(v)
612 }
613}
614
615impl From<LeBool> for bool {
616 #[inline(always)]
617 fn from(v: LeBool) -> Self {
618 v.get()
619 }
620}
621
622impl core::fmt::Debug for LeBool {
623 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
624 write!(f, "LeBool({})", self.get())
625 }
626}
627
628impl core::fmt::Display for LeBool {
629 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
630 write!(f, "{}", self.get())
631 }
632}
633
634unsafe impl Projectable for LeBool {}
637unsafe impl crate::pod::Zeroable for LeBool {}
639unsafe impl crate::pod::Pod for LeBool {}
640
641#[repr(transparent)]
648#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
649pub struct LeU128([u8; 16]);
650
651impl LeU128 {
652 pub const ZERO: Self = Self([0; 16]);
653 pub const MAX: Self = Self(u128::MAX.to_le_bytes());
654
655 #[inline(always)]
656 pub const fn new(v: u128) -> Self {
657 Self(v.to_le_bytes())
658 }
659
660 #[inline(always)]
661 pub const fn get(self) -> u128 {
662 u128::from_le_bytes(self.0)
663 }
664
665 #[inline(always)]
666 pub const fn to_le_bytes(self) -> [u8; 16] {
667 self.0
668 }
669
670 #[inline(always)]
671 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
672 match self.get().checked_add(rhs.get()) {
673 Some(v) => Some(Self::new(v)),
674 None => None,
675 }
676 }
677
678 #[inline(always)]
679 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
680 match self.get().checked_sub(rhs.get()) {
681 Some(v) => Some(Self::new(v)),
682 None => None,
683 }
684 }
685
686 #[inline(always)]
687 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
688 match self.get().checked_mul(rhs.get()) {
689 Some(v) => Some(Self::new(v)),
690 None => None,
691 }
692 }
693
694 #[inline(always)]
695 pub const fn saturating_add(self, rhs: Self) -> Self {
696 Self::new(self.get().saturating_add(rhs.get()))
697 }
698
699 #[inline(always)]
700 pub const fn saturating_sub(self, rhs: Self) -> Self {
701 Self::new(self.get().saturating_sub(rhs.get()))
702 }
703
704 #[inline(always)]
705 pub const fn is_zero(self) -> bool {
706 self.get() == 0
707 }
708}
709
710impl From<u128> for LeU128 {
711 #[inline(always)]
712 fn from(v: u128) -> Self {
713 Self::new(v)
714 }
715}
716
717impl From<LeU128> for u128 {
718 #[inline(always)]
719 fn from(v: LeU128) -> Self {
720 v.get()
721 }
722}
723
724impl PartialOrd for LeU128 {
725 #[inline(always)]
726 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
727 Some(self.cmp(other))
728 }
729}
730
731impl Ord for LeU128 {
732 #[inline(always)]
733 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
734 self.get().cmp(&other.get())
735 }
736}
737
738impl core::fmt::Debug for LeU128 {
739 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
740 write!(f, "LeU128({})", self.get())
741 }
742}
743
744impl core::fmt::Display for LeU128 {
745 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
746 write!(f, "{}", self.get())
747 }
748}
749
750unsafe impl Projectable for LeU128 {}
751unsafe impl crate::pod::Zeroable for LeU128 {}
754unsafe impl crate::pod::Pod for LeU128 {}
755
756__wire_arith_ops!(LeU128, u128);
757
758#[cfg(test)]
759mod tests {
760 use super::*;
761
762 fn require_pod<T: crate::pod::Pod>() {}
763
764 #[test]
768 fn wire_types_satisfy_substrate_pod() {
769 require_pod::<LeU64>();
770 require_pod::<LeU32>();
771 require_pod::<LeU16>();
772 require_pod::<LeI64>();
773 require_pod::<LeI32>();
774 require_pod::<LeI16>();
775 require_pod::<LeBool>();
776 require_pod::<LeU128>();
777 }
778
779 #[test]
780 fn wire_roundtrip_and_checked_math() {
781 let a = LeU64::new(u64::MAX - 1);
782 assert_eq!(a.get(), u64::MAX - 1);
783 assert_eq!(a.checked_add(LeU64::new(1)), Some(LeU64::MAX));
784 assert_eq!(LeU64::MAX.checked_add(LeU64::new(1)), None);
785 assert_eq!(LeU64::ZERO.checked_sub(LeU64::new(1)), None);
786 assert!(LeBool::new(true).get());
787 assert!(!LeBool::FALSE.get());
788 assert!(LeBool::TRUE.is_canonical());
789 }
790}