1use crate::{Decimal, NumericValue};
4use candid::{CandidType, Nat as WrappedNat};
5use derive_more::{Add, AddAssign, Sub, SubAssign};
6use num_bigint::BigUint;
7use serde::{Deserialize, Serialize};
8use std::{
9 fmt,
10 iter::Sum,
11 ops::{Div, DivAssign, Mul, MulAssign},
12 str::FromStr,
13};
14
15#[derive(
20 Add,
21 AddAssign,
22 CandidType,
23 Clone,
24 Debug,
25 Default,
26 Eq,
27 PartialEq,
28 Hash,
29 Ord,
30 PartialOrd,
31 Serialize,
32 Deserialize,
33 Sub,
34 SubAssign,
35)]
36pub struct NatBig(WrappedNat);
38
39impl NatBig {
40 #[must_use]
42 pub const fn from_candid(value: WrappedNat) -> Self {
43 Self(value)
44 }
45
46 #[must_use]
48 pub fn from_biguint(value: BigUint) -> Self {
49 Self::from_candid(WrappedNat::from(value))
50 }
51
52 #[must_use]
56 pub fn u32_digits(&self) -> Vec<u32> {
57 self.0.0.to_u32_digits()
58 }
59
60 #[must_use]
62 pub fn to_u128(&self) -> Option<u128> {
63 let big = &self.0.0;
64
65 u128::try_from(big).ok()
66 }
67
68 #[must_use]
70 pub fn to_u64(&self) -> Option<u64> {
71 let big = &self.0.0;
72
73 u64::try_from(big).ok()
74 }
75
76 #[must_use]
78 pub fn to_leb128(&self) -> Vec<u8> {
79 let mut out = Vec::new();
80 let encoded = self.0.encode(&mut out);
81 debug_assert!(
82 encoded.is_ok(),
83 "Vec-backed unsigned LEB128 encoding failed"
84 );
85
86 out
87 }
88
89 #[must_use]
91 pub fn saturating_add(self, rhs: Self) -> Self {
92 Self(self.0 + rhs.0)
93 }
94
95 #[must_use]
97 pub fn saturating_sub(self, rhs: Self) -> Self {
98 if rhs > self {
99 return Self::default();
100 }
101
102 Self(self.0 - rhs.0)
103 }
104}
105
106impl fmt::Display for NatBig {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 self.0.fmt(f)
109 }
110}
111
112impl FromStr for NatBig {
113 type Err = <WrappedNat as FromStr>::Err;
114
115 fn from_str(s: &str) -> Result<Self, Self::Err> {
116 WrappedNat::from_str(s).map(Self::from_candid)
117 }
118}
119
120impl Div for NatBig {
121 type Output = Self;
122
123 fn div(self, other: Self) -> Self::Output {
124 Self(self.0 / other.0)
125 }
126}
127
128impl DivAssign for NatBig {
129 fn div_assign(&mut self, other: Self) {
130 self.0 /= other.0;
131 }
132}
133
134impl From<u64> for NatBig {
135 fn from(n: u64) -> Self {
136 Self::from_candid(WrappedNat::from(n))
137 }
138}
139
140impl From<u32> for NatBig {
141 fn from(n: u32) -> Self {
142 Self::from_candid(WrappedNat::from(n))
143 }
144}
145
146impl Mul for NatBig {
147 type Output = Self;
148
149 fn mul(self, other: Self) -> Self::Output {
150 Self(self.0 * other.0)
151 }
152}
153
154impl MulAssign for NatBig {
155 fn mul_assign(&mut self, other: Self) {
156 self.0 *= other.0;
157 }
158}
159
160impl NumericValue for NatBig {
161 fn try_to_decimal(&self) -> Option<Decimal> {
162 self.to_u128().and_then(Decimal::from_u128)
163 }
164
165 fn try_from_decimal(value: Decimal) -> Option<Self> {
166 value.to_u128().map(WrappedNat::from).map(Self::from_candid)
167 }
168}
169
170impl Sum for NatBig {
171 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
172 iter.fold(Self::default(), |acc, x| acc + x)
173 }
174}
175
176impl TryFrom<i32> for NatBig {
177 type Error = std::num::TryFromIntError;
178
179 fn try_from(n: i32) -> Result<Self, Self::Error> {
180 let v = Self::from_candid(WrappedNat::from(u32::try_from(n)?));
181 Ok(v)
182 }
183}