1use core::{cmp::Ordering, convert::Infallible, fmt::Debug};
2
3use super::{
4 env::internal::{
5 DurationSmall, DurationVal, Env as _, EnvBase as _, I256Small, I256Val, TimepointSmall,
6 TimepointVal, 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)]
155 pub fn env(&self) -> &Env {
156 &self.env
157 }
158
159 pub fn as_val(&self) -> &Val {
160 self.val.as_val()
161 }
162
163 pub fn to_val(&self) -> Val {
164 self.val.to_val()
165 }
166
167 pub fn to_val_type(&self) -> $val {
168 self.val
169 }
170 }
171 };
172}
173
174#[derive(Clone)]
187pub struct U256 {
188 env: Env,
189 val: U256Val,
190}
191
192impl_num_wrapping_val_type!(U256, U256Val, U256Small);
193
194impl U256 {
195 pub fn from_u32(env: &Env, u: u32) -> Self {
196 U256 {
197 env: env.clone(),
198 val: U256Val::from_u32(u),
199 }
200 }
201
202 pub fn from_u128(env: &Env, u: u128) -> Self {
203 let lo: Bytes = Bytes::from_array(env, &u.to_be_bytes());
204 let mut bytes: Bytes = Bytes::from_array(env, &[0u8; 16]);
205 bytes.append(&lo);
206 Self::from_be_bytes(env, &bytes)
207 }
208
209 pub fn from_parts(env: &Env, hi_hi: u64, hi_lo: u64, lo_hi: u64, lo_lo: u64) -> Self {
210 let obj = env
211 .obj_from_u256_pieces(hi_hi, hi_lo, lo_hi, lo_lo)
212 .unwrap_infallible();
213 U256 {
214 env: env.clone(),
215 val: obj.into(),
216 }
217 }
218
219 pub fn from_be_bytes(env: &Env, bytes: &Bytes) -> Self {
220 env.check_same_env(bytes.env()).unwrap_infallible();
221 let val = env
222 .u256_val_from_be_bytes(bytes.to_object())
223 .unwrap_infallible();
224 U256 {
225 env: env.clone(),
226 val,
227 }
228 }
229
230 pub fn to_u128(&self) -> Option<u128> {
231 let be_bytes = self.to_be_bytes();
232 let be_bytes_hi: [u8; 16] = be_bytes.slice(0..16).try_into().unwrap();
233 let be_bytes_lo: [u8; 16] = be_bytes.slice(16..32).try_into().unwrap();
234 if u128::from_be_bytes(be_bytes_hi) == 0 {
235 Some(u128::from_be_bytes(be_bytes_lo))
236 } else {
237 None
238 }
239 }
240
241 pub fn to_be_bytes(&self) -> Bytes {
242 let obj = self
243 .env
244 .u256_val_to_be_bytes(self.to_val_type())
245 .unwrap_infallible();
246 unsafe { Bytes::unchecked_new(self.env.clone(), obj) }
247 }
248
249 pub fn add(&self, other: &U256) -> U256 {
250 self.env.check_same_env(&other.env).unwrap_infallible();
251 let val = self.env.u256_add(self.val, other.val).unwrap_infallible();
252 U256 {
253 env: self.env.clone(),
254 val,
255 }
256 }
257
258 pub fn sub(&self, other: &U256) -> U256 {
259 self.env.check_same_env(&other.env).unwrap_infallible();
260 let val = self.env.u256_sub(self.val, other.val).unwrap_infallible();
261 U256 {
262 env: self.env.clone(),
263 val,
264 }
265 }
266
267 pub fn mul(&self, other: &U256) -> U256 {
268 self.env.check_same_env(&other.env).unwrap_infallible();
269 let val = self.env.u256_mul(self.val, other.val).unwrap_infallible();
270 U256 {
271 env: self.env.clone(),
272 val,
273 }
274 }
275
276 pub fn div(&self, other: &U256) -> U256 {
277 self.env.check_same_env(&other.env).unwrap_infallible();
278 let val = self.env.u256_div(self.val, other.val).unwrap_infallible();
279 U256 {
280 env: self.env.clone(),
281 val,
282 }
283 }
284
285 pub fn rem_euclid(&self, other: &U256) -> U256 {
286 self.env.check_same_env(&other.env).unwrap_infallible();
287 let val = self
288 .env
289 .u256_rem_euclid(self.val, other.val)
290 .unwrap_infallible();
291 U256 {
292 env: self.env.clone(),
293 val,
294 }
295 }
296
297 pub fn pow(&self, pow: u32) -> U256 {
298 let val = self.env.u256_pow(self.val, pow.into()).unwrap_infallible();
299 U256 {
300 env: self.env.clone(),
301 val,
302 }
303 }
304
305 pub fn shl(&self, bits: u32) -> U256 {
306 let val = self.env.u256_shl(self.val, bits.into()).unwrap_infallible();
307 U256 {
308 env: self.env.clone(),
309 val,
310 }
311 }
312
313 pub fn shr(&self, bits: u32) -> U256 {
314 let val = self.env.u256_shr(self.val, bits.into()).unwrap_infallible();
315 U256 {
316 env: self.env.clone(),
317 val,
318 }
319 }
320}
321
322#[derive(Clone)]
336pub struct I256 {
337 env: Env,
338 val: I256Val,
339}
340
341impl_num_wrapping_val_type!(I256, I256Val, I256Small);
342
343impl I256 {
344 pub fn from_i32(env: &Env, i: i32) -> Self {
345 I256 {
346 env: env.clone(),
347 val: I256Val::from_i32(i),
348 }
349 }
350
351 pub fn from_i128(env: &Env, i: i128) -> Self {
352 let lo: Bytes = Bytes::from_array(env, &i.to_be_bytes());
353 if i < 0 {
354 let mut i256_bytes: Bytes = Bytes::from_array(env, &[255_u8; 16]);
355 i256_bytes.append(&lo);
356 Self::from_be_bytes(env, &i256_bytes)
357 } else {
358 let mut i256_bytes: Bytes = Bytes::from_array(env, &[0_u8; 16]);
359 i256_bytes.append(&lo);
360 Self::from_be_bytes(env, &i256_bytes)
361 }
362 }
363
364 pub fn from_parts(env: &Env, hi_hi: i64, hi_lo: u64, lo_hi: u64, lo_lo: u64) -> Self {
365 let obj = env
366 .obj_from_i256_pieces(hi_hi, hi_lo, lo_hi, lo_lo)
367 .unwrap_infallible();
368 I256 {
369 env: env.clone(),
370 val: obj.into(),
371 }
372 }
373
374 pub fn from_be_bytes(env: &Env, bytes: &Bytes) -> Self {
375 env.check_same_env(bytes.env()).unwrap_infallible();
376 let val = env
377 .i256_val_from_be_bytes(bytes.to_object())
378 .unwrap_infallible();
379 I256 {
380 env: env.clone(),
381 val,
382 }
383 }
384
385 pub fn to_i128(&self) -> Option<i128> {
386 let be_bytes = self.to_be_bytes();
387 let be_bytes_hi: [u8; 16] = be_bytes.slice(0..16).try_into().unwrap();
388 let be_bytes_lo: [u8; 16] = be_bytes.slice(16..32).try_into().unwrap();
389 let i128_hi = i128::from_be_bytes(be_bytes_hi);
390 let i128_lo = i128::from_be_bytes(be_bytes_lo);
391 if (i128_hi == 0 && i128_lo >= 0) || (i128_hi == -1 && i128_lo < 0) {
392 Some(i128_lo)
393 } else {
394 None
395 }
396 }
397
398 pub fn to_be_bytes(&self) -> Bytes {
399 let obj = self
400 .env
401 .i256_val_to_be_bytes(self.to_val_type())
402 .unwrap_infallible();
403 unsafe { Bytes::unchecked_new(self.env.clone(), obj) }
404 }
405
406 pub fn add(&self, other: &I256) -> I256 {
407 self.env.check_same_env(&other.env).unwrap_infallible();
408 let val = self.env.i256_add(self.val, other.val).unwrap_infallible();
409 I256 {
410 env: self.env.clone(),
411 val,
412 }
413 }
414
415 pub fn sub(&self, other: &I256) -> I256 {
416 self.env.check_same_env(&other.env).unwrap_infallible();
417 let val = self.env.i256_sub(self.val, other.val).unwrap_infallible();
418 I256 {
419 env: self.env.clone(),
420 val,
421 }
422 }
423
424 pub fn mul(&self, other: &I256) -> I256 {
425 self.env.check_same_env(&other.env).unwrap_infallible();
426 let val = self.env.i256_mul(self.val, other.val).unwrap_infallible();
427 I256 {
428 env: self.env.clone(),
429 val,
430 }
431 }
432
433 pub fn div(&self, other: &I256) -> I256 {
434 self.env.check_same_env(&other.env).unwrap_infallible();
435 let val = self.env.i256_div(self.val, other.val).unwrap_infallible();
436 I256 {
437 env: self.env.clone(),
438 val,
439 }
440 }
441
442 pub fn rem_euclid(&self, other: &I256) -> I256 {
443 self.env.check_same_env(&other.env).unwrap_infallible();
444 let val = self
445 .env
446 .i256_rem_euclid(self.val, other.val)
447 .unwrap_infallible();
448 I256 {
449 env: self.env.clone(),
450 val,
451 }
452 }
453
454 pub fn pow(&self, pow: u32) -> I256 {
455 let val = self.env.i256_pow(self.val, pow.into()).unwrap_infallible();
456 I256 {
457 env: self.env.clone(),
458 val,
459 }
460 }
461
462 pub fn shl(&self, bits: u32) -> I256 {
463 let val = self.env.i256_shl(self.val, bits.into()).unwrap_infallible();
464 I256 {
465 env: self.env.clone(),
466 val,
467 }
468 }
469
470 pub fn shr(&self, bits: u32) -> I256 {
471 let val = self.env.i256_shr(self.val, bits.into()).unwrap_infallible();
472 I256 {
473 env: self.env.clone(),
474 val,
475 }
476 }
477}
478
479#[doc = "Timepoint holds a 64-bit unsigned integer."]
480#[derive(Clone)]
481pub struct Timepoint {
482 env: Env,
483 val: TimepointVal,
484}
485
486impl_num_wrapping_val_type!(Timepoint, TimepointVal, TimepointSmall);
487
488impl Timepoint {
489 pub fn from_unix(env: &Env, seconds: u64) -> Timepoint {
492 let val = TimepointVal::try_from_val(env, &seconds).unwrap_optimized();
493 Timepoint {
494 env: env.clone(),
495 val,
496 }
497 }
498
499 pub fn to_unix(&self) -> u64 {
502 u64::try_from_val(self.env(), &self.to_val_type()).unwrap_optimized()
503 }
504}
505
506#[doc = "Duration holds a 64-bit unsigned integer."]
507#[derive(Clone)]
508pub struct Duration {
509 env: Env,
510 val: DurationVal,
511}
512
513impl_num_wrapping_val_type!(Duration, DurationVal, DurationSmall);
514
515impl Duration {
516 pub fn from_seconds(env: &Env, seconds: u64) -> Duration {
518 let val = DurationVal::try_from_val(env, &seconds).unwrap_optimized();
519 Duration {
520 env: env.clone(),
521 val,
522 }
523 }
524
525 pub fn to_seconds(&self) -> u64 {
527 u64::try_from_val(self.env(), &self.to_val_type()).unwrap_optimized()
528 }
529}
530
531#[cfg(test)]
532mod test {
533 use super::*;
534
535 #[test]
536 fn test_u256_roundtrip() {
537 let env = Env::default();
538
539 let u1 = U256::from_u32(&env, 12345);
540 let bytes = u1.to_be_bytes();
541 let u2 = U256::from_be_bytes(&env, &bytes);
542 assert_eq!(u1, u2);
543 }
544
545 #[test]
546 fn test_u256_u128_conversion() {
547 let env = Env::default();
548
549 let start = u128::MAX / 7;
551 let from = U256::from_u128(&env, start);
552 let end = from.to_u128().unwrap();
553 assert_eq!(start, end);
554
555 let over_u128 = from.mul(&U256::from_u32(&env, 8));
556 let failure = over_u128.to_u128();
557 assert_eq!(failure, None);
558
559 let start = 0_u128;
561 let from = U256::from_u128(&env, start);
562 let end = from.to_u128().unwrap();
563 assert_eq!(start, end);
564 }
565
566 #[test]
567 fn test_i256_roundtrip() {
568 let env = Env::default();
569
570 let i1 = I256::from_i32(&env, -12345);
571 let bytes = i1.to_be_bytes();
572 let i2 = I256::from_be_bytes(&env, &bytes);
573 assert_eq!(i1, i2);
574 }
575
576 #[test]
577 fn test_i256_i128_conversion() {
578 let env = Env::default();
579
580 let start = i128::MAX / 7;
582 let from = I256::from_i128(&env, start);
583 let end = from.to_i128().unwrap();
584 assert_eq!(start, end);
585
586 let over_i128 = from.mul(&I256::from_i32(&env, 8));
587 let failure = over_i128.to_i128();
588 assert_eq!(failure, None);
589
590 let start = i128::MIN / 7;
592 let from = I256::from_i128(&env, start);
593 let end = from.to_i128().unwrap();
594 assert_eq!(start, end);
595
596 let over_i128 = from.mul(&I256::from_i32(&env, 8));
597 let failure = over_i128.to_i128();
598 assert_eq!(failure, None);
599
600 let start = 0_i128;
602 let from = I256::from_i128(&env, start);
603 let end = from.to_i128().unwrap();
604 assert_eq!(start, end);
605 }
606
607 #[test]
608 fn test_timepoint_roundtrip() {
609 let env = Env::default();
610
611 let tp = Timepoint::from_unix(&env, 123);
612 let u = tp.to_unix();
613 assert_eq!(u, 123);
614 }
615
616 #[test]
617 fn test_duration_roundtrip() {
618 let env = Env::default();
619
620 let tp = Duration::from_seconds(&env, 123);
621 let u = tp.to_seconds();
622 assert_eq!(u, 123);
623 }
624
625 #[test]
626 fn test_u256_arith() {
627 let env = Env::default();
628
629 let u1 = U256::from_u32(&env, 6);
630 let u2 = U256::from_u32(&env, 3);
631 assert_eq!(u1.add(&u2), U256::from_u32(&env, 9));
632 assert_eq!(u1.sub(&u2), U256::from_u32(&env, 3));
633 assert_eq!(u1.mul(&u2), U256::from_u32(&env, 18));
634 assert_eq!(u1.div(&u2), U256::from_u32(&env, 2));
635 assert_eq!(u1.pow(2), U256::from_u32(&env, 36));
636 assert_eq!(u1.shl(2), U256::from_u32(&env, 24));
637 assert_eq!(u1.shr(1), U256::from_u32(&env, 3));
638
639 let u3 = U256::from_u32(&env, 7);
640 let u4 = U256::from_u32(&env, 4);
641 assert_eq!(u3.rem_euclid(&u4), U256::from_u32(&env, 3));
642 }
643
644 #[test]
645 fn test_i256_arith() {
646 let env = Env::default();
647
648 let i1 = I256::from_i32(&env, -6);
649 let i2 = I256::from_i32(&env, 3);
650 assert_eq!(i1.add(&i2), I256::from_i32(&env, -3));
651 assert_eq!(i1.sub(&i2), I256::from_i32(&env, -9));
652 assert_eq!(i1.mul(&i2), I256::from_i32(&env, -18));
653 assert_eq!(i1.div(&i2), I256::from_i32(&env, -2));
654 assert_eq!(i1.pow(2), I256::from_i32(&env, 36));
655 assert_eq!(i1.shl(2), I256::from_i32(&env, -24));
656 assert_eq!(i1.shr(1), I256::from_i32(&env, -3));
657
658 let u3 = I256::from_i32(&env, -7);
659 let u4 = I256::from_i32(&env, 4);
660 assert_eq!(u3.rem_euclid(&u4), I256::from_i32(&env, 1));
661 }
662}