1use core::{cmp::Ordering, convert::Infallible, fmt::Debug};
2
3use super::{
4 env::internal::{
5 DurationSmall, DurationVal, Env as _, I256Object, I256Small, I256Val, TimepointSmall,
6 TimepointVal, U256Object, U256Small, U256Val,
7 },
8 Bytes, ConversionError, Env, TryFromVal, TryIntoVal, Val,
9};
10
11#[cfg(not(target_family = "wasm"))]
12use crate::env::internal::xdr::ScVal;
13use crate::unwrap::{UnwrapInfallible, UnwrapOptimized};
14
15macro_rules! impl_num_wrapping_val_type {
16 ($wrapper:ident, $val:ty, $small:ty) => {
17 impl Debug for $wrapper {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 write!(f, "{:?}", self.val.as_val())
21 }
22 }
23
24 impl Eq for $wrapper {}
25
26 impl PartialEq for $wrapper {
27 fn eq(&self, other: &Self) -> bool {
28 self.partial_cmp(other) == Some(Ordering::Equal)
29 }
30 }
31
32 impl PartialOrd for $wrapper {
33 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
34 Some(Ord::cmp(self, other))
35 }
36 }
37
38 impl Ord for $wrapper {
39 fn cmp(&self, other: &Self) -> Ordering {
40 let self_raw = self.val.to_val();
41 let other_raw = other.val.to_val();
42
43 match (<$small>::try_from(self_raw), <$small>::try_from(other_raw)) {
44 (Ok(self_num), Ok(other_num)) => self_num.cmp(&other_num),
46 _ => {
49 #[cfg(not(target_family = "wasm"))]
50 if !self.env.is_same_env(&other.env) {
51 return ScVal::from(self).cmp(&ScVal::from(other));
52 }
53 let v = self.env.obj_cmp(self_raw, other_raw).unwrap_infallible();
54 v.cmp(&0)
55 }
56 }
57 }
58 }
59
60 impl From<$wrapper> for $val {
61 #[inline(always)]
62 fn from(v: $wrapper) -> Self {
63 v.val
64 }
65 }
66
67 impl From<&$wrapper> for $val {
68 #[inline(always)]
69 fn from(v: &$wrapper) -> Self {
70 v.val
71 }
72 }
73
74 impl From<&$wrapper> for $wrapper {
75 #[inline(always)]
76 fn from(v: &$wrapper) -> Self {
77 v.clone()
78 }
79 }
80
81 impl TryFromVal<Env, $val> for $wrapper {
82 type Error = Infallible;
83
84 fn try_from_val(env: &Env, val: &$val) -> Result<Self, Self::Error> {
85 Ok(unsafe { $wrapper::unchecked_new(env.clone(), *val) })
86 }
87 }
88
89 impl TryFromVal<Env, Val> for $wrapper {
90 type Error = ConversionError;
91
92 fn try_from_val(env: &Env, val: &Val) -> Result<Self, Self::Error> {
93 Ok(<$val>::try_from_val(env, val)?
94 .try_into_val(env)
95 .unwrap_infallible())
96 }
97 }
98
99 impl TryFromVal<Env, $wrapper> for Val {
100 type Error = ConversionError;
101
102 fn try_from_val(_env: &Env, v: &$wrapper) -> Result<Self, Self::Error> {
103 Ok(v.to_val())
104 }
105 }
106
107 impl TryFromVal<Env, &$wrapper> for Val {
108 type Error = ConversionError;
109
110 fn try_from_val(_env: &Env, v: &&$wrapper) -> Result<Self, Self::Error> {
111 Ok(v.to_val())
112 }
113 }
114
115 #[cfg(not(target_family = "wasm"))]
116 impl From<&$wrapper> for ScVal {
117 fn from(v: &$wrapper) -> Self {
118 if let Ok(ss) = <$small>::try_from(v.val) {
124 ScVal::try_from(ss).unwrap()
125 } else {
126 ScVal::try_from_val(&v.env, &v.to_val()).unwrap()
127 }
128 }
129 }
130
131 #[cfg(not(target_family = "wasm"))]
132 impl From<$wrapper> for ScVal {
133 fn from(v: $wrapper) -> Self {
134 (&v).into()
135 }
136 }
137
138 #[cfg(not(target_family = "wasm"))]
139 impl TryFromVal<Env, ScVal> for $wrapper {
140 type Error = ConversionError;
141 fn try_from_val(env: &Env, val: &ScVal) -> Result<Self, Self::Error> {
142 Ok(<$val>::try_from_val(env, &Val::try_from_val(env, val)?)?
143 .try_into_val(env)
144 .unwrap_infallible())
145 }
146 }
147
148 impl $wrapper {
149 #[inline(always)]
150 pub(crate) unsafe fn unchecked_new(env: Env, val: $val) -> Self {
151 Self { env, val }
152 }
153
154 #[inline(always)]
158 pub(crate) unsafe fn unchecked_from_val(env: Env, val: Val) -> Self {
159 Self {
160 env,
161 val: <$val>::try_from(val).unwrap_optimized(),
162 }
163 }
164
165 #[inline(always)]
166 pub fn env(&self) -> &Env {
167 &self.env
168 }
169
170 pub fn as_val(&self) -> &Val {
171 self.val.as_val()
172 }
173
174 pub fn to_val(&self) -> Val {
175 self.val.to_val()
176 }
177
178 pub fn to_val_type(&self) -> $val {
179 self.val
180 }
181 }
182 };
183}
184
185#[derive(Clone)]
198pub struct U256 {
199 env: Env,
200 val: U256Val,
201}
202
203impl_num_wrapping_val_type!(U256, U256Val, U256Small);
204
205impl U256 {
206 pub const BITS: u32 = 256;
207
208 pub fn min_value(env: &Env) -> Self {
210 Self::from_u32(env, 0)
211 }
212
213 pub fn max_value(env: &Env) -> Self {
215 Self::from_parts(env, u64::MAX, u64::MAX, u64::MAX, u64::MAX)
216 }
217
218 fn is_zero(&self) -> bool {
219 *self == U256::from_u32(&self.env, 0)
220 }
221
222 pub fn from_u32(env: &Env, u: u32) -> Self {
223 U256 {
224 env: env.clone(),
225 val: U256Val::from_u32(u),
226 }
227 }
228
229 pub fn from_u128(env: &Env, u: u128) -> Self {
230 let lo_hi = (u >> 64) as u64;
231 let lo_lo = u as u64;
232 Self::from_parts(env, 0, 0, lo_hi, lo_lo)
233 }
234
235 pub fn from_parts(env: &Env, hi_hi: u64, hi_lo: u64, lo_hi: u64, lo_lo: u64) -> Self {
236 let obj = env
237 .obj_from_u256_pieces(hi_hi, hi_lo, lo_hi, lo_lo)
238 .unwrap_infallible();
239 U256 {
240 env: env.clone(),
241 val: obj.into(),
242 }
243 }
244
245 pub fn from_be_bytes(env: &Env, bytes: &Bytes) -> Self {
246 let val = env
247 .u256_val_from_be_bytes(bytes.to_object())
248 .unwrap_infallible();
249 U256 {
250 env: env.clone(),
251 val,
252 }
253 }
254
255 pub fn to_u128(&self) -> Option<u128> {
256 let v = *self.val.as_val();
257
258 if let Ok(small) = U256Small::try_from(v) {
260 return Some(u64::from(small) as u128);
261 }
262
263 let obj: U256Object = v.try_into().ok()?;
265 let hi_hi = self.env.obj_to_u256_hi_hi(obj).unwrap_infallible();
266 let hi_lo = self.env.obj_to_u256_hi_lo(obj).unwrap_infallible();
267 if hi_hi != 0 || hi_lo != 0 {
268 return None;
269 }
270 let lo_hi = self.env.obj_to_u256_lo_hi(obj).unwrap_infallible();
271 let lo_lo = self.env.obj_to_u256_lo_lo(obj).unwrap_infallible();
272 Some(((lo_hi as u128) << 64) | (lo_lo as u128))
273 }
274
275 pub fn to_be_bytes(&self) -> Bytes {
276 let obj = self
277 .env
278 .u256_val_to_be_bytes(self.to_val_type())
279 .unwrap_infallible();
280 unsafe { Bytes::unchecked_new(self.env.clone(), obj) }
281 }
282
283 pub fn add(&self, other: &U256) -> U256 {
284 let val = self.env.u256_add(self.val, other.val).unwrap_infallible();
285 U256 {
286 env: self.env.clone(),
287 val,
288 }
289 }
290
291 pub fn sub(&self, other: &U256) -> U256 {
292 let val = self.env.u256_sub(self.val, other.val).unwrap_infallible();
293 U256 {
294 env: self.env.clone(),
295 val,
296 }
297 }
298
299 pub fn mul(&self, other: &U256) -> U256 {
300 let val = self.env.u256_mul(self.val, other.val).unwrap_infallible();
301 U256 {
302 env: self.env.clone(),
303 val,
304 }
305 }
306
307 pub fn div(&self, other: &U256) -> U256 {
308 let val = self.env.u256_div(self.val, other.val).unwrap_infallible();
309 U256 {
310 env: self.env.clone(),
311 val,
312 }
313 }
314
315 pub fn rem_euclid(&self, other: &U256) -> U256 {
316 let val = self
317 .env
318 .u256_rem_euclid(self.val, other.val)
319 .unwrap_infallible();
320 U256 {
321 env: self.env.clone(),
322 val,
323 }
324 }
325
326 pub fn pow(&self, pow: u32) -> U256 {
327 let val = self.env.u256_pow(self.val, pow.into()).unwrap_infallible();
328 U256 {
329 env: self.env.clone(),
330 val,
331 }
332 }
333
334 pub fn shl(&self, bits: u32) -> U256 {
335 let val = self.env.u256_shl(self.val, bits.into()).unwrap_infallible();
336 U256 {
337 env: self.env.clone(),
338 val,
339 }
340 }
341
342 pub fn shr(&self, bits: u32) -> U256 {
343 let val = self.env.u256_shr(self.val, bits.into()).unwrap_infallible();
344 U256 {
345 env: self.env.clone(),
346 val,
347 }
348 }
349
350 pub fn checked_add(&self, other: &U256) -> Option<U256> {
352 let val = self
353 .env
354 .u256_checked_add(self.val, other.val)
355 .unwrap_infallible();
356 if val.is_void() {
357 None
358 } else {
359 Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
360 }
361 }
362
363 pub fn checked_sub(&self, other: &U256) -> Option<U256> {
365 let val = self
366 .env
367 .u256_checked_sub(self.val, other.val)
368 .unwrap_infallible();
369 if val.is_void() {
370 None
371 } else {
372 Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
373 }
374 }
375
376 pub fn checked_mul(&self, other: &U256) -> Option<U256> {
378 let val = self
379 .env
380 .u256_checked_mul(self.val, other.val)
381 .unwrap_infallible();
382 if val.is_void() {
383 None
384 } else {
385 Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
386 }
387 }
388
389 pub fn checked_pow(&self, pow: u32) -> Option<U256> {
391 let val = self
392 .env
393 .u256_checked_pow(self.val, pow.into())
394 .unwrap_infallible();
395 if val.is_void() {
396 None
397 } else {
398 Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
399 }
400 }
401
402 pub fn checked_div(&self, other: &U256) -> Option<U256> {
404 if other.is_zero() {
405 return None;
406 }
407 Some(self.div(other))
408 }
409
410 pub fn checked_rem_euclid(&self, other: &U256) -> Option<U256> {
412 if other.is_zero() {
413 return None;
414 }
415 Some(self.rem_euclid(other))
416 }
417
418 pub fn checked_shl(&self, bits: u32) -> Option<U256> {
420 if bits >= Self::BITS {
421 return None;
422 }
423 Some(self.shl(bits))
424 }
425
426 pub fn checked_shr(&self, bits: u32) -> Option<U256> {
428 if bits >= Self::BITS {
429 return None;
430 }
431 Some(self.shr(bits))
432 }
433}
434
435#[derive(Clone)]
449pub struct I256 {
450 env: Env,
451 val: I256Val,
452}
453
454impl_num_wrapping_val_type!(I256, I256Val, I256Small);
455
456impl I256 {
457 pub const BITS: u32 = 256;
458
459 pub fn min_value(env: &Env) -> Self {
461 Self::from_parts(env, i64::MIN, 0, 0, 0)
462 }
463
464 pub fn max_value(env: &Env) -> Self {
466 Self::from_parts(env, i64::MAX, u64::MAX, u64::MAX, u64::MAX)
467 }
468
469 fn is_zero(&self) -> bool {
470 *self == I256::from_i32(&self.env, 0)
471 }
472
473 fn is_neg_one(&self) -> bool {
474 *self == I256::from_i32(&self.env, -1)
475 }
476
477 pub fn from_i32(env: &Env, i: i32) -> Self {
478 I256 {
479 env: env.clone(),
480 val: I256Val::from_i32(i),
481 }
482 }
483
484 pub fn from_i128(env: &Env, i: i128) -> Self {
485 let lo_hi = (i >> 64) as u64;
486 let lo_lo = i as u64;
487 let (hi_hi, hi_lo) = if i < 0 {
488 (-1_i64, u64::MAX) } else {
490 (0_i64, 0_u64) };
492 I256::from_parts(env, hi_hi, hi_lo, lo_hi, lo_lo)
493 }
494
495 pub fn from_parts(env: &Env, hi_hi: i64, hi_lo: u64, lo_hi: u64, lo_lo: u64) -> Self {
496 let obj = env
497 .obj_from_i256_pieces(hi_hi, hi_lo, lo_hi, lo_lo)
498 .unwrap_infallible();
499 I256 {
500 env: env.clone(),
501 val: obj.into(),
502 }
503 }
504
505 pub fn from_be_bytes(env: &Env, bytes: &Bytes) -> Self {
506 let val = env
507 .i256_val_from_be_bytes(bytes.to_object())
508 .unwrap_infallible();
509 I256 {
510 env: env.clone(),
511 val,
512 }
513 }
514
515 pub fn to_i128(&self) -> Option<i128> {
516 let v = *self.val.as_val();
517
518 if let Ok(small) = I256Small::try_from(v) {
520 return Some(i64::from(small) as i128);
521 }
522
523 let obj: I256Object = v.try_into().ok()?;
526 let hi_hi = self.env.obj_to_i256_hi_hi(obj).unwrap_infallible();
527 let hi_lo = self.env.obj_to_i256_hi_lo(obj).unwrap_infallible();
528 let lo_hi = self.env.obj_to_i256_lo_hi(obj).unwrap_infallible();
529 let lo_lo = self.env.obj_to_i256_lo_lo(obj).unwrap_infallible();
530 let lo = (((lo_hi as u128) << 64) | (lo_lo as u128)) as i128;
532
533 if lo < 0 && hi_hi == -1 && hi_lo == u64::MAX {
534 Some(lo) } else if 0 <= lo && hi_hi == 0 && hi_lo == 0 {
536 Some(lo) } else {
538 None
539 }
540 }
541
542 pub fn to_be_bytes(&self) -> Bytes {
543 let obj = self
544 .env
545 .i256_val_to_be_bytes(self.to_val_type())
546 .unwrap_infallible();
547 unsafe { Bytes::unchecked_new(self.env.clone(), obj) }
548 }
549
550 pub fn add(&self, other: &I256) -> I256 {
551 let val = self.env.i256_add(self.val, other.val).unwrap_infallible();
552 I256 {
553 env: self.env.clone(),
554 val,
555 }
556 }
557
558 pub fn sub(&self, other: &I256) -> I256 {
559 let val = self.env.i256_sub(self.val, other.val).unwrap_infallible();
560 I256 {
561 env: self.env.clone(),
562 val,
563 }
564 }
565
566 pub fn mul(&self, other: &I256) -> I256 {
567 let val = self.env.i256_mul(self.val, other.val).unwrap_infallible();
568 I256 {
569 env: self.env.clone(),
570 val,
571 }
572 }
573
574 pub fn div(&self, other: &I256) -> I256 {
575 let val = self.env.i256_div(self.val, other.val).unwrap_infallible();
576 I256 {
577 env: self.env.clone(),
578 val,
579 }
580 }
581
582 pub fn rem_euclid(&self, other: &I256) -> I256 {
583 let val = self
584 .env
585 .i256_rem_euclid(self.val, other.val)
586 .unwrap_infallible();
587 I256 {
588 env: self.env.clone(),
589 val,
590 }
591 }
592
593 pub fn pow(&self, pow: u32) -> I256 {
594 let val = self.env.i256_pow(self.val, pow.into()).unwrap_infallible();
595 I256 {
596 env: self.env.clone(),
597 val,
598 }
599 }
600
601 pub fn shl(&self, bits: u32) -> I256 {
602 let val = self.env.i256_shl(self.val, bits.into()).unwrap_infallible();
603 I256 {
604 env: self.env.clone(),
605 val,
606 }
607 }
608
609 pub fn shr(&self, bits: u32) -> I256 {
610 let val = self.env.i256_shr(self.val, bits.into()).unwrap_infallible();
611 I256 {
612 env: self.env.clone(),
613 val,
614 }
615 }
616
617 pub fn checked_add(&self, other: &I256) -> Option<I256> {
619 let val = self
620 .env
621 .i256_checked_add(self.val, other.val)
622 .unwrap_infallible();
623 if val.is_void() {
624 None
625 } else {
626 Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
627 }
628 }
629
630 pub fn checked_sub(&self, other: &I256) -> Option<I256> {
632 let val = self
633 .env
634 .i256_checked_sub(self.val, other.val)
635 .unwrap_infallible();
636 if val.is_void() {
637 None
638 } else {
639 Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
640 }
641 }
642
643 pub fn checked_mul(&self, other: &I256) -> Option<I256> {
645 let val = self
646 .env
647 .i256_checked_mul(self.val, other.val)
648 .unwrap_infallible();
649 if val.is_void() {
650 None
651 } else {
652 Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
653 }
654 }
655
656 pub fn checked_pow(&self, pow: u32) -> Option<I256> {
658 let val = self
659 .env
660 .i256_checked_pow(self.val, pow.into())
661 .unwrap_infallible();
662 if val.is_void() {
663 None
664 } else {
665 Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
666 }
667 }
668
669 fn is_div_overflow(&self, other: &I256) -> bool {
672 if other.is_zero() {
673 return true;
674 }
675 if other.is_neg_one() {
676 let min = I256::min_value(&self.env);
677 if *self == min {
678 return true;
679 }
680 }
681 false
682 }
683
684 pub fn checked_div(&self, other: &I256) -> Option<I256> {
687 if self.is_div_overflow(other) {
688 return None;
689 }
690 Some(self.div(other))
691 }
692
693 pub fn checked_rem_euclid(&self, other: &I256) -> Option<I256> {
697 if self.is_div_overflow(other) {
698 return None;
699 }
700 Some(self.rem_euclid(other))
701 }
702
703 pub fn checked_shl(&self, bits: u32) -> Option<I256> {
705 if bits >= Self::BITS {
706 return None;
707 }
708 Some(self.shl(bits))
709 }
710
711 pub fn checked_shr(&self, bits: u32) -> Option<I256> {
713 if bits >= Self::BITS {
714 return None;
715 }
716 Some(self.shr(bits))
717 }
718}
719
720#[doc = "Timepoint holds a 64-bit unsigned integer."]
721#[derive(Clone)]
722pub struct Timepoint {
723 env: Env,
724 val: TimepointVal,
725}
726
727impl_num_wrapping_val_type!(Timepoint, TimepointVal, TimepointSmall);
728
729impl Timepoint {
730 pub fn from_unix(env: &Env, seconds: u64) -> Timepoint {
733 let val = TimepointVal::try_from_val(env, &seconds).unwrap_optimized();
734 Timepoint {
735 env: env.clone(),
736 val,
737 }
738 }
739
740 pub fn to_unix(&self) -> u64 {
743 u64::try_from_val(self.env(), &self.to_val_type()).unwrap_optimized()
744 }
745}
746
747#[doc = "Duration holds a 64-bit unsigned integer."]
748#[derive(Clone)]
749pub struct Duration {
750 env: Env,
751 val: DurationVal,
752}
753
754impl_num_wrapping_val_type!(Duration, DurationVal, DurationSmall);
755
756impl Duration {
757 pub fn from_seconds(env: &Env, seconds: u64) -> Duration {
759 let val = DurationVal::try_from_val(env, &seconds).unwrap_optimized();
760 Duration {
761 env: env.clone(),
762 val,
763 }
764 }
765
766 pub fn to_seconds(&self) -> u64 {
768 u64::try_from_val(self.env(), &self.to_val_type()).unwrap_optimized()
769 }
770}
771
772#[cfg(test)]
773mod test {
774 use super::*;
775
776 #[test]
777 fn test_u256_roundtrip() {
778 let env = Env::default();
779
780 let u1 = U256::from_u32(&env, 12345);
781 let bytes = u1.to_be_bytes();
782 let u2 = U256::from_be_bytes(&env, &bytes);
783 assert_eq!(u1, u2);
784 }
785
786 #[test]
787 fn test_u256_u128_conversion() {
788 let env = Env::default();
789
790 let start = u128::MAX / 7;
792 let from = U256::from_u128(&env, start);
793 let end = from.to_u128().unwrap();
794 assert_eq!(start, end);
795
796 let over_u128 = from.mul(&U256::from_u32(&env, 8));
797 let failure = over_u128.to_u128();
798 assert_eq!(failure, None);
799
800 let start = 0_u128;
802 let from = U256::from_u128(&env, start);
803 let end = from.to_u128().unwrap();
804 assert_eq!(start, end);
805
806 let from_small = U256::from_u32(&env, 0);
808 assert_eq!(from_small.to_u128(), Some(0_u128));
809
810 let from_small = U256::from_u32(&env, u32::MAX);
811 assert_eq!(from_small.to_u128(), Some(u32::MAX as u128));
812 }
813
814 #[test]
815 fn test_i256_roundtrip() {
816 let env = Env::default();
817
818 let i1 = I256::from_i32(&env, -12345);
819 let bytes = i1.to_be_bytes();
820 let i2 = I256::from_be_bytes(&env, &bytes);
821 assert_eq!(i1, i2);
822 }
823
824 #[test]
825 fn test_i256_i128_conversion() {
826 let env = Env::default();
827
828 let start = i128::MAX / 7;
830 let from = I256::from_i128(&env, start);
831 let end = from.to_i128().unwrap();
832 assert_eq!(start, end);
833
834 let over_i128 = from.mul(&I256::from_i32(&env, 8));
835 let failure = over_i128.to_i128();
836 assert_eq!(failure, None);
837
838 let start = i128::MIN / 7;
840 let from = I256::from_i128(&env, start);
841 let end = from.to_i128().unwrap();
842 assert_eq!(start, end);
843
844 let over_i128 = from.mul(&I256::from_i32(&env, 8));
845 let failure = over_i128.to_i128();
846 assert_eq!(failure, None);
847
848 let start = 0_i128;
850 let from = I256::from_i128(&env, start);
851 let end = from.to_i128().unwrap();
852 assert_eq!(start, end);
853
854 let from_small = I256::from_i32(&env, 0);
856 assert_eq!(from_small.to_i128(), Some(0_i128));
857
858 let from_small = I256::from_i32(&env, i32::MAX);
859 assert_eq!(from_small.to_i128(), Some(i32::MAX as i128));
860
861 let from_small = I256::from_i32(&env, i32::MIN);
862 assert_eq!(from_small.to_i128(), Some(i32::MIN as i128));
863 }
864
865 #[test]
866 fn test_timepoint_roundtrip() {
867 let env = Env::default();
868
869 let tp = Timepoint::from_unix(&env, 123);
870 let u = tp.to_unix();
871 assert_eq!(u, 123);
872 }
873
874 #[test]
875 fn test_duration_roundtrip() {
876 let env = Env::default();
877
878 let tp = Duration::from_seconds(&env, 123);
879 let u = tp.to_seconds();
880 assert_eq!(u, 123);
881 }
882
883 #[test]
884 fn test_u256_arith() {
885 let env = Env::default();
886
887 let u1 = U256::from_u32(&env, 6);
888 let u2 = U256::from_u32(&env, 3);
889 assert_eq!(u1.add(&u2), U256::from_u32(&env, 9));
890 assert_eq!(u1.sub(&u2), U256::from_u32(&env, 3));
891 assert_eq!(u1.mul(&u2), U256::from_u32(&env, 18));
892 assert_eq!(u1.div(&u2), U256::from_u32(&env, 2));
893 assert_eq!(u1.pow(2), U256::from_u32(&env, 36));
894 assert_eq!(u1.shl(2), U256::from_u32(&env, 24));
895 assert_eq!(u1.shr(1), U256::from_u32(&env, 3));
896
897 let u3 = U256::from_u32(&env, 7);
898 let u4 = U256::from_u32(&env, 4);
899 assert_eq!(u3.rem_euclid(&u4), U256::from_u32(&env, 3));
900 }
901
902 #[test]
903 fn test_u256_min() {
904 let env = Env::default();
905
906 let min = U256::min_value(&env);
907 assert_eq!(min, U256::from_u32(&env, 0));
908
909 let one = U256::from_u32(&env, 1);
910 assert_eq!(min.checked_sub(&one), None);
911 assert!(min.checked_add(&one).is_some());
912 }
913
914 #[test]
915 fn test_u256_max() {
916 let env = Env::default();
917
918 let max = U256::max_value(&env);
919 assert_eq!(
920 max,
921 U256::from_parts(&env, u64::MAX, u64::MAX, u64::MAX, u64::MAX)
922 );
923
924 let u128_max = U256::from_u128(&env, u128::MAX);
925 assert!(max > u128_max);
926
927 let one = U256::from_u32(&env, 1);
928 assert_eq!(max.checked_add(&one), None);
929 assert!(max.checked_sub(&one).is_some());
930 }
931
932 #[test]
933 fn test_u256_checked_arith() {
934 let env = Env::default();
935
936 let u1 = U256::from_u32(&env, 6);
937 let u2 = U256::from_u32(&env, 3);
938 assert_eq!(u1.checked_add(&u2), Some(U256::from_u32(&env, 9)));
939 assert_eq!(u1.checked_sub(&u2), Some(U256::from_u32(&env, 3)));
940 assert_eq!(u1.checked_mul(&u2), Some(U256::from_u32(&env, 18)));
941 assert_eq!(u1.checked_div(&u2), Some(U256::from_u32(&env, 2)));
942 assert_eq!(u1.checked_pow(2), Some(U256::from_u32(&env, 36)));
943 assert_eq!(u1.checked_shl(2), Some(U256::from_u32(&env, 24)));
944 assert_eq!(u1.checked_shr(1), Some(U256::from_u32(&env, 3)));
945
946 let u3 = U256::from_u32(&env, 7);
947 let u4 = U256::from_u32(&env, 4);
948 assert_eq!(u3.checked_rem_euclid(&u4), Some(U256::from_u32(&env, 3)));
949 }
950
951 #[test]
952 fn test_u256_checked_arith_overflow() {
953 let env = Env::default();
954
955 let zero = U256::from_u32(&env, 0);
956 let one = U256::from_u32(&env, 1);
957 let two = U256::from_u32(&env, 2);
958 let max = U256::max_value(&env);
959 assert_eq!(max.checked_add(&one), None);
960 assert_eq!(zero.checked_sub(&one), None);
961 assert_eq!(max.checked_mul(&two), None);
962 assert_eq!(one.checked_div(&zero), None);
963 assert_eq!(max.checked_pow(2), None);
964 assert_eq!(one.checked_shl(256), None);
965 assert_eq!(one.checked_shr(256), None);
966 assert_eq!(one.checked_rem_euclid(&zero), None);
967
968 let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
969 let one_from_parts = U256::from_parts(&env, 0, 0, 0, 1);
970 assert_eq!(one.checked_div(&zero_from_parts), None);
971 assert_eq!(zero.checked_sub(&one_from_parts), None);
972 }
973
974 #[test]
975 fn test_u256_is_zero() {
976 let env = Env::default();
977
978 let zero = U256::from_u32(&env, 0);
979 let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
980 let non_zero = U256::from_u32(&env, 1);
981
982 assert!(zero.is_zero());
983 assert!(zero_from_parts.is_zero());
984 assert!(!non_zero.is_zero());
985 }
986
987 #[test]
988 fn test_i256_arith() {
989 let env = Env::default();
990
991 let i1 = I256::from_i32(&env, -6);
992 let i2 = I256::from_i32(&env, 3);
993 assert_eq!(i1.add(&i2), I256::from_i32(&env, -3));
994 assert_eq!(i1.sub(&i2), I256::from_i32(&env, -9));
995 assert_eq!(i1.mul(&i2), I256::from_i32(&env, -18));
996 assert_eq!(i1.div(&i2), I256::from_i32(&env, -2));
997 assert_eq!(i1.pow(2), I256::from_i32(&env, 36));
998 assert_eq!(i1.shl(2), I256::from_i32(&env, -24));
999 assert_eq!(i1.shr(1), I256::from_i32(&env, -3));
1000
1001 let u3 = I256::from_i32(&env, -7);
1002 let u4 = I256::from_i32(&env, 4);
1003 assert_eq!(u3.rem_euclid(&u4), I256::from_i32(&env, 1));
1004 }
1005
1006 #[test]
1007 fn test_i256_min() {
1008 let env = Env::default();
1009
1010 let min = I256::min_value(&env);
1011 assert_eq!(min, I256::from_parts(&env, i64::MIN, 0, 0, 0));
1012
1013 let i128_min = I256::from_i128(&env, i128::MIN);
1014 assert!(min < i128_min);
1015
1016 let one = I256::from_i32(&env, 1);
1017 assert_eq!(min.checked_sub(&one), None);
1018 assert!(min.checked_add(&one).is_some());
1019 }
1020
1021 #[test]
1022 fn test_i256_max() {
1023 let env = Env::default();
1024
1025 let max = I256::max_value(&env);
1026 assert_eq!(
1027 max,
1028 I256::from_parts(&env, i64::MAX, u64::MAX, u64::MAX, u64::MAX)
1029 );
1030
1031 let i128_max = I256::from_i128(&env, i128::MAX);
1032 assert!(max > i128_max);
1033
1034 let one = I256::from_i32(&env, 1);
1035 assert_eq!(max.checked_add(&one), None);
1036 assert!(max.checked_sub(&one).is_some());
1037 }
1038
1039 #[test]
1040 fn test_i256_checked_arith() {
1041 let env = Env::default();
1042
1043 let i1 = I256::from_i32(&env, -6);
1044 let i2 = I256::from_i32(&env, 3);
1045 assert_eq!(i1.checked_add(&i2), Some(I256::from_i32(&env, -3)));
1046 assert_eq!(i1.checked_sub(&i2), Some(I256::from_i32(&env, -9)));
1047 assert_eq!(i1.checked_mul(&i2), Some(I256::from_i32(&env, -18)));
1048 assert_eq!(i1.checked_div(&i2), Some(I256::from_i32(&env, -2)));
1049 assert_eq!(i1.checked_pow(2), Some(I256::from_i32(&env, 36)));
1050 assert_eq!(i1.checked_shl(2), Some(I256::from_i32(&env, -24)));
1051 assert_eq!(i1.checked_shr(1), Some(I256::from_i32(&env, -3)));
1052
1053 let u3 = I256::from_i32(&env, -7);
1054 let u4 = I256::from_i32(&env, 4);
1055 assert_eq!(u3.checked_rem_euclid(&u4), Some(I256::from_i32(&env, 1)));
1056 }
1057
1058 #[test]
1059 fn test_i256_checked_arith_overflow() {
1060 let env = Env::default();
1061
1062 let zero = I256::from_i32(&env, 0);
1063 let one = I256::from_i32(&env, 1);
1064 let negative_one = I256::from_i32(&env, -1);
1065 let two = I256::from_i32(&env, 2);
1066 let max = I256::max_value(&env);
1067 let min = I256::min_value(&env);
1068 assert_eq!(max.checked_add(&one), None);
1069 assert_eq!(min.checked_sub(&one), None);
1070 assert_eq!(max.checked_mul(&two), None);
1071 assert_eq!(one.checked_div(&zero), None);
1072 assert_eq!(min.checked_div(&negative_one), None);
1073 assert_eq!(max.checked_pow(2), None);
1074 assert_eq!(one.checked_shl(256), None);
1075 assert_eq!(one.checked_shr(256), None);
1076 assert_eq!(one.checked_rem_euclid(&zero), None);
1077
1078 let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
1079 let one_from_parts = I256::from_parts(&env, 0, 0, 0, 1);
1080 assert_eq!(one.checked_div(&zero_from_parts), None);
1081 assert_eq!(min.checked_sub(&one_from_parts), None);
1082 }
1083
1084 #[test]
1085 fn test_i256_is_zero() {
1086 let env = Env::default();
1087
1088 let zero = I256::from_i32(&env, 0);
1089 let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
1090 let non_zero = I256::from_i32(&env, 1);
1091
1092 assert!(zero.is_zero());
1093 assert!(zero_from_parts.is_zero());
1094 assert!(!non_zero.is_zero());
1095 }
1096
1097 #[test]
1098 fn test_i256_is_neg_one() {
1099 let env = Env::default();
1100
1101 let negative_one = I256::from_i32(&env, -1);
1102 let negative_one_from_parts = I256::from_parts(&env, -1, u64::MAX, u64::MAX, u64::MAX);
1103 let negative_two = I256::from_i32(&env, -2);
1104
1105 assert!(negative_one.is_neg_one());
1106 assert!(negative_one_from_parts.is_neg_one());
1107 assert!(!negative_two.is_neg_one());
1108 }
1109
1110 #[test]
1111 fn test_i256_is_div_overflow() {
1112 let env = Env::default();
1113
1114 let zero = I256::from_i32(&env, 0);
1115 let negative_one = I256::from_i32(&env, -1);
1116 let min = I256::min_value(&env);
1117
1118 assert!(!zero.is_div_overflow(&negative_one));
1119
1120 assert!(negative_one.is_div_overflow(&zero));
1121 assert!(min.is_div_overflow(&negative_one));
1122 }
1123}