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