1use crate::{
4 Decimal, NumericValue,
5 integer_wire::{self, IntegerWire},
6};
7use candid::{CandidType, Int as WrappedInt};
8use derive_more::{Add, AddAssign, Sub, SubAssign};
9use num_bigint::BigInt;
10use serde::{Deserialize, Serialize};
11use std::{
12 fmt,
13 iter::{Product, Sum},
14 ops::{Div, DivAssign, Mul, MulAssign, Neg},
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 IntBig(WrappedInt);
42
43impl IntBig {
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 let bits = self.magnitude_bits();
54 let negative_boundary = self.0.0.sign() == num_bigint::Sign::Minus
58 && bits.is_multiple_of(7)
59 && self.0.0.trailing_zeros() == Some(bits.saturating_sub(1));
60 bits / 7 + 1 - u64::from(negative_boundary)
61 }
62
63 #[must_use]
65 pub const fn from_candid(value: WrappedInt) -> Self {
66 Self(value)
67 }
68
69 #[must_use]
71 pub fn from_bigint(value: BigInt) -> Self {
72 Self::from_candid(WrappedInt::from(value))
73 }
74
75 pub fn sign_and_u32_digits(
77 &self,
78 ) -> (
79 bool,
80 impl DoubleEndedIterator<Item = u32> + ExactSizeIterator + '_,
81 ) {
82 (
83 self.0.0.sign() == num_bigint::Sign::Minus,
84 self.0.0.magnitude().iter_u32_digits(),
85 )
86 }
87
88 #[must_use]
90 pub fn to_i128(&self) -> Option<i128> {
91 let big = &self.0.0;
92
93 i128::try_from(big).ok()
94 }
95
96 #[must_use]
98 pub fn to_i64(&self) -> Option<i64> {
99 let big = &self.0.0;
100
101 i64::try_from(big).ok()
102 }
103
104 #[must_use]
106 pub fn to_leb128(&self) -> Vec<u8> {
107 self.leb128_bytes().collect()
108 }
109
110 pub fn leb128_bytes(&self) -> impl Iterator<Item = u8> + '_ {
112 let (negative, limbs) = self.sign_and_u32_digits();
113 crate::leb128::bytes(limbs, negative, self.leb128_len())
114 }
115
116 pub(crate) fn to_sign_and_magnitude_bytes(&self) -> (bool, Vec<u8>) {
117 let (sign, magnitude) = self.0.0.to_bytes_be();
118 (sign == num_bigint::Sign::Minus, magnitude)
119 }
120
121 pub(crate) fn from_sign_and_magnitude_bytes(negative: bool, magnitude: &[u8]) -> Self {
122 let sign = if magnitude.is_empty() {
123 num_bigint::Sign::NoSign
124 } else if negative {
125 num_bigint::Sign::Minus
126 } else {
127 num_bigint::Sign::Plus
128 };
129 Self::from_bigint(BigInt::from_bytes_be(sign, magnitude))
130 }
131
132 #[must_use]
134 pub fn saturating_add(self, rhs: Self) -> Self {
135 Self(self.0 + rhs.0)
136 }
137
138 #[must_use]
140 pub fn saturating_sub(self, rhs: Self) -> Self {
141 Self(self.0 - rhs.0)
142 }
143}
144
145impl<'de> Deserialize<'de> for IntBig {
146 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
147 integer_wire::deserialize_integer(deserializer)
148 }
149}
150
151impl fmt::Display for IntBig {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 self.0.fmt(f)
154 }
155}
156
157impl FromStr for IntBig {
158 type Err = <WrappedInt as FromStr>::Err;
159
160 fn from_str(s: &str) -> Result<Self, Self::Err> {
161 WrappedInt::from_str(s).map(Self::from_candid)
162 }
163}
164
165impl Div for IntBig {
166 type Output = Self;
167
168 fn div(self, other: Self) -> Self::Output {
169 Self(self.0 / other.0)
170 }
171}
172
173impl DivAssign for IntBig {
174 fn div_assign(&mut self, other: Self) {
175 self.0 /= other.0;
176 }
177}
178
179impl From<i32> for IntBig {
180 fn from(n: i32) -> Self {
181 Self::from_candid(WrappedInt::from(n))
182 }
183}
184
185impl From<i64> for IntBig {
186 fn from(n: i64) -> Self {
187 Self::from_candid(WrappedInt::from(n))
188 }
189}
190
191impl IntegerWire for IntBig {
192 fn from_signed(value: i64) -> Option<Self> {
193 Some(Self::from(value))
194 }
195
196 fn from_unsigned(value: u64) -> Self {
197 Self::from_candid(WrappedInt::from(value))
198 }
199
200 fn from_wire_bytes(value: &[u8]) -> Option<Self> {
201 integer_wire::signed_body(value)
202 .map(|body| Self::from_bigint(BigInt::from_signed_bytes_le(body)))
203 }
204}
205
206impl Mul for IntBig {
207 type Output = Self;
208
209 fn mul(self, other: Self) -> Self::Output {
210 Self(self.0 * other.0)
211 }
212}
213
214impl MulAssign for IntBig {
215 fn mul_assign(&mut self, other: Self) {
216 self.0 *= other.0;
217 }
218}
219
220impl Neg for IntBig {
221 type Output = Self;
222
223 fn neg(self) -> Self::Output {
224 Self::from_bigint(-self.0.0)
225 }
226}
227
228impl NumericValue for IntBig {
229 fn try_to_decimal(&self) -> Option<Decimal> {
230 self.to_i128().and_then(Decimal::from_i128)
231 }
232
233 fn try_from_decimal(value: Decimal) -> Option<Self> {
234 value.to_i128().map(WrappedInt::from).map(Self::from_candid)
235 }
236}
237
238impl Product for IntBig {
239 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
240 iter.fold(Self::from(1), |acc, value| acc * value)
241 }
242}
243
244impl Serialize for IntBig {
245 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
246 if serializer.is_human_readable() {
247 return serializer.collect_str(&self.0.0);
248 }
249 if let Some(value) = self.to_i64() {
250 return serializer.serialize_i64(value);
251 }
252 if let Ok(value) = u64::try_from(&self.0.0) {
253 return serializer.serialize_u64(value);
254 }
255 let (negative, limbs) = self.sign_and_u32_digits();
256 serializer.serialize_bytes(&integer_wire::signed_bytes(negative, limbs))
257 }
258}
259
260impl Sum for IntBig {
261 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
262 iter.fold(Self::default(), |acc, x| acc + x)
263 }
264}