1use crate::{
4 Decimal, NumericValue,
5 integer_wire::{self, IntegerWire},
6};
7use candid::{CandidType, Nat as WrappedNat};
8use derive_more::{Add, AddAssign, Sub, SubAssign};
9use num_bigint::BigUint;
10use serde::{Deserialize, Serialize};
11use std::{
12 fmt,
13 iter::{Product, Sum},
14 ops::{Div, DivAssign, Mul, MulAssign},
15 str::FromStr,
16};
17
18#[derive(
23 Add,
24 AddAssign,
25 CandidType,
26 Clone,
27 Debug,
28 Default,
29 Eq,
30 PartialEq,
31 Hash,
32 Ord,
33 PartialOrd,
34 Sub,
35 SubAssign,
36)]
37pub struct NatBig(WrappedNat);
42
43impl NatBig {
44 #[must_use]
46 pub fn magnitude_bits(&self) -> u64 {
47 self.0.0.bits()
48 }
49
50 #[must_use]
52 pub fn leb128_len(&self) -> u64 {
53 self.magnitude_bits().div_ceil(7).max(1)
54 }
55
56 #[must_use]
58 pub const fn from_candid(value: WrappedNat) -> Self {
59 Self(value)
60 }
61
62 #[must_use]
64 pub fn from_biguint(value: BigUint) -> Self {
65 Self::from_candid(WrappedNat::from(value))
66 }
67
68 #[must_use]
70 pub fn u32_digits(&self) -> impl DoubleEndedIterator<Item = u32> + ExactSizeIterator + '_ {
71 self.0.0.iter_u32_digits()
72 }
73
74 #[must_use]
76 pub fn to_u128(&self) -> Option<u128> {
77 let big = &self.0.0;
78
79 u128::try_from(big).ok()
80 }
81
82 #[must_use]
84 pub fn to_u64(&self) -> Option<u64> {
85 let big = &self.0.0;
86
87 u64::try_from(big).ok()
88 }
89
90 #[must_use]
92 pub fn to_leb128(&self) -> Vec<u8> {
93 self.leb128_bytes().collect()
94 }
95
96 pub fn leb128_bytes(&self) -> impl Iterator<Item = u8> + '_ {
98 crate::leb128::bytes(self.u32_digits(), false, self.leb128_len())
99 }
100
101 pub(crate) fn to_magnitude_bytes(&self) -> Vec<u8> {
102 self.0.0.to_bytes_be()
103 }
104
105 pub(crate) fn from_magnitude_bytes(magnitude: &[u8]) -> Self {
106 Self::from_biguint(BigUint::from_bytes_be(magnitude))
107 }
108
109 #[must_use]
111 pub fn saturating_add(self, rhs: Self) -> Self {
112 Self(self.0 + rhs.0)
113 }
114
115 #[must_use]
117 pub fn saturating_sub(self, rhs: Self) -> Self {
118 if rhs > self {
119 return Self::default();
120 }
121
122 Self(self.0 - rhs.0)
123 }
124}
125
126impl<'de> Deserialize<'de> for NatBig {
127 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
128 integer_wire::deserialize_integer(deserializer)
129 }
130}
131
132impl fmt::Display for NatBig {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 self.0.fmt(f)
135 }
136}
137
138impl FromStr for NatBig {
139 type Err = <WrappedNat as FromStr>::Err;
140
141 fn from_str(s: &str) -> Result<Self, Self::Err> {
142 WrappedNat::from_str(s).map(Self::from_candid)
143 }
144}
145
146impl Div for NatBig {
147 type Output = Self;
148
149 fn div(self, other: Self) -> Self::Output {
150 Self(self.0 / other.0)
151 }
152}
153
154impl DivAssign for NatBig {
155 fn div_assign(&mut self, other: Self) {
156 self.0 /= other.0;
157 }
158}
159
160impl From<u64> for NatBig {
161 fn from(n: u64) -> Self {
162 Self::from_candid(WrappedNat::from(n))
163 }
164}
165
166impl From<u32> for NatBig {
167 fn from(n: u32) -> Self {
168 Self::from_candid(WrappedNat::from(n))
169 }
170}
171
172impl IntegerWire for NatBig {
173 fn from_signed(value: i64) -> Option<Self> {
174 u64::try_from(value).ok().map(Self::from)
175 }
176
177 fn from_unsigned(value: u64) -> Self {
178 Self::from(value)
179 }
180
181 fn from_wire_bytes(value: &[u8]) -> Option<Self> {
182 integer_wire::unsigned_body(value)
183 .map(|body| Self::from_biguint(BigUint::from_bytes_le(body)))
184 }
185}
186
187impl Mul for NatBig {
188 type Output = Self;
189
190 fn mul(self, other: Self) -> Self::Output {
191 Self(self.0 * other.0)
192 }
193}
194
195impl MulAssign for NatBig {
196 fn mul_assign(&mut self, other: Self) {
197 self.0 *= other.0;
198 }
199}
200
201impl NumericValue for NatBig {
202 fn try_to_decimal(&self) -> Option<Decimal> {
203 self.to_u128().and_then(Decimal::from_u128)
204 }
205
206 fn try_from_decimal(value: Decimal) -> Option<Self> {
207 value.to_u128().map(WrappedNat::from).map(Self::from_candid)
208 }
209}
210
211impl Product for NatBig {
212 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
213 iter.fold(Self::from(1_u32), |acc, value| acc * value)
214 }
215}
216
217impl Serialize for NatBig {
218 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
219 if serializer.is_human_readable() {
220 return serializer.collect_str(&self.0.0);
221 }
222 if let Some(value) = self.to_u64() {
223 return serializer.serialize_u64(value);
224 }
225 serializer.serialize_bytes(&integer_wire::unsigned_bytes(self.u32_digits()))
226 }
227}
228
229impl Sum for NatBig {
230 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
231 iter.fold(Self::default(), |acc, x| acc + x)
232 }
233}
234
235impl TryFrom<i32> for NatBig {
236 type Error = std::num::TryFromIntError;
237
238 fn try_from(n: i32) -> Result<Self, Self::Error> {
239 let v = Self::from_candid(WrappedNat::from(u32::try_from(n)?));
240 Ok(v)
241 }
242}