Skip to main content

soroban_sdk/
num.rs

1use core::{cmp::Ordering, convert::Infallible, fmt::Debug};
2
3use super::{
4    env::internal::{
5        DurationSmall, DurationVal, Env as _, I256Small, I256Val, TimepointSmall, TimepointVal,
6        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                // FIXME: properly print it when we have the conversion functions
20                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                    // Compare small numbers.
45                    (Ok(self_num), Ok(other_num)) => self_num.cmp(&other_num),
46                    // The object-to-small number comparisons are handled by `obj_cmp`,
47                    // so it's safe to handle all the other cases using it.
48                    _ => {
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                // This conversion occurs only in test utilities, and theoretically all
119                // values should convert to an ScVal because the Env won't let the host
120                // type to exist otherwise, unwrapping. Even if there are edge cases
121                // that don't, this is a trade off for a better test developer
122                // experience.
123                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            /// Converts a `Val` known to be of this type into `Self` without
155            /// env-based conversion. The caller must guarantee the `Val` is of
156            /// the correct type; only a cheap tag check is performed.
157            #[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/// U256 holds a 256-bit unsigned integer.
186///
187/// ### Examples
188///
189/// ```
190/// use soroban_sdk::{U256, Env};
191///
192/// let env = Env::default();
193/// let u1 = U256::from_u32(&env, 6);
194/// let u2 = U256::from_u32(&env, 3);
195/// assert_eq!(u1.add(&u2), U256::from_u32(&env, 9));
196/// ```
197#[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    /// Returns the smallest value that can be represented by this type (0).
209    pub fn min_value(env: &Env) -> Self {
210        Self::from_u32(env, 0)
211    }
212
213    /// Returns the largest value that can be represented by this type (2^256 - 1).
214    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: Bytes = Bytes::from_array(env, &u.to_be_bytes());
231        let mut bytes: Bytes = Bytes::from_array(env, &[0u8; 16]);
232        bytes.append(&lo);
233        Self::from_be_bytes(env, &bytes)
234    }
235
236    pub fn from_parts(env: &Env, hi_hi: u64, hi_lo: u64, lo_hi: u64, lo_lo: u64) -> Self {
237        let obj = env
238            .obj_from_u256_pieces(hi_hi, hi_lo, lo_hi, lo_lo)
239            .unwrap_infallible();
240        U256 {
241            env: env.clone(),
242            val: obj.into(),
243        }
244    }
245
246    pub fn from_be_bytes(env: &Env, bytes: &Bytes) -> Self {
247        let val = env
248            .u256_val_from_be_bytes(bytes.to_object())
249            .unwrap_infallible();
250        U256 {
251            env: env.clone(),
252            val,
253        }
254    }
255
256    pub fn to_u128(&self) -> Option<u128> {
257        let be_bytes = self.to_be_bytes();
258        let be_bytes_hi: [u8; 16] = be_bytes.slice(0..16).try_into().unwrap();
259        let be_bytes_lo: [u8; 16] = be_bytes.slice(16..32).try_into().unwrap();
260        if u128::from_be_bytes(be_bytes_hi) == 0 {
261            Some(u128::from_be_bytes(be_bytes_lo))
262        } else {
263            None
264        }
265    }
266
267    pub fn to_be_bytes(&self) -> Bytes {
268        let obj = self
269            .env
270            .u256_val_to_be_bytes(self.to_val_type())
271            .unwrap_infallible();
272        unsafe { Bytes::unchecked_new(self.env.clone(), obj) }
273    }
274
275    pub fn add(&self, other: &U256) -> U256 {
276        let val = self.env.u256_add(self.val, other.val).unwrap_infallible();
277        U256 {
278            env: self.env.clone(),
279            val,
280        }
281    }
282
283    pub fn sub(&self, other: &U256) -> U256 {
284        let val = self.env.u256_sub(self.val, other.val).unwrap_infallible();
285        U256 {
286            env: self.env.clone(),
287            val,
288        }
289    }
290
291    pub fn mul(&self, other: &U256) -> U256 {
292        let val = self.env.u256_mul(self.val, other.val).unwrap_infallible();
293        U256 {
294            env: self.env.clone(),
295            val,
296        }
297    }
298
299    pub fn div(&self, other: &U256) -> U256 {
300        let val = self.env.u256_div(self.val, other.val).unwrap_infallible();
301        U256 {
302            env: self.env.clone(),
303            val,
304        }
305    }
306
307    pub fn rem_euclid(&self, other: &U256) -> U256 {
308        let val = self
309            .env
310            .u256_rem_euclid(self.val, other.val)
311            .unwrap_infallible();
312        U256 {
313            env: self.env.clone(),
314            val,
315        }
316    }
317
318    pub fn pow(&self, pow: u32) -> U256 {
319        let val = self.env.u256_pow(self.val, pow.into()).unwrap_infallible();
320        U256 {
321            env: self.env.clone(),
322            val,
323        }
324    }
325
326    pub fn shl(&self, bits: u32) -> U256 {
327        let val = self.env.u256_shl(self.val, bits.into()).unwrap_infallible();
328        U256 {
329            env: self.env.clone(),
330            val,
331        }
332    }
333
334    pub fn shr(&self, bits: u32) -> U256 {
335        let val = self.env.u256_shr(self.val, bits.into()).unwrap_infallible();
336        U256 {
337            env: self.env.clone(),
338            val,
339        }
340    }
341
342    /// Performs checked addition. Returns `None` if overflow occurred.
343    pub fn checked_add(&self, other: &U256) -> Option<U256> {
344        let val = self
345            .env
346            .u256_checked_add(self.val, other.val)
347            .unwrap_infallible();
348        if val.is_void() {
349            None
350        } else {
351            Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
352        }
353    }
354
355    /// Performs checked subtraction. Returns `None` if overflow occurred.
356    pub fn checked_sub(&self, other: &U256) -> Option<U256> {
357        let val = self
358            .env
359            .u256_checked_sub(self.val, other.val)
360            .unwrap_infallible();
361        if val.is_void() {
362            None
363        } else {
364            Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
365        }
366    }
367
368    /// Performs checked multiplication. Returns `None` if overflow occurred.
369    pub fn checked_mul(&self, other: &U256) -> Option<U256> {
370        let val = self
371            .env
372            .u256_checked_mul(self.val, other.val)
373            .unwrap_infallible();
374        if val.is_void() {
375            None
376        } else {
377            Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
378        }
379    }
380
381    /// Performs checked exponentiation. Returns `None` if overflow occurred.
382    pub fn checked_pow(&self, pow: u32) -> Option<U256> {
383        let val = self
384            .env
385            .u256_checked_pow(self.val, pow.into())
386            .unwrap_infallible();
387        if val.is_void() {
388            None
389        } else {
390            Some(unsafe { U256::unchecked_from_val(self.env.clone(), val) })
391        }
392    }
393
394    /// Performs checked division. Returns `None` if `other` is zero.
395    pub fn checked_div(&self, other: &U256) -> Option<U256> {
396        if other.is_zero() {
397            return None;
398        }
399        Some(self.div(other))
400    }
401
402    /// Performs checked Euclidean remainder. Returns `None` if `other` is zero.
403    pub fn checked_rem_euclid(&self, other: &U256) -> Option<U256> {
404        if other.is_zero() {
405            return None;
406        }
407        Some(self.rem_euclid(other))
408    }
409
410    /// Performs checked left shift. Returns `None` if `bits >= 256`.
411    pub fn checked_shl(&self, bits: u32) -> Option<U256> {
412        if bits >= Self::BITS {
413            return None;
414        }
415        Some(self.shl(bits))
416    }
417
418    /// Performs checked right shift. Returns `None` if `bits >= 256`.
419    pub fn checked_shr(&self, bits: u32) -> Option<U256> {
420        if bits >= Self::BITS {
421            return None;
422        }
423        Some(self.shr(bits))
424    }
425}
426
427/// I256 holds a 256-bit signed integer.
428///
429/// ### Examples
430///
431/// ```
432/// use soroban_sdk::{I256, Env};
433///
434/// let env = Env::default();
435///
436/// let i1 = I256::from_i32(&env, -6);
437/// let i2 = I256::from_i32(&env, 3);
438/// assert_eq!(i1.add(&i2), I256::from_i32(&env, -3));
439/// ```
440#[derive(Clone)]
441pub struct I256 {
442    env: Env,
443    val: I256Val,
444}
445
446impl_num_wrapping_val_type!(I256, I256Val, I256Small);
447
448impl I256 {
449    pub const BITS: u32 = 256;
450
451    /// Returns the smallest value that can be represented by this type (-2^255).
452    pub fn min_value(env: &Env) -> Self {
453        Self::from_parts(env, i64::MIN, 0, 0, 0)
454    }
455
456    /// Returns the largest value that can be represented by this type (2^255 - 1).
457    pub fn max_value(env: &Env) -> Self {
458        Self::from_parts(env, i64::MAX, u64::MAX, u64::MAX, u64::MAX)
459    }
460
461    fn is_zero(&self) -> bool {
462        *self == I256::from_i32(&self.env, 0)
463    }
464
465    fn is_neg_one(&self) -> bool {
466        *self == I256::from_i32(&self.env, -1)
467    }
468
469    pub fn from_i32(env: &Env, i: i32) -> Self {
470        I256 {
471            env: env.clone(),
472            val: I256Val::from_i32(i),
473        }
474    }
475
476    pub fn from_i128(env: &Env, i: i128) -> Self {
477        let lo: Bytes = Bytes::from_array(env, &i.to_be_bytes());
478        if i < 0 {
479            let mut i256_bytes: Bytes = Bytes::from_array(env, &[255_u8; 16]);
480            i256_bytes.append(&lo);
481            Self::from_be_bytes(env, &i256_bytes)
482        } else {
483            let mut i256_bytes: Bytes = Bytes::from_array(env, &[0_u8; 16]);
484            i256_bytes.append(&lo);
485            Self::from_be_bytes(env, &i256_bytes)
486        }
487    }
488
489    pub fn from_parts(env: &Env, hi_hi: i64, hi_lo: u64, lo_hi: u64, lo_lo: u64) -> Self {
490        let obj = env
491            .obj_from_i256_pieces(hi_hi, hi_lo, lo_hi, lo_lo)
492            .unwrap_infallible();
493        I256 {
494            env: env.clone(),
495            val: obj.into(),
496        }
497    }
498
499    pub fn from_be_bytes(env: &Env, bytes: &Bytes) -> Self {
500        let val = env
501            .i256_val_from_be_bytes(bytes.to_object())
502            .unwrap_infallible();
503        I256 {
504            env: env.clone(),
505            val,
506        }
507    }
508
509    pub fn to_i128(&self) -> Option<i128> {
510        let be_bytes = self.to_be_bytes();
511        let be_bytes_hi: [u8; 16] = be_bytes.slice(0..16).try_into().unwrap();
512        let be_bytes_lo: [u8; 16] = be_bytes.slice(16..32).try_into().unwrap();
513        let i128_hi = i128::from_be_bytes(be_bytes_hi);
514        let i128_lo = i128::from_be_bytes(be_bytes_lo);
515        if (i128_hi == 0 && i128_lo >= 0) || (i128_hi == -1 && i128_lo < 0) {
516            Some(i128_lo)
517        } else {
518            None
519        }
520    }
521
522    pub fn to_be_bytes(&self) -> Bytes {
523        let obj = self
524            .env
525            .i256_val_to_be_bytes(self.to_val_type())
526            .unwrap_infallible();
527        unsafe { Bytes::unchecked_new(self.env.clone(), obj) }
528    }
529
530    pub fn add(&self, other: &I256) -> I256 {
531        let val = self.env.i256_add(self.val, other.val).unwrap_infallible();
532        I256 {
533            env: self.env.clone(),
534            val,
535        }
536    }
537
538    pub fn sub(&self, other: &I256) -> I256 {
539        let val = self.env.i256_sub(self.val, other.val).unwrap_infallible();
540        I256 {
541            env: self.env.clone(),
542            val,
543        }
544    }
545
546    pub fn mul(&self, other: &I256) -> I256 {
547        let val = self.env.i256_mul(self.val, other.val).unwrap_infallible();
548        I256 {
549            env: self.env.clone(),
550            val,
551        }
552    }
553
554    pub fn div(&self, other: &I256) -> I256 {
555        let val = self.env.i256_div(self.val, other.val).unwrap_infallible();
556        I256 {
557            env: self.env.clone(),
558            val,
559        }
560    }
561
562    pub fn rem_euclid(&self, other: &I256) -> I256 {
563        let val = self
564            .env
565            .i256_rem_euclid(self.val, other.val)
566            .unwrap_infallible();
567        I256 {
568            env: self.env.clone(),
569            val,
570        }
571    }
572
573    pub fn pow(&self, pow: u32) -> I256 {
574        let val = self.env.i256_pow(self.val, pow.into()).unwrap_infallible();
575        I256 {
576            env: self.env.clone(),
577            val,
578        }
579    }
580
581    pub fn shl(&self, bits: u32) -> I256 {
582        let val = self.env.i256_shl(self.val, bits.into()).unwrap_infallible();
583        I256 {
584            env: self.env.clone(),
585            val,
586        }
587    }
588
589    pub fn shr(&self, bits: u32) -> I256 {
590        let val = self.env.i256_shr(self.val, bits.into()).unwrap_infallible();
591        I256 {
592            env: self.env.clone(),
593            val,
594        }
595    }
596
597    /// Performs checked addition. Returns `None` if overflow occurred.
598    pub fn checked_add(&self, other: &I256) -> Option<I256> {
599        let val = self
600            .env
601            .i256_checked_add(self.val, other.val)
602            .unwrap_infallible();
603        if val.is_void() {
604            None
605        } else {
606            Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
607        }
608    }
609
610    /// Performs checked subtraction. Returns `None` if overflow occurred.
611    pub fn checked_sub(&self, other: &I256) -> Option<I256> {
612        let val = self
613            .env
614            .i256_checked_sub(self.val, other.val)
615            .unwrap_infallible();
616        if val.is_void() {
617            None
618        } else {
619            Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
620        }
621    }
622
623    /// Performs checked multiplication. Returns `None` if overflow occurred.
624    pub fn checked_mul(&self, other: &I256) -> Option<I256> {
625        let val = self
626            .env
627            .i256_checked_mul(self.val, other.val)
628            .unwrap_infallible();
629        if val.is_void() {
630            None
631        } else {
632            Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
633        }
634    }
635
636    /// Performs checked exponentiation. Returns `None` if overflow occurred.
637    pub fn checked_pow(&self, pow: u32) -> Option<I256> {
638        let val = self
639            .env
640            .i256_checked_pow(self.val, pow.into())
641            .unwrap_infallible();
642        if val.is_void() {
643            None
644        } else {
645            Some(unsafe { I256::unchecked_from_val(self.env.clone(), val) })
646        }
647    }
648
649    /// Returns `true` if dividing `self` by `other` would overflow or divide by zero.
650    /// This covers: `other == 0`, or `self == I256::MIN && other == -1`.
651    fn is_div_overflow(&self, other: &I256) -> bool {
652        if other.is_zero() {
653            return true;
654        }
655        if other.is_neg_one() {
656            let min = I256::min_value(&self.env);
657            if *self == min {
658                return true;
659            }
660        }
661        false
662    }
663
664    /// Performs checked division. Returns `None` if `other` is zero, or if
665    /// `self` is `I256::MIN` and `other` is `-1` (overflow).
666    pub fn checked_div(&self, other: &I256) -> Option<I256> {
667        if self.is_div_overflow(other) {
668            return None;
669        }
670        Some(self.div(other))
671    }
672
673    /// Performs checked Euclidean remainder. Returns `None` if `other` is zero,
674    /// or if `self` is `I256::MIN` and `other` is `-1` (overflow in intermediate
675    /// division).
676    pub fn checked_rem_euclid(&self, other: &I256) -> Option<I256> {
677        if self.is_div_overflow(other) {
678            return None;
679        }
680        Some(self.rem_euclid(other))
681    }
682
683    /// Performs checked left shift. Returns `None` if `bits >= 256`.
684    pub fn checked_shl(&self, bits: u32) -> Option<I256> {
685        if bits >= Self::BITS {
686            return None;
687        }
688        Some(self.shl(bits))
689    }
690
691    /// Performs checked right shift. Returns `None` if `bits >= 256`.
692    pub fn checked_shr(&self, bits: u32) -> Option<I256> {
693        if bits >= Self::BITS {
694            return None;
695        }
696        Some(self.shr(bits))
697    }
698}
699
700#[doc = "Timepoint holds a 64-bit unsigned integer."]
701#[derive(Clone)]
702pub struct Timepoint {
703    env: Env,
704    val: TimepointVal,
705}
706
707impl_num_wrapping_val_type!(Timepoint, TimepointVal, TimepointSmall);
708
709impl Timepoint {
710    /// Create a Timepoint from a unix time in seconds, the time in seconds
711    /// since January 1, 1970 UTC.
712    pub fn from_unix(env: &Env, seconds: u64) -> Timepoint {
713        let val = TimepointVal::try_from_val(env, &seconds).unwrap_optimized();
714        Timepoint {
715            env: env.clone(),
716            val,
717        }
718    }
719
720    /// Returns the Timepoint as unix time in seconds, the time in seconds since
721    /// January 1, 1970 UTC.
722    pub fn to_unix(&self) -> u64 {
723        u64::try_from_val(self.env(), &self.to_val_type()).unwrap_optimized()
724    }
725}
726
727#[doc = "Duration holds a 64-bit unsigned integer."]
728#[derive(Clone)]
729pub struct Duration {
730    env: Env,
731    val: DurationVal,
732}
733
734impl_num_wrapping_val_type!(Duration, DurationVal, DurationSmall);
735
736impl Duration {
737    /// Create a Duration from seconds.
738    pub fn from_seconds(env: &Env, seconds: u64) -> Duration {
739        let val = DurationVal::try_from_val(env, &seconds).unwrap_optimized();
740        Duration {
741            env: env.clone(),
742            val,
743        }
744    }
745
746    /// Returns the Duration as seconds.
747    pub fn to_seconds(&self) -> u64 {
748        u64::try_from_val(self.env(), &self.to_val_type()).unwrap_optimized()
749    }
750}
751
752#[cfg(test)]
753mod test {
754    use super::*;
755
756    #[test]
757    fn test_u256_roundtrip() {
758        let env = Env::default();
759
760        let u1 = U256::from_u32(&env, 12345);
761        let bytes = u1.to_be_bytes();
762        let u2 = U256::from_be_bytes(&env, &bytes);
763        assert_eq!(u1, u2);
764    }
765
766    #[test]
767    fn test_u256_u128_conversion() {
768        let env = Env::default();
769
770        // positive
771        let start = u128::MAX / 7;
772        let from = U256::from_u128(&env, start);
773        let end = from.to_u128().unwrap();
774        assert_eq!(start, end);
775
776        let over_u128 = from.mul(&U256::from_u32(&env, 8));
777        let failure = over_u128.to_u128();
778        assert_eq!(failure, None);
779
780        // zero
781        let start = 0_u128;
782        let from = U256::from_u128(&env, start);
783        let end = from.to_u128().unwrap();
784        assert_eq!(start, end);
785    }
786
787    #[test]
788    fn test_i256_roundtrip() {
789        let env = Env::default();
790
791        let i1 = I256::from_i32(&env, -12345);
792        let bytes = i1.to_be_bytes();
793        let i2 = I256::from_be_bytes(&env, &bytes);
794        assert_eq!(i1, i2);
795    }
796
797    #[test]
798    fn test_i256_i128_conversion() {
799        let env = Env::default();
800
801        // positive
802        let start = i128::MAX / 7;
803        let from = I256::from_i128(&env, start);
804        let end = from.to_i128().unwrap();
805        assert_eq!(start, end);
806
807        let over_i128 = from.mul(&I256::from_i32(&env, 8));
808        let failure = over_i128.to_i128();
809        assert_eq!(failure, None);
810
811        // negative
812        let start = i128::MIN / 7;
813        let from = I256::from_i128(&env, start);
814        let end = from.to_i128().unwrap();
815        assert_eq!(start, end);
816
817        let over_i128 = from.mul(&I256::from_i32(&env, 8));
818        let failure = over_i128.to_i128();
819        assert_eq!(failure, None);
820
821        // zero
822        let start = 0_i128;
823        let from = I256::from_i128(&env, start);
824        let end = from.to_i128().unwrap();
825        assert_eq!(start, end);
826    }
827
828    #[test]
829    fn test_timepoint_roundtrip() {
830        let env = Env::default();
831
832        let tp = Timepoint::from_unix(&env, 123);
833        let u = tp.to_unix();
834        assert_eq!(u, 123);
835    }
836
837    #[test]
838    fn test_duration_roundtrip() {
839        let env = Env::default();
840
841        let tp = Duration::from_seconds(&env, 123);
842        let u = tp.to_seconds();
843        assert_eq!(u, 123);
844    }
845
846    #[test]
847    fn test_u256_arith() {
848        let env = Env::default();
849
850        let u1 = U256::from_u32(&env, 6);
851        let u2 = U256::from_u32(&env, 3);
852        assert_eq!(u1.add(&u2), U256::from_u32(&env, 9));
853        assert_eq!(u1.sub(&u2), U256::from_u32(&env, 3));
854        assert_eq!(u1.mul(&u2), U256::from_u32(&env, 18));
855        assert_eq!(u1.div(&u2), U256::from_u32(&env, 2));
856        assert_eq!(u1.pow(2), U256::from_u32(&env, 36));
857        assert_eq!(u1.shl(2), U256::from_u32(&env, 24));
858        assert_eq!(u1.shr(1), U256::from_u32(&env, 3));
859
860        let u3 = U256::from_u32(&env, 7);
861        let u4 = U256::from_u32(&env, 4);
862        assert_eq!(u3.rem_euclid(&u4), U256::from_u32(&env, 3));
863    }
864
865    #[test]
866    fn test_u256_min() {
867        let env = Env::default();
868
869        let min = U256::min_value(&env);
870        assert_eq!(min, U256::from_u32(&env, 0));
871
872        let one = U256::from_u32(&env, 1);
873        assert_eq!(min.checked_sub(&one), None);
874        assert!(min.checked_add(&one).is_some());
875    }
876
877    #[test]
878    fn test_u256_max() {
879        let env = Env::default();
880
881        let max = U256::max_value(&env);
882        assert_eq!(
883            max,
884            U256::from_parts(&env, u64::MAX, u64::MAX, u64::MAX, u64::MAX)
885        );
886
887        let u128_max = U256::from_u128(&env, u128::MAX);
888        assert!(max > u128_max);
889
890        let one = U256::from_u32(&env, 1);
891        assert_eq!(max.checked_add(&one), None);
892        assert!(max.checked_sub(&one).is_some());
893    }
894
895    #[test]
896    fn test_u256_checked_arith() {
897        let env = Env::default();
898
899        let u1 = U256::from_u32(&env, 6);
900        let u2 = U256::from_u32(&env, 3);
901        assert_eq!(u1.checked_add(&u2), Some(U256::from_u32(&env, 9)));
902        assert_eq!(u1.checked_sub(&u2), Some(U256::from_u32(&env, 3)));
903        assert_eq!(u1.checked_mul(&u2), Some(U256::from_u32(&env, 18)));
904        assert_eq!(u1.checked_div(&u2), Some(U256::from_u32(&env, 2)));
905        assert_eq!(u1.checked_pow(2), Some(U256::from_u32(&env, 36)));
906        assert_eq!(u1.checked_shl(2), Some(U256::from_u32(&env, 24)));
907        assert_eq!(u1.checked_shr(1), Some(U256::from_u32(&env, 3)));
908
909        let u3 = U256::from_u32(&env, 7);
910        let u4 = U256::from_u32(&env, 4);
911        assert_eq!(u3.checked_rem_euclid(&u4), Some(U256::from_u32(&env, 3)));
912    }
913
914    #[test]
915    fn test_u256_checked_arith_overflow() {
916        let env = Env::default();
917
918        let zero = U256::from_u32(&env, 0);
919        let one = U256::from_u32(&env, 1);
920        let two = U256::from_u32(&env, 2);
921        let max = U256::max_value(&env);
922        assert_eq!(max.checked_add(&one), None);
923        assert_eq!(zero.checked_sub(&one), None);
924        assert_eq!(max.checked_mul(&two), None);
925        assert_eq!(one.checked_div(&zero), None);
926        assert_eq!(max.checked_pow(2), None);
927        assert_eq!(one.checked_shl(256), None);
928        assert_eq!(one.checked_shr(256), None);
929        assert_eq!(one.checked_rem_euclid(&zero), None);
930
931        let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
932        let one_from_parts = U256::from_parts(&env, 0, 0, 0, 1);
933        assert_eq!(one.checked_div(&zero_from_parts), None);
934        assert_eq!(zero.checked_sub(&one_from_parts), None);
935    }
936
937    #[test]
938    fn test_u256_is_zero() {
939        let env = Env::default();
940
941        let zero = U256::from_u32(&env, 0);
942        let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
943        let non_zero = U256::from_u32(&env, 1);
944
945        assert!(zero.is_zero());
946        assert!(zero_from_parts.is_zero());
947        assert!(!non_zero.is_zero());
948    }
949
950    #[test]
951    fn test_i256_arith() {
952        let env = Env::default();
953
954        let i1 = I256::from_i32(&env, -6);
955        let i2 = I256::from_i32(&env, 3);
956        assert_eq!(i1.add(&i2), I256::from_i32(&env, -3));
957        assert_eq!(i1.sub(&i2), I256::from_i32(&env, -9));
958        assert_eq!(i1.mul(&i2), I256::from_i32(&env, -18));
959        assert_eq!(i1.div(&i2), I256::from_i32(&env, -2));
960        assert_eq!(i1.pow(2), I256::from_i32(&env, 36));
961        assert_eq!(i1.shl(2), I256::from_i32(&env, -24));
962        assert_eq!(i1.shr(1), I256::from_i32(&env, -3));
963
964        let u3 = I256::from_i32(&env, -7);
965        let u4 = I256::from_i32(&env, 4);
966        assert_eq!(u3.rem_euclid(&u4), I256::from_i32(&env, 1));
967    }
968
969    #[test]
970    fn test_i256_min() {
971        let env = Env::default();
972
973        let min = I256::min_value(&env);
974        assert_eq!(min, I256::from_parts(&env, i64::MIN, 0, 0, 0));
975
976        let i128_min = I256::from_i128(&env, i128::MIN);
977        assert!(min < i128_min);
978
979        let one = I256::from_i32(&env, 1);
980        assert_eq!(min.checked_sub(&one), None);
981        assert!(min.checked_add(&one).is_some());
982    }
983
984    #[test]
985    fn test_i256_max() {
986        let env = Env::default();
987
988        let max = I256::max_value(&env);
989        assert_eq!(
990            max,
991            I256::from_parts(&env, i64::MAX, u64::MAX, u64::MAX, u64::MAX)
992        );
993
994        let i128_max = I256::from_i128(&env, i128::MAX);
995        assert!(max > i128_max);
996
997        let one = I256::from_i32(&env, 1);
998        assert_eq!(max.checked_add(&one), None);
999        assert!(max.checked_sub(&one).is_some());
1000    }
1001
1002    #[test]
1003    fn test_i256_checked_arith() {
1004        let env = Env::default();
1005
1006        let i1 = I256::from_i32(&env, -6);
1007        let i2 = I256::from_i32(&env, 3);
1008        assert_eq!(i1.checked_add(&i2), Some(I256::from_i32(&env, -3)));
1009        assert_eq!(i1.checked_sub(&i2), Some(I256::from_i32(&env, -9)));
1010        assert_eq!(i1.checked_mul(&i2), Some(I256::from_i32(&env, -18)));
1011        assert_eq!(i1.checked_div(&i2), Some(I256::from_i32(&env, -2)));
1012        assert_eq!(i1.checked_pow(2), Some(I256::from_i32(&env, 36)));
1013        assert_eq!(i1.checked_shl(2), Some(I256::from_i32(&env, -24)));
1014        assert_eq!(i1.checked_shr(1), Some(I256::from_i32(&env, -3)));
1015
1016        let u3 = I256::from_i32(&env, -7);
1017        let u4 = I256::from_i32(&env, 4);
1018        assert_eq!(u3.checked_rem_euclid(&u4), Some(I256::from_i32(&env, 1)));
1019    }
1020
1021    #[test]
1022    fn test_i256_checked_arith_overflow() {
1023        let env = Env::default();
1024
1025        let zero = I256::from_i32(&env, 0);
1026        let one = I256::from_i32(&env, 1);
1027        let negative_one = I256::from_i32(&env, -1);
1028        let two = I256::from_i32(&env, 2);
1029        let max = I256::max_value(&env);
1030        let min = I256::min_value(&env);
1031        assert_eq!(max.checked_add(&one), None);
1032        assert_eq!(min.checked_sub(&one), None);
1033        assert_eq!(max.checked_mul(&two), None);
1034        assert_eq!(one.checked_div(&zero), None);
1035        assert_eq!(min.checked_div(&negative_one), None);
1036        assert_eq!(max.checked_pow(2), None);
1037        assert_eq!(one.checked_shl(256), None);
1038        assert_eq!(one.checked_shr(256), None);
1039        assert_eq!(one.checked_rem_euclid(&zero), None);
1040
1041        let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
1042        let one_from_parts = I256::from_parts(&env, 0, 0, 0, 1);
1043        assert_eq!(one.checked_div(&zero_from_parts), None);
1044        assert_eq!(min.checked_sub(&one_from_parts), None);
1045    }
1046
1047    #[test]
1048    fn test_i256_is_zero() {
1049        let env = Env::default();
1050
1051        let zero = I256::from_i32(&env, 0);
1052        let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
1053        let non_zero = I256::from_i32(&env, 1);
1054
1055        assert!(zero.is_zero());
1056        assert!(zero_from_parts.is_zero());
1057        assert!(!non_zero.is_zero());
1058    }
1059
1060    #[test]
1061    fn test_i256_is_neg_one() {
1062        let env = Env::default();
1063
1064        let negative_one = I256::from_i32(&env, -1);
1065        let negative_one_from_parts = I256::from_parts(&env, -1, u64::MAX, u64::MAX, u64::MAX);
1066        let negative_two = I256::from_i32(&env, -2);
1067
1068        assert!(negative_one.is_neg_one());
1069        assert!(negative_one_from_parts.is_neg_one());
1070        assert!(!negative_two.is_neg_one());
1071    }
1072
1073    #[test]
1074    fn test_i256_is_div_overflow() {
1075        let env = Env::default();
1076
1077        let zero = I256::from_i32(&env, 0);
1078        let negative_one = I256::from_i32(&env, -1);
1079        let min = I256::min_value(&env);
1080
1081        assert!(!zero.is_div_overflow(&negative_one));
1082
1083        assert!(negative_one.is_div_overflow(&zero));
1084        assert!(min.is_div_overflow(&negative_one));
1085    }
1086}