1use std::num::NonZeroU8;
4
5use crate::cell::*;
6use crate::error::{Error, ParseIntError};
7use crate::util::unlikely;
8
9pub use self::varuint248::VarUint248;
10
11mod varuint248;
12
13macro_rules! impl_serde {
14 ($ident:ident, $inner: ty) => {
15 #[cfg(feature = "serde")]
16 impl serde::Serialize for $ident {
17 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
18 where
19 S: serde::Serializer,
20 {
21 self.0.serialize(serializer)
22 }
23 }
24
25 #[cfg(feature = "serde")]
26 impl<'de> serde::Deserialize<'de> for $ident {
27 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
28 where
29 D: serde::Deserializer<'de>,
30 {
31 use serde::de::{Error, Unexpected};
32
33 struct Expected;
34
35 impl serde::de::Expected for Expected {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 f.write_str(stringify!($ident))
38 }
39 }
40
41 let res = Self::new(ok!(<$inner>::deserialize(deserializer)));
42 if res.is_valid() {
43 Ok(res)
44 } else {
45 Err(D::Error::invalid_type(
46 Unexpected::Other("big number"),
47 &Expected,
48 ))
49 }
50 }
51 }
52 };
53}
54
55macro_rules! impl_ops {
56 ($ident:ident, $inner:ty) => {
57 impl From<$ident> for $inner {
58 #[inline]
59 fn from(value: $ident) -> Self {
60 value.0
61 }
62 }
63
64 impl TryFrom<$inner> for $ident {
65 type Error = ParseIntError;
66
67 #[inline]
68 fn try_from(inner: $inner) -> Result<Self, Self::Error> {
69 let result = Self::new(inner);
70 if result.is_valid() {
71 Ok(result)
72 } else {
73 Err(ParseIntError::Overflow)
74 }
75 }
76 }
77
78 impl std::str::FromStr for $ident {
79 type Err = ParseIntError;
80
81 fn from_str(s: &str) -> Result<Self, Self::Err> {
82 match std::str::FromStr::from_str(s) {
83 Ok(inner) => {
84 let result = Self::new(inner);
85 if result.is_valid() {
86 Ok(result)
87 } else {
88 Err(ParseIntError::Overflow)
89 }
90 }
91 Err(e) => Err(ParseIntError::InvalidString(e)),
92 }
93 }
94 }
95
96 impl PartialEq<$inner> for $ident {
97 #[inline]
98 fn eq(&self, other: &$inner) -> bool {
99 self.0 == *other
100 }
101 }
102
103 impl PartialEq<$ident> for $inner {
104 #[inline]
105 fn eq(&self, other: &$ident) -> bool {
106 *self == other.0
107 }
108 }
109
110 impl std::fmt::Display for $ident {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 self.0.fmt(f)
113 }
114 }
115
116 impl std::fmt::Binary for $ident {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 std::fmt::Binary::fmt(&self.0, f)
119 }
120 }
121
122 impl std::fmt::LowerHex for $ident {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 std::fmt::LowerHex::fmt(&self.0, f)
125 }
126 }
127
128 impl std::fmt::UpperHex for $ident {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 std::fmt::UpperHex::fmt(&self.0, f)
131 }
132 }
133
134 impl std::ops::Add for $ident {
135 type Output = Self;
136
137 #[inline]
138 fn add(mut self, rhs: Self) -> Self::Output {
139 self.0 += rhs.0;
140 self
141 }
142 }
143
144 impl std::ops::Add<$inner> for $ident {
145 type Output = Self;
146
147 #[inline]
148 fn add(mut self, rhs: $inner) -> Self::Output {
149 self.0 += rhs;
150 self
151 }
152 }
153
154 impl std::ops::AddAssign for $ident {
155 #[inline]
156 fn add_assign(&mut self, rhs: Self) {
157 self.0 += rhs.0;
158 }
159 }
160
161 impl std::ops::AddAssign<$inner> for $ident {
162 fn add_assign(&mut self, rhs: $inner) {
163 self.0 += rhs;
164 }
165 }
166
167 impl std::ops::Sub for $ident {
168 type Output = Self;
169
170 #[inline]
171 fn sub(mut self, rhs: Self) -> Self::Output {
172 self.0 -= rhs.0;
173 self
174 }
175 }
176
177 impl std::ops::Sub<$inner> for $ident {
178 type Output = Self;
179
180 #[inline]
181 fn sub(mut self, rhs: $inner) -> Self::Output {
182 self.0 -= rhs;
183 self
184 }
185 }
186
187 impl std::ops::SubAssign for $ident {
188 #[inline]
189 fn sub_assign(&mut self, rhs: Self) {
190 self.0 -= rhs.0;
191 }
192 }
193
194 impl std::ops::SubAssign<$inner> for $ident {
195 #[inline]
196 fn sub_assign(&mut self, rhs: $inner) {
197 self.0 -= rhs;
198 }
199 }
200
201 impl std::ops::Mul for $ident {
202 type Output = Self;
203
204 #[inline]
205 fn mul(mut self, rhs: Self) -> Self::Output {
206 self.0 *= rhs.0;
207 self
208 }
209 }
210
211 impl std::ops::Mul<$inner> for $ident {
212 type Output = Self;
213
214 #[inline]
215 fn mul(mut self, rhs: $inner) -> Self::Output {
216 self.0 *= rhs;
217 self
218 }
219 }
220
221 impl std::ops::MulAssign for $ident {
222 #[inline]
223 fn mul_assign(&mut self, rhs: Self) {
224 self.0 *= rhs.0;
225 }
226 }
227
228 impl std::ops::MulAssign<$inner> for $ident {
229 #[inline]
230 fn mul_assign(&mut self, rhs: $inner) {
231 self.0 *= rhs;
232 }
233 }
234
235 impl std::ops::Div for $ident {
236 type Output = Self;
237
238 #[inline]
239 fn div(mut self, rhs: Self) -> Self::Output {
240 self.0 /= rhs.0;
241 self
242 }
243 }
244
245 impl std::ops::Div<$inner> for $ident {
246 type Output = Self;
247
248 #[inline]
249 fn div(mut self, rhs: $inner) -> Self::Output {
250 self.0 /= rhs;
251 self
252 }
253 }
254
255 impl std::ops::DivAssign for $ident {
256 #[inline]
257 fn div_assign(&mut self, rhs: Self) {
258 self.0 /= rhs.0;
259 }
260 }
261
262 impl std::ops::DivAssign<$inner> for $ident {
263 #[inline]
264 fn div_assign(&mut self, rhs: $inner) {
265 self.0 /= rhs;
266 }
267 }
268
269 impl std::ops::Shr<u8> for $ident {
270 type Output = Self;
271
272 #[inline]
273 fn shr(mut self, rhs: u8) -> Self::Output {
274 self.0 >>= rhs;
275 self
276 }
277 }
278
279 impl std::ops::ShrAssign<u8> for $ident {
280 #[inline]
281 fn shr_assign(&mut self, rhs: u8) {
282 self.0 >>= rhs;
283 }
284 }
285
286 impl std::ops::Shl<u8> for $ident {
287 type Output = Self;
288
289 #[inline]
290 fn shl(mut self, rhs: u8) -> Self::Output {
291 self.0 <<= rhs;
292 self
293 }
294 }
295
296 impl std::ops::ShlAssign<u8> for $ident {
297 #[inline]
298 fn shl_assign(&mut self, rhs: u8) {
299 self.0 <<= rhs;
300 }
301 }
302 };
303}
304
305macro_rules! impl_var_uints {
306 ($($(#[doc = $doc:expr])* $vis:vis struct $ident:ident($inner:ty[..$max_bytes:literal]);)*) => {
307 $(
308 impl_var_uints!{@impl $(#[doc = $doc])* $vis $ident $inner, $max_bytes}
309 )*
310 };
311
312 (@impl $(#[doc = $doc:expr])* $vis:vis $ident:ident $inner:ty, $max_bytes:literal) => {
313 $(#[doc = $doc])*
314 #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
315 #[repr(transparent)]
316 $vis struct $ident($inner);
317
318 impl $ident {
319 pub const ZERO: Self = $ident(0);
321
322 pub const ONE: Self = $ident(1);
324
325 pub const MIN: Self = $ident(0);
327
328 pub const MAX: Self = $ident(((1 as $inner) << ($max_bytes * 8)) - 1);
330
331 pub const LEN_BITS: u16 = 8 - ($max_bytes as u8).leading_zeros() as u16;
333
334 pub const MAX_BITS: u16 = Self::LEN_BITS + $max_bytes * 8;
336
337 #[inline]
339 pub const fn new(value: $inner) -> Self {
340 Self(value)
341 }
342
343 #[inline]
345 pub const fn into_inner(self) -> $inner {
346 self.0
347 }
348
349 #[inline]
351 pub const fn is_zero(&self) -> bool {
352 self.0 == 0
353 }
354
355 #[inline]
357 pub const fn is_valid(&self) -> bool {
358 self.0 <= Self::MAX.0
359 }
360
361 pub const fn bit_len(&self) -> Option<u16> {
364 let bytes = (std::mem::size_of::<Self>() as u32 - self.0.leading_zeros() / 8) as u8;
365 if unlikely(bytes > $max_bytes) {
366 None
367 } else {
368 Some(Self::LEN_BITS + bytes as u16 * 8)
369 }
370 }
371
372 pub const fn unwrap_bit_len(&self) -> u16 {
377 let bytes = (std::mem::size_of::<Self>() as u32 - self.0.leading_zeros() / 8) as u8;
378 if unlikely(bytes > $max_bytes) {
379 Self::MAX_BITS
380 } else {
381 Self::LEN_BITS + bytes as u16 * 8
382 }
383 }
384
385 #[inline]
387 #[must_use]
388 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
389 match self.0.checked_add(rhs.0) {
390 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
391 _ => None,
392 }
393 }
394
395 #[inline]
397 #[must_use]
398 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
399 match self.0.checked_sub(rhs.0) {
400 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
401 _ => None,
402 }
403 }
404
405 #[inline]
407 #[must_use]
408 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
409 match self.0.checked_mul(rhs.0) {
410 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
411 _ => None,
412 }
413 }
414
415 #[inline]
418 #[must_use]
419 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
420 match self.0.checked_div(rhs.0) {
421 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
422 _ => None,
423 }
424 }
425 }
426
427 impl ExactSize for $ident {
428 #[inline]
429 fn exact_size(&self) -> Size {
430 Size {
431 bits: self.bit_len().unwrap_or_default(),
432 refs: 0,
433 }
434 }
435 }
436
437 impl_ops! { $ident, $inner }
438 };
439}
440
441impl_var_uints! {
442 pub struct VarUint24(u32[..3]);
446
447 pub struct VarUint56(u64[..7]);
451
452 pub struct Tokens(u128[..15]);
456}
457
458impl_serde!(VarUint24, u32);
459impl_serde!(VarUint56, u64);
460
461#[cfg(feature = "serde")]
462impl serde::Serialize for Tokens {
463 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
464 where
465 S: serde::Serializer,
466 {
467 if serializer.is_human_readable() {
468 serializer.collect_str(&self.0)
469 } else {
470 self.0.serialize(serializer)
471 }
472 }
473}
474
475#[cfg(feature = "serde")]
476impl<'de> serde::Deserialize<'de> for Tokens {
477 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
478 where
479 D: serde::Deserializer<'de>,
480 {
481 use serde::de::{Error, Unexpected, Visitor};
482
483 struct Expected;
484
485 impl serde::de::Expected for Expected {
486 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
487 f.write_str(stringify!($ident))
488 }
489 }
490
491 struct TokensVisitor;
492
493 impl<'de> Visitor<'de> for TokensVisitor {
494 type Value = u128;
495
496 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
497 f.write_str("a string with a number")
498 }
499
500 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
501 v.parse().map_err(E::custom)
502 }
503 }
504
505 let res = Self::new(ok!(if deserializer.is_human_readable() {
506 deserializer.deserialize_str(TokensVisitor)
507 } else {
508 u128::deserialize(deserializer)
509 }));
510
511 if res.is_valid() {
512 Ok(res)
513 } else {
514 Err(D::Error::invalid_type(
515 Unexpected::Other("big number"),
516 &Expected,
517 ))
518 }
519 }
520}
521
522impl Store for VarUint24 {
523 fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
524 let bytes = (4 - self.0.leading_zeros() / 8) as u8;
525 let bits = bytes as u16 * 8;
526
527 if unlikely(bytes > 3 || !builder.has_capacity(Self::LEN_BITS + bits, 0)) {
528 return Err(Error::CellOverflow);
529 }
530
531 ok!(builder.store_small_uint(bytes, Self::LEN_BITS));
532 builder.store_uint(self.0 as u64, bits)
533 }
534}
535
536impl<'a> Load<'a> for VarUint24 {
537 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
538 let bytes = ok!(slice.load_small_uint(Self::LEN_BITS));
539 match slice.load_uint(bytes as u16 * 8) {
540 Ok(value) => Ok(Self(value as u32)),
541 Err(e) => Err(e),
542 }
543 }
544}
545
546impl Store for VarUint56 {
547 fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
548 let bytes = (8 - self.0.leading_zeros() / 8) as u8;
549 let bits = bytes as u16 * 8;
550
551 if unlikely(bytes > 7 || !builder.has_capacity(Self::LEN_BITS + bits, 0)) {
552 return Err(Error::CellOverflow);
553 }
554
555 ok!(builder.store_small_uint(bytes, Self::LEN_BITS));
556 builder.store_uint(self.0, bits)
557 }
558}
559
560impl<'a> Load<'a> for VarUint56 {
561 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
562 let bytes = ok!(slice.load_small_uint(Self::LEN_BITS));
563 match slice.load_uint(bytes as u16 * 8) {
564 Ok(value) => Ok(Self(value)),
565 Err(e) => Err(e),
566 }
567 }
568}
569
570impl Store for Tokens {
571 fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
572 let bytes = (16 - self.0.leading_zeros() / 8) as u8;
573 let bits = bytes as u16 * 8;
574
575 if unlikely(bytes > 15 || !builder.has_capacity(Self::LEN_BITS + bits, 0)) {
576 return Err(Error::CellOverflow);
577 }
578
579 ok!(builder.store_small_uint(bytes, Self::LEN_BITS));
580 store_u128(builder, self.0, bits)
581 }
582}
583
584impl<'a> Load<'a> for Tokens {
585 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
586 let bytes = ok!(slice.load_small_uint(Self::LEN_BITS));
587 match load_u128(slice, bytes) {
588 Ok(value) => Ok(Self(value)),
589 Err(e) => Err(e),
590 }
591 }
592}
593
594macro_rules! impl_small_uints {
595 ($($(#[doc = $doc:expr])* $vis:vis struct $ident:ident($bits:literal);)*) => {
596 $(
597 impl_small_uints!{@impl $(#[doc = $doc])* $vis $ident, $bits}
598 )*
599 };
600
601 (@impl $(#[doc = $doc:expr])* $vis:vis $ident:ident, $bits:literal) => {
602 $(#[doc = $doc])*
603 #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
604 #[repr(transparent)]
605 $vis struct $ident(u16);
606
607 impl $ident {
608 pub const ZERO: Self = $ident(0);
610
611 pub const ONE: Self = $ident(1);
613
614 pub const MIN: Self = $ident(0);
616
617 pub const MAX: Self = $ident((1u16 << $bits) - 1);
619
620 pub const BITS: u16 = $bits;
622
623 #[inline]
625 pub const fn new(value: u16) -> Self {
626 Self(value)
627 }
628
629 #[inline]
631 pub const fn into_inner(self) -> u16 {
632 self.0
633 }
634
635 #[inline]
637 pub const fn is_zero(&self) -> bool {
638 self.0 == 0
639 }
640
641 #[inline]
643 pub const fn is_valid(&self) -> bool {
644 self.0 <= Self::MAX.0
645 }
646
647 #[inline]
649 #[must_use]
650 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
651 match self.0.checked_add(rhs.0) {
652 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
653 _ => None,
654 }
655 }
656
657 #[inline]
659 #[must_use]
660 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
661 match self.0.checked_sub(rhs.0) {
662 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
663 _ => None,
664 }
665 }
666
667 #[inline]
669 #[must_use]
670 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
671 match self.0.checked_mul(rhs.0) {
672 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
673 _ => None,
674 }
675 }
676
677 #[inline]
680 #[must_use]
681 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
682 match self.0.checked_div(rhs.0) {
683 Some(value) if value <= Self::MAX.0 => Some($ident(value)),
684 _ => None,
685 }
686 }
687 }
688
689 impl ExactSize for $ident {
690 #[inline]
691 fn exact_size(&self) -> Size {
692 Size { bits: $bits, refs: 0 }
693 }
694 }
695
696 impl Store for $ident {
697 fn store_into(
698 &self,
699 builder: &mut CellBuilder,
700 _: &mut dyn CellContext
701 ) -> Result<(), Error> {
702 if !self.is_valid() {
703 return Err(Error::IntOverflow);
704 }
705 builder.store_uint(self.0 as u64, Self::BITS)
706 }
707 }
708
709 impl<'a> Load<'a> for $ident {
710 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
711 match slice.load_uint(Self::BITS) {
712 Ok(value) => Ok(Self(value as u16)),
713 Err(e) => Err(e),
714 }
715 }
716 }
717
718 impl crate::dict::DictKey for $ident {
719 const BITS: u16 = $bits;
720
721 #[inline]
722 fn from_raw_data(d: &[u8; 128]) -> Option<Self> {
723 Some($ident(u16::from_be_bytes([d[0], d[1]]) >> (16 - $bits)))
724 }
725 }
726
727 impl_ops! { $ident, u16 }
728 };
729}
730
731impl_small_uints! {
732 pub struct Uint9(9);
734
735 pub struct Uint12(12);
737
738 pub struct Uint15(15);
740}
741
742impl_serde!(Uint9, u16);
743impl_serde!(Uint12, u16);
744impl_serde!(Uint15, u16);
745
746#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
748#[repr(transparent)]
749pub struct SplitDepth(NonZeroU8);
750
751impl SplitDepth {
752 pub const MIN: Self = match NonZeroU8::new(1) {
754 Some(value) => Self(value),
755 None => unreachable!(),
756 };
757
758 pub const MAX: Self = match NonZeroU8::new(30) {
760 Some(value) => Self(value),
761 None => unreachable!(),
762 };
763
764 pub const BITS: u16 = 5;
766
767 #[inline]
769 pub const fn new(value: u8) -> Result<Self, Error> {
770 match NonZeroU8::new(value) {
771 Some(value) => Ok(Self(value)),
772 None => Err(Error::IntOverflow),
773 }
774 }
775
776 #[inline]
778 pub const fn from_bit_len(bit_len: u16) -> Result<Self, Error> {
779 if bit_len < u8::MAX as u16 {
780 Self::new(bit_len as u8)
781 } else {
782 Err(Error::IntOverflow)
783 }
784 }
785
786 #[inline]
788 pub const fn into_bit_len(self) -> u16 {
789 self.0.get() as u16
790 }
791}
792
793impl ExactSize for SplitDepth {
794 #[inline]
795 fn exact_size(&self) -> Size {
796 Size {
797 bits: Self::BITS,
798 refs: 0,
799 }
800 }
801}
802
803impl Store for SplitDepth {
804 fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
805 builder.store_small_uint(self.0.get(), Self::BITS)
806 }
807}
808
809impl<'a> Load<'a> for SplitDepth {
810 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
811 match slice.load_small_uint(Self::BITS) {
812 Ok(value) => Self::new(value),
813 Err(e) => Err(e),
814 }
815 }
816}
817
818#[cfg(feature = "serde")]
819impl serde::Serialize for SplitDepth {
820 #[inline]
821 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
822 where
823 S: serde::Serializer,
824 {
825 self.0.get().serialize(serializer)
826 }
827}
828
829#[cfg(feature = "serde")]
830impl<'de> serde::Deserialize<'de> for SplitDepth {
831 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
832 where
833 D: serde::Deserializer<'de>,
834 {
835 match u8::deserialize(deserializer) {
836 Ok(value) => Self::new(value).map_err(serde::de::Error::custom),
837 Err(e) => Err(e),
838 }
839 }
840}
841
842fn store_u128(builder: &mut CellBuilder, value: u128, mut bits: u16) -> Result<(), Error> {
843 if let Some(high_bits) = bits.checked_sub(64) {
844 ok!(builder.store_uint((value >> 64) as u64, high_bits));
845 bits -= high_bits;
846 }
847 builder.store_uint(value as u64, bits)
848}
849
850fn load_u128(slice: &mut CellSlice<'_>, mut bytes: u8) -> Result<u128, Error> {
851 let mut result: u128 = 0;
852 if let Some(high_bytes) = bytes.checked_sub(8) {
853 if high_bytes > 0 {
854 result = (ok!(slice.load_uint(high_bytes as u16 * 8)) as u128) << 64;
855 bytes -= high_bytes;
856 }
857 }
858
859 match slice.load_uint(bytes as u16 * 8) {
860 Ok(value) => Ok(result | value as u128),
861 Err(e) => Err(e),
862 }
863}
864
865#[cfg(test)]
866mod tests {
867 use super::*;
868 use crate::prelude::CellBuilder;
869
870 macro_rules! impl_operation_tests {
871 ($ident:ident$(, $check_max_div:ident)?) => {
872 assert_eq!($ident::new(10) + $ident::new(4), $ident::new(14));
873 assert_eq!($ident::new(10) + 4, $ident::new(14));
874
875 assert_eq!($ident::new(10) - $ident::new(4), $ident::new(6));
876 assert_eq!($ident::new(10) - 4, $ident::new(6));
877
878 assert_eq!($ident::new(10) * $ident::new(4), $ident::new(40));
879 assert_eq!($ident::new(10) * 4, $ident::new(40));
880
881 assert_eq!($ident::new(10) / $ident::new(2), $ident::new(5));
882 assert_eq!($ident::new(10) / 2, $ident::new(5));
883
884 assert_eq!($ident::new(10) >> 2, $ident::new(2));
885 assert_eq!($ident::new(10) << 2, $ident::new(40));
886
887 let mut value = $ident::new(10);
888 value += 4;
889 assert_eq!(value, $ident::new(14));
890
891 let mut value = $ident::new(10);
892 value -= 4;
893 assert_eq!(value, $ident::new(6));
894
895 let mut value = $ident::new(10);
896 value *= 4;
897 assert_eq!(value, $ident::new(40));
898
899 let mut value = $ident::new(10);
900 value /= 2;
901 assert_eq!(value, $ident::new(5));
902
903 let mut value = $ident::new(10);
904 value >>= 2;
905 assert_eq!(value, $ident::new(2));
906
907 let mut value = $ident::new(10);
908 value <<= 2;
909 assert_eq!(value, $ident::new(40));
910
911 assert!(!($ident::MAX + 1).is_valid());
912
913 assert_eq!($ident::MAX.checked_add($ident::new(1)), None);
914 assert_eq!(
915 ($ident::MAX - 1).checked_add($ident::new(1)),
916 Some($ident::MAX)
917 );
918
919 assert_eq!(($ident::MAX + 10).checked_sub($ident::new(1)), None);
920 assert_eq!(
921 ($ident::MAX + 10).checked_sub($ident::MAX),
922 Some($ident::new(10)),
923 );
924 assert_eq!($ident::new(10).checked_sub($ident::MAX), None);
925
926 assert_eq!($ident::MAX.checked_mul($ident::new(2)), None);
927 assert_eq!(
928 ($ident::MAX / 2).checked_mul($ident::new(2)),
929 Some($ident::MAX - 1)
930 );
931
932 $(
933 let $check_max_div = ();
934 _ = $check_max_div;
935 assert_eq!((($ident::MAX + 1) * 2).checked_div($ident::new(2)), None);
936 assert_eq!(
937 ($ident::MAX * 2).checked_div($ident::new(2)),
938 Some($ident::MAX)
939 );
940 assert_eq!($ident::ONE.checked_div($ident::ZERO), None);
941 )?
942 };
943 }
944
945 macro_rules! impl_serialization_tests {
946 ($ident:ident, $max_bits:literal) => {
947 let context = &mut Cell::empty_context();
948
949 for i in 0..$max_bits {
950 let value = $ident::ONE << i;
951 let mut builder = CellBuilder::new();
952
953 if value <= $ident::MAX {
954 value.store_into(&mut builder, context).unwrap();
955 let cell = builder.build().unwrap();
956 assert_eq!(value.bit_len().unwrap(), cell.bit_len());
957 } else {
958 assert!(value.store_into(&mut builder, context).is_err());
959 }
960 }
961 };
962 }
963
964 macro_rules! impl_deserialization_tests {
965 ($ident:ident, $max_bits:literal, $value:literal) => {
966 let context = &mut Cell::empty_context();
967
968 let mut value = $ident::new($value);
969 for _ in 0..=$max_bits {
970 let mut builder = CellBuilder::new();
971 value.store_into(&mut builder, context).unwrap();
972 let cell = builder.build().unwrap();
973
974 let parsed_value = cell.parse::<$ident>().unwrap();
975 assert_eq!(parsed_value, value);
976
977 value >>= 1;
978 }
979 };
980 }
981
982 macro_rules! impl_fixed_len_serialization_tests {
983 ($ident:ident, $max_bits:literal) => {
984 let context = &mut Cell::empty_context();
985
986 for i in 0..$max_bits {
987 let value = $ident::ONE << i;
988 let mut builder = CellBuilder::new();
989
990 if value <= $ident::MAX {
991 value.store_into(&mut builder, context).unwrap();
992 let cell = builder.build().unwrap();
993 assert_eq!($ident::BITS, cell.bit_len());
994 } else {
995 assert!(value.store_into(&mut builder, context).is_err());
996 }
997 }
998 };
999 }
1000
1001 #[test]
1002 fn fixed_len_operations() {
1003 impl_operation_tests!(Uint9, check_max_div);
1004 impl_operation_tests!(Uint12, check_max_div);
1005 impl_operation_tests!(Uint15);
1006 }
1007
1008 #[test]
1009 fn fixed_len_serialization() {
1010 impl_fixed_len_serialization_tests!(Uint9, 16);
1011 impl_fixed_len_serialization_tests!(Uint12, 16);
1012 impl_fixed_len_serialization_tests!(Uint15, 16);
1013 }
1014
1015 #[test]
1016 fn fixed_len_deserialization() {
1017 impl_deserialization_tests!(Uint9, 9, 0b100110011);
1018 impl_deserialization_tests!(Uint12, 12, 0b111100110011);
1019 impl_deserialization_tests!(Uint15, 15, 0b11111100110011);
1020 }
1021
1022 #[test]
1023 fn var_uint24_operations() {
1024 impl_operation_tests!(VarUint24, check_max_div);
1025 }
1026
1027 #[test]
1028 fn var_uint56_operations() {
1029 impl_operation_tests!(VarUint56, check_max_div);
1030 }
1031
1032 #[test]
1033 fn tokens_operations() {
1034 impl_operation_tests!(Tokens, check_max_div);
1035 }
1036
1037 #[test]
1038 fn var_uint24_serialization() {
1039 impl_serialization_tests!(VarUint24, 32);
1040 }
1041
1042 #[test]
1043 fn var_uint56_serialization() {
1044 impl_serialization_tests!(VarUint56, 64);
1045 }
1046
1047 #[test]
1048 fn tokens_serialization() {
1049 impl_serialization_tests!(Tokens, 128);
1050 }
1051
1052 #[test]
1053 fn var_uint24_deserialization() {
1054 impl_deserialization_tests!(VarUint24, 24, 0xabcdef);
1055 }
1056
1057 #[test]
1058 fn var_uint56_deserialization() {
1059 impl_deserialization_tests!(VarUint56, 56, 0xabcdef89abcdef);
1060 }
1061
1062 #[test]
1063 fn tokens_deserialization() {
1064 impl_deserialization_tests!(Tokens, 120, 0xabcdef89abcdefdeadbeeffafacafe);
1065 }
1066
1067 fn _num_must_use() {
1068 #[expect(unused_must_use)]
1069 {
1070 Uint9::new(10).checked_add(Uint9::ZERO);
1071 }
1072
1073 #[expect(unused_must_use)]
1074 {
1075 Uint12::new(10).checked_add(Uint12::ZERO);
1076 }
1077
1078 #[expect(unused_must_use)]
1079 {
1080 Uint15::new(10).checked_add(Uint15::ZERO);
1081 }
1082
1083 #[expect(unused_must_use)]
1084 {
1085 VarUint24::new(10).checked_add(VarUint24::ZERO);
1086 }
1087
1088 #[expect(unused_must_use)]
1089 {
1090 VarUint56::new(10).checked_add(VarUint56::ZERO);
1091 }
1092
1093 #[expect(unused_must_use)]
1094 {
1095 Tokens::new(10).checked_add(Tokens::ZERO);
1096 }
1097
1098 #[expect(unused_must_use)]
1099 {
1100 VarUint248::new(10).checked_add(&VarUint248::ZERO);
1101 }
1102 }
1103}