1use crate::{Decimal, NumericValue};
4use candid::{CandidType, Int as WrappedInt};
5use derive_more::{Add, AddAssign, Sub, SubAssign};
6use num_bigint::BigInt;
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 IntBig(WrappedInt);
38
39impl IntBig {
40 #[must_use]
42 pub const fn from_candid(value: WrappedInt) -> Self {
43 Self(value)
44 }
45
46 #[must_use]
48 pub fn from_bigint(value: BigInt) -> Self {
49 Self::from_candid(WrappedInt::from(value))
50 }
51
52 #[must_use]
56 pub fn sign_and_u32_digits(&self) -> (bool, Vec<u32>) {
57 (
58 self.0.0.cmp(&0.into()).is_lt(),
59 self.0.0.magnitude().to_u32_digits(),
60 )
61 }
62
63 #[must_use]
65 pub fn to_i128(&self) -> Option<i128> {
66 let big = &self.0.0;
67
68 i128::try_from(big).ok()
69 }
70
71 #[must_use]
73 pub fn to_i64(&self) -> Option<i64> {
74 let big = &self.0.0;
75
76 i64::try_from(big).ok()
77 }
78
79 #[must_use]
81 pub fn to_leb128(&self) -> Vec<u8> {
82 let mut out = Vec::new();
83 let encoded = self.0.encode(&mut out);
84 debug_assert!(encoded.is_ok(), "Vec-backed signed LEB128 encoding failed");
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 Self(self.0 - rhs.0)
99 }
100}
101
102impl fmt::Display for IntBig {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 self.0.fmt(f)
105 }
106}
107
108impl FromStr for IntBig {
109 type Err = <WrappedInt as FromStr>::Err;
110
111 fn from_str(s: &str) -> Result<Self, Self::Err> {
112 WrappedInt::from_str(s).map(Self::from_candid)
113 }
114}
115
116impl Div for IntBig {
117 type Output = Self;
118
119 fn div(self, other: Self) -> Self::Output {
120 Self(self.0 / other.0)
121 }
122}
123
124impl DivAssign for IntBig {
125 fn div_assign(&mut self, other: Self) {
126 self.0 /= other.0;
127 }
128}
129
130impl From<i32> for IntBig {
131 fn from(n: i32) -> Self {
132 Self::from_candid(WrappedInt::from(n))
133 }
134}
135
136impl From<i64> for IntBig {
137 fn from(n: i64) -> Self {
138 Self::from_candid(WrappedInt::from(n))
139 }
140}
141
142impl Mul for IntBig {
143 type Output = Self;
144
145 fn mul(self, other: Self) -> Self::Output {
146 Self(self.0 * other.0)
147 }
148}
149
150impl MulAssign for IntBig {
151 fn mul_assign(&mut self, other: Self) {
152 self.0 *= other.0;
153 }
154}
155
156impl NumericValue for IntBig {
157 fn try_to_decimal(&self) -> Option<Decimal> {
158 self.to_i128().and_then(Decimal::from_i128)
159 }
160
161 fn try_from_decimal(value: Decimal) -> Option<Self> {
162 value.to_i128().map(WrappedInt::from).map(Self::from_candid)
163 }
164}
165
166impl Sum for IntBig {
167 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
168 iter.fold(Self::default(), |acc, x| acc + x)
169 }
170}