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::{Product, 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 fn magnitude_bits(&self) -> u64 {
43 self.0.0.bits()
44 }
45
46 #[must_use]
48 pub fn leb128_len(&self) -> u64 {
49 self.magnitude_bits().div_ceil(7).max(1)
50 }
51
52 #[must_use]
54 pub const fn from_candid(value: WrappedNat) -> Self {
55 Self(value)
56 }
57
58 #[must_use]
60 pub fn from_biguint(value: BigUint) -> Self {
61 Self::from_candid(WrappedNat::from(value))
62 }
63
64 #[must_use]
66 pub fn u32_digits(&self) -> impl DoubleEndedIterator<Item = u32> + ExactSizeIterator + '_ {
67 self.0.0.iter_u32_digits()
68 }
69
70 #[must_use]
72 pub fn to_u128(&self) -> Option<u128> {
73 let big = &self.0.0;
74
75 u128::try_from(big).ok()
76 }
77
78 #[must_use]
80 pub fn to_u64(&self) -> Option<u64> {
81 let big = &self.0.0;
82
83 u64::try_from(big).ok()
84 }
85
86 #[must_use]
88 pub fn to_leb128(&self) -> Vec<u8> {
89 self.leb128_bytes().collect()
90 }
91
92 pub fn leb128_bytes(&self) -> impl Iterator<Item = u8> + '_ {
94 crate::leb128::bytes(self.u32_digits(), false, self.leb128_len())
95 }
96
97 pub(crate) fn to_magnitude_bytes(&self) -> Vec<u8> {
98 self.0.0.to_bytes_be()
99 }
100
101 pub(crate) fn from_magnitude_bytes(magnitude: &[u8]) -> Self {
102 Self::from_biguint(BigUint::from_bytes_be(magnitude))
103 }
104
105 #[must_use]
107 pub fn saturating_add(self, rhs: Self) -> Self {
108 Self(self.0 + rhs.0)
109 }
110
111 #[must_use]
113 pub fn saturating_sub(self, rhs: Self) -> Self {
114 if rhs > self {
115 return Self::default();
116 }
117
118 Self(self.0 - rhs.0)
119 }
120}
121
122impl fmt::Display for NatBig {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 self.0.fmt(f)
125 }
126}
127
128impl FromStr for NatBig {
129 type Err = <WrappedNat as FromStr>::Err;
130
131 fn from_str(s: &str) -> Result<Self, Self::Err> {
132 WrappedNat::from_str(s).map(Self::from_candid)
133 }
134}
135
136impl Div for NatBig {
137 type Output = Self;
138
139 fn div(self, other: Self) -> Self::Output {
140 Self(self.0 / other.0)
141 }
142}
143
144impl DivAssign for NatBig {
145 fn div_assign(&mut self, other: Self) {
146 self.0 /= other.0;
147 }
148}
149
150impl From<u64> for NatBig {
151 fn from(n: u64) -> Self {
152 Self::from_candid(WrappedNat::from(n))
153 }
154}
155
156impl From<u32> for NatBig {
157 fn from(n: u32) -> Self {
158 Self::from_candid(WrappedNat::from(n))
159 }
160}
161
162impl Mul for NatBig {
163 type Output = Self;
164
165 fn mul(self, other: Self) -> Self::Output {
166 Self(self.0 * other.0)
167 }
168}
169
170impl MulAssign for NatBig {
171 fn mul_assign(&mut self, other: Self) {
172 self.0 *= other.0;
173 }
174}
175
176impl NumericValue for NatBig {
177 fn try_to_decimal(&self) -> Option<Decimal> {
178 self.to_u128().and_then(Decimal::from_u128)
179 }
180
181 fn try_from_decimal(value: Decimal) -> Option<Self> {
182 value.to_u128().map(WrappedNat::from).map(Self::from_candid)
183 }
184}
185
186impl Product for NatBig {
187 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
188 iter.fold(Self::from(1_u32), |acc, value| acc * value)
189 }
190}
191
192impl Sum for NatBig {
193 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
194 iter.fold(Self::default(), |acc, x| acc + x)
195 }
196}
197
198impl TryFrom<i32> for NatBig {
199 type Error = std::num::TryFromIntError;
200
201 fn try_from(n: i32) -> Result<Self, Self::Error> {
202 let v = Self::from_candid(WrappedNat::from(u32::try_from(n)?));
203 Ok(v)
204 }
205}