cosmwasm_std/math/
mod.rs

1mod conversion;
2mod decimal;
3mod decimal256;
4mod fraction;
5mod int128;
6mod int256;
7mod int512;
8mod int64;
9mod isqrt;
10mod num_consts;
11mod signed_decimal;
12mod signed_decimal_256;
13mod uint128;
14mod uint256;
15mod uint512;
16mod uint64;
17
18pub use decimal::{Decimal, DecimalRangeExceeded};
19pub use decimal256::{Decimal256, Decimal256RangeExceeded};
20pub use fraction::Fraction;
21pub use int128::Int128;
22pub use int256::Int256;
23pub use int512::Int512;
24pub use int64::Int64;
25pub use isqrt::Isqrt;
26pub use signed_decimal::{SignedDecimal, SignedDecimalRangeExceeded};
27pub use signed_decimal_256::{SignedDecimal256, SignedDecimal256RangeExceeded};
28pub use uint128::Uint128;
29pub use uint256::Uint256;
30pub use uint512::Uint512;
31pub use uint64::Uint64;
32
33macro_rules! impl_int_serde {
34    ($ty:ty) => {
35        impl ::serde::Serialize for $ty {
36            /// Serializes as an integer string using base 10.
37            ///
38            /// We consistently serialize all `UintXXX` and `IntYYY` types as strings in JSON
39            /// to ensure the best possible compatibility with clients. E.g. JavaScript and jq
40            /// only support up to ~53bit numbers without losing precision, making it hard to use
41            /// serialized `u64`s on other systems than Rust or Go. `Uint64`/`Int64` ensure the full
42            /// 64 bit range is supported. For larger integers, the use of strings is pretty much the
43            /// only reasonable way to store them in JSON.
44            ///
45            /// For binary encodings (notably MessagePack) strings are used too. The reason is that
46            /// in MessagePack integers are limited to 64 bit and we strive for consistent encoding
47            /// within the `UintXXX`/`IntYYY` family. Also for small to mid sized values, decimal strings
48            /// are often more compact than a fixed-length binary encoding.
49            ///
50            /// ## Examples
51            ///
52            /// Serialize to JSON:
53            ///
54            /// ```
55            /// # use cosmwasm_std::{to_json_vec, Uint64};
56            /// let value = Uint64::new(17);
57            /// let serialized = to_json_vec(&value).unwrap();
58            /// assert_eq!(serialized, b"\"17\"");
59            /// ```
60            ///
61            /// Serialize to MessagePack:
62            ///
63            /// ```
64            /// # use cosmwasm_std::{to_msgpack_vec, Uint64};
65            /// let value = Uint64::new(17);
66            /// let serialized = to_msgpack_vec(&value).unwrap();
67            /// assert_eq!(serialized, [0b10100000 ^ 2, b'1', b'7']); // string of lengths 2 with value "17"
68            /// ```
69            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70            where
71                S: ::serde::ser::Serializer,
72            {
73                serializer.serialize_str(&self.to_string())
74            }
75        }
76
77        impl<'de> ::serde::Deserialize<'de> for $ty {
78            /// Deserializes from an integer string using base 10.
79            ///
80            /// See the [`Serialize` documentation](#method.serialize) for a few more words
81            /// on the encoding of the `UintXXX`/`IntYYY` family.
82            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
83            where
84                D: ::serde::de::Deserializer<'de>,
85            {
86                struct IntVisitor;
87
88                impl<'de> ::serde::de::Visitor<'de> for IntVisitor {
89                    type Value = $ty;
90
91                    fn expecting(
92                        &self,
93                        formatter: &mut ::core::fmt::Formatter,
94                    ) -> ::core::fmt::Result {
95                        formatter.write_str("string-encoded integer")
96                    }
97
98                    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
99                    where
100                        E: ::serde::de::Error,
101                    {
102                        <_>::try_from(v).map_err(|e| {
103                            E::custom(format_args!("invalid {} '{v}' - {e}", stringify!($t)))
104                        })
105                    }
106                }
107
108                deserializer.deserialize_str(IntVisitor)
109            }
110        }
111    };
112}
113use impl_int_serde;
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118    use core::ops::*;
119
120    /// A trait that ensures other traits are implemented for our number types
121    trait AllImpl<'a>:
122        Add
123        + Add<&'a Self>
124        + AddAssign
125        + AddAssign<&'a Self>
126        + Sub
127        + Sub<&'a Self>
128        + SubAssign
129        + SubAssign<&'a Self>
130        + Mul
131        + Mul<&'a Self>
132        + MulAssign
133        + MulAssign<&'a Self>
134        + Div
135        + Div<&'a Self>
136        + DivAssign
137        + DivAssign<&'a Self>
138        + Rem
139        + Rem<&'a Self>
140        + RemAssign
141        + RemAssign<&'a Self>
142        + Sized
143        + Copy
144    where
145        Self: 'a,
146    {
147    }
148
149    /// A trait that ensures other traits are implemented for our integer types
150    trait IntImpl<'a>:
151        AllImpl<'a>
152        + Shl<u32>
153        + Shl<&'a u32>
154        + ShlAssign<u32>
155        + ShlAssign<&'a u32>
156        + Shr<u32>
157        + Shr<&'a u32>
158        + ShrAssign<u32>
159        + ShrAssign<&'a u32>
160        + Not<Output = Self>
161        + super::num_consts::NumConsts
162    {
163    }
164
165    #[allow(dead_code)] // This is used to statically ensure all the integers have a shared set of traits
166    trait SignedImpl<'a>: IntImpl<'a> + Neg<Output = Self> {}
167
168    impl AllImpl<'_> for Uint64 {}
169    impl AllImpl<'_> for Uint128 {}
170    impl AllImpl<'_> for Uint256 {}
171    impl AllImpl<'_> for Uint512 {}
172    impl AllImpl<'_> for Int64 {}
173    impl AllImpl<'_> for Int128 {}
174    impl AllImpl<'_> for Int256 {}
175    impl AllImpl<'_> for Int512 {}
176
177    impl IntImpl<'_> for Int64 {}
178    impl IntImpl<'_> for Int128 {}
179    impl IntImpl<'_> for Int256 {}
180    impl IntImpl<'_> for Int512 {}
181    impl IntImpl<'_> for Uint64 {}
182    impl IntImpl<'_> for Uint128 {}
183    impl IntImpl<'_> for Uint256 {}
184    impl IntImpl<'_> for Uint512 {}
185
186    impl AllImpl<'_> for Decimal {}
187    impl AllImpl<'_> for Decimal256 {}
188
189    impl SignedImpl<'_> for Int64 {}
190    impl SignedImpl<'_> for Int128 {}
191    impl SignedImpl<'_> for Int256 {}
192    impl SignedImpl<'_> for Int512 {}
193}