cosmwasm_std/math/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
mod conversion;
mod decimal;
mod decimal256;
mod fraction;
mod int128;
mod int256;
mod int512;
mod int64;
mod isqrt;
mod num_consts;
mod signed_decimal;
mod signed_decimal_256;
mod uint128;
mod uint256;
mod uint512;
mod uint64;

pub use decimal::{Decimal, DecimalRangeExceeded};
pub use decimal256::{Decimal256, Decimal256RangeExceeded};
pub use fraction::Fraction;
pub use int128::Int128;
pub use int256::Int256;
pub use int512::Int512;
pub use int64::Int64;
pub use isqrt::Isqrt;
pub use signed_decimal::{SignedDecimal, SignedDecimalRangeExceeded};
pub use signed_decimal_256::{SignedDecimal256, SignedDecimal256RangeExceeded};
pub use uint128::Uint128;
pub use uint256::Uint256;
pub use uint512::Uint512;
pub use uint64::Uint64;

macro_rules! impl_int_serde {
    ($ty:ty) => {
        impl ::serde::Serialize for $ty {
            /// Serializes as an integer string using base 10.
            ///
            /// We consistently serialize all `UintXXX` and `IntYYY` types as strings in JSON
            /// to ensure the best possible compatibility with clients. E.g. JavaScript and jq
            /// only support up to ~53bit numbers without losing precision, making it hard to use
            /// serialized `u64`s on other systems than Rust or Go. `Uint64`/`Int64` ensure the full
            /// 64 bit range is supported. For larger integers, the use of strings is pretty much the
            /// only reasonable way to store them in JSON.
            ///
            /// For binary encodings (notably MessagePack) strings are used too. The reason is that
            /// in MessagePack integers are limited to 64 bit and we strive for consistent encoding
            /// within the `UintXXX`/`IntYYY` family. Also for small to mid sized values, decimal strings
            /// are often more compact than a fixed-length binary encoding.
            ///
            /// ## Examples
            ///
            /// Serialize to JSON:
            ///
            /// ```
            /// # use cosmwasm_std::{to_json_vec, Uint64};
            /// let value = Uint64::new(17);
            /// let serialized = to_json_vec(&value).unwrap();
            /// assert_eq!(serialized, b"\"17\"");
            /// ```
            ///
            /// Serialize to MessagePack:
            ///
            /// ```
            /// # use cosmwasm_std::{to_msgpack_vec, Uint64};
            /// let value = Uint64::new(17);
            /// let serialized = to_msgpack_vec(&value).unwrap();
            /// assert_eq!(serialized, [0b10100000 ^ 2, b'1', b'7']); // string of lengths 2 with value "17"
            /// ```
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: ::serde::ser::Serializer,
            {
                serializer.serialize_str(&self.to_string())
            }
        }

        impl<'de> ::serde::Deserialize<'de> for $ty {
            /// Deserializes from an integer string using base 10.
            ///
            /// See the [`Serialize` documentation](#method.serialize) for a few more words
            /// on the encoding of the `UintXXX`/`IntYYY` family.
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: ::serde::de::Deserializer<'de>,
            {
                struct IntVisitor;

                impl<'de> ::serde::de::Visitor<'de> for IntVisitor {
                    type Value = $ty;

                    fn expecting(
                        &self,
                        formatter: &mut ::core::fmt::Formatter,
                    ) -> ::core::fmt::Result {
                        formatter.write_str("string-encoded integer")
                    }

                    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
                    where
                        E: ::serde::de::Error,
                    {
                        <_>::try_from(v).map_err(|e| {
                            E::custom(format_args!("invalid {} '{v}' - {e}", stringify!($t)))
                        })
                    }
                }

                deserializer.deserialize_str(IntVisitor)
            }
        }
    };
}
use impl_int_serde;

#[cfg(test)]
mod tests {
    use super::*;
    use core::ops::*;

    /// A trait that ensures other traits are implemented for our number types
    trait AllImpl<'a>:
        Add
        + Add<&'a Self>
        + AddAssign
        + AddAssign<&'a Self>
        + Sub
        + Sub<&'a Self>
        + SubAssign
        + SubAssign<&'a Self>
        + Mul
        + Mul<&'a Self>
        + MulAssign
        + MulAssign<&'a Self>
        + Div
        + Div<&'a Self>
        + DivAssign
        + DivAssign<&'a Self>
        + Rem
        + Rem<&'a Self>
        + RemAssign
        + RemAssign<&'a Self>
        + Sized
        + Copy
    where
        Self: 'a,
    {
    }

    /// A trait that ensures other traits are implemented for our integer types
    trait IntImpl<'a>:
        AllImpl<'a>
        + Shl<u32>
        + Shl<&'a u32>
        + ShlAssign<u32>
        + ShlAssign<&'a u32>
        + Shr<u32>
        + Shr<&'a u32>
        + ShrAssign<u32>
        + ShrAssign<&'a u32>
        + Not<Output = Self>
        + super::num_consts::NumConsts
    {
    }

    #[allow(dead_code)] // This is used to statically ensure all the integers have a shared set of traits
    trait SignedImpl<'a>: IntImpl<'a> + Neg<Output = Self> {}

    impl AllImpl<'_> for Uint64 {}
    impl AllImpl<'_> for Uint128 {}
    impl AllImpl<'_> for Uint256 {}
    impl AllImpl<'_> for Uint512 {}
    impl AllImpl<'_> for Int64 {}
    impl AllImpl<'_> for Int128 {}
    impl AllImpl<'_> for Int256 {}
    impl AllImpl<'_> for Int512 {}

    impl IntImpl<'_> for Int64 {}
    impl IntImpl<'_> for Int128 {}
    impl IntImpl<'_> for Int256 {}
    impl IntImpl<'_> for Int512 {}
    impl IntImpl<'_> for Uint64 {}
    impl IntImpl<'_> for Uint128 {}
    impl IntImpl<'_> for Uint256 {}
    impl IntImpl<'_> for Uint512 {}

    impl AllImpl<'_> for Decimal {}
    impl AllImpl<'_> for Decimal256 {}

    impl SignedImpl<'_> for Int64 {}
    impl SignedImpl<'_> for Int128 {}
    impl SignedImpl<'_> for Int256 {}
    impl SignedImpl<'_> for Int512 {}
}