cardano_serialization_lib/protocol_types/numeric/
big_int.rs1use num_bigint::Sign;
2use num_integer::Integer;
3use num_traits::Signed;
4use crate::*;
5
6#[wasm_bindgen]
7#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
8pub struct BigInt(pub(crate) num_bigint::BigInt);
9
10impl_to_from!(BigInt);
11
12impl serde::Serialize for BigInt {
13 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
14 where
15 S: serde::Serializer,
16 {
17 serializer.serialize_str(&self.to_str())
18 }
19}
20
21impl<'de> serde::de::Deserialize<'de> for BigInt {
22 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
23 where
24 D: serde::de::Deserializer<'de>,
25 {
26 let s = <String as serde::de::Deserialize>::deserialize(deserializer)?;
27 BigInt::from_str(&s).map_err(|_e| {
28 serde::de::Error::invalid_value(
29 serde::de::Unexpected::Str(&s),
30 &"string rep of a big int",
31 )
32 })
33 }
34}
35
36impl JsonSchema for BigInt {
37 fn schema_name() -> String {
38 String::from("BigInt")
39 }
40 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
41 String::json_schema(gen)
42 }
43 fn is_referenceable() -> bool {
44 String::is_referenceable()
45 }
46}
47
48#[wasm_bindgen]
49impl BigInt {
50 pub fn is_zero(&self) -> bool {
51 self.0.sign() == Sign::NoSign
52 }
53
54 pub fn as_u64(&self) -> Option<BigNum> {
55 let (sign, u64_digits) = self.0.to_u64_digits();
56 if sign == Sign::Minus {
57 return None;
58 }
59 match u64_digits.len() {
60 0 => Some(BigNum::zero()),
61 1 => Some((*u64_digits.first().unwrap()).into()),
62 _ => None,
63 }
64 }
65
66 pub fn as_int(&self) -> Option<Int> {
67 let (sign, u64_digits) = self.0.to_u64_digits();
68 let u64_digit = match u64_digits.len() {
69 0 => Some(BigNum::zero()),
70 1 => Some((*u64_digits.first().unwrap()).into()),
71 _ => None,
72 }?;
73 match sign {
74 num_bigint::Sign::NoSign | num_bigint::Sign::Plus => Some(Int::new(&u64_digit)),
75 num_bigint::Sign::Minus => Some(Int::new_negative(&u64_digit)),
76 }
77 }
78
79 pub fn from_str(text: &str) -> Result<BigInt, JsError> {
80 use std::str::FromStr;
81 num_bigint::BigInt::from_str(text)
82 .map_err(|e| JsError::from_str(&format! {"{:?}", e}))
83 .map(Self)
84 }
85
86 pub fn to_str(&self) -> String {
87 self.0.to_string()
88 }
89
90 pub fn add(&self, other: &BigInt) -> BigInt {
91 Self(&self.0 + &other.0)
92 }
93
94 pub fn sub(&self, other: &BigInt) -> BigInt {
95 Self(&self.0 - &other.0)
96 }
97
98 pub fn mul(&self, other: &BigInt) -> BigInt {
99 Self(&self.0 * &other.0)
100 }
101
102 pub fn pow(&self, exp: u32) -> BigInt {
103 Self(self.0.pow(exp))
104 }
105
106 pub fn one() -> BigInt {
107 Self(num_bigint::BigInt::from(1))
108 }
109
110 pub fn zero() -> BigInt {
111 Self(num_bigint::BigInt::from(0))
112 }
113
114 pub fn abs(&self) -> BigInt {
115 Self(self.0.abs())
116 }
117
118 pub fn increment(&self) -> BigInt {
119 self.add(&Self::one())
120 }
121
122 pub fn div_ceil(&self, other: &BigInt) -> BigInt {
123 Self(self.0.div_ceil(&other.0))
124 }
125
126 pub fn div_floor(&self, other: &BigInt) -> BigInt {
127 Self(self.0.div_floor(&other.0))
128 }
129
130 pub(crate) fn is_negative(&self) -> bool {
131 self.0.is_negative()
132 }
133}
134
135impl<T> std::convert::From<T> for BigInt
136 where
137 T: std::convert::Into<num_bigint::BigInt>,
138{
139 fn from(x: T) -> Self {
140 Self(x.into())
141 }
142}
143
144impl From<BigNum> for BigInt {
145 fn from(x: BigNum) -> Self {
146 Self(x.0.into())
147 }
148}
149
150impl From<&BigNum> for BigInt {
151 fn from(x: &BigNum) -> Self {
152 Self(x.0.into())
153 }
154}
155
156pub fn to_bigint(val: u64) -> BigInt {
157 BigInt::from_str(&val.to_string()).unwrap()
158}