saa_common/types/
uint.rs

1use core::{fmt, ops::{Add, Sub,}};
2use saa_schema::saa_str_struct;
3use serde::{de, ser, Deserialize, Deserializer, Serialize};
4
5
6#[saa_str_struct]
7pub struct Uint64(#[cfg_attr(feature = "wasm", schemars(with = "String"))]pub(crate) u64);
8
9
10#[saa_str_struct]
11pub struct Uint128(#[cfg_attr(feature = "wasm", schemars(with = "String"))] pub(crate) u128);
12
13
14
15impl Uint64 {
16
17    pub const MAX: Self = Self(u64::MAX);
18    pub const MIN: Self = Self(u64::MIN);
19
20    /// Creates a Uint64(value).
21    ///
22    /// This method is less flexible than `from` but can be called in a const context.
23    pub const fn new(value: u64) -> Self {
24        Uint64(value)
25    }
26
27    /// Creates a Uint64(0)
28    #[inline]
29    pub const fn zero() -> Self {
30        Uint64(0)
31    }
32
33    /// Creates a Uint64(1)
34    #[inline]
35    pub const fn one() -> Self {
36        Self(1)
37    }
38
39    /// Returns a copy of the internal data
40    pub const fn u64(&self) -> u64 {
41        self.0
42    }
43
44
45    /// Strict integer addition. Computes `self + rhs`, panicking if overflow occurred.
46    ///
47    /// This is the same as [`Uint64::add`] but const.
48    #[must_use = "this returns the result of the operation, without modifying the original"]
49    pub const fn strict_add(self, rhs: Self) -> Self {
50        match self.0.checked_add(rhs.u64()) {
51            None => panic!("attempt to add with overflow"),
52            Some(sum) => Self(sum),
53        }
54    }
55
56    /// Strict integer subtraction. Computes `self - rhs`, panicking if overflow occurred.
57    ///
58    /// This is the same as [`Uint64::sub`] but const.
59    #[must_use = "this returns the result of the operation, without modifying the original"]
60    pub const fn strict_sub(self, other: Self) -> Self {
61        match self.0.checked_sub(other.u64()) {
62            None => panic!("attempt to subtract with overflow"),
63            Some(diff) => Self(diff),
64        }
65    }
66
67}
68
69
70impl Uint128 {
71    pub const MAX: Self = Self(u128::MAX);
72    pub const MIN: Self = Self(u128::MIN);
73
74    /// Creates a Uint128(value).
75    ///
76    /// This method is less flexible than `from` but can be called in a const context.
77    pub const fn new(value: u128) -> Self {
78        Uint128(value)
79    }
80
81    /// Creates a Uint128(0)
82    #[inline]
83    pub const fn zero() -> Self {
84        Uint128(0)
85    }
86
87    /// Creates a Uint128(1)
88    #[inline]
89    pub const fn one() -> Self {
90        Self(1)
91    }
92
93    /// Returns a copy of the internal data
94    pub const fn u128(&self) -> u128 {
95        self.0
96    }
97
98    /// Returns a copy of the number as big endian bytes.
99    #[must_use = "this returns the result of the operation, without modifying the original"]
100    pub const fn to_be_bytes(self) -> [u8; 16] {
101        self.0.to_be_bytes()
102    }
103
104    /// Returns a copy of the number as little endian bytes.
105    #[must_use = "this returns the result of the operation, without modifying the original"]
106    pub const fn to_le_bytes(self) -> [u8; 16] {
107        self.0.to_le_bytes()
108    }
109
110     /// Strict integer addition. Computes `self + rhs`, panicking if overflow occurred.
111    ///
112    /// This is the same as [`Uint128::add`] but const.
113    #[must_use = "this returns the result of the operation, without modifying the original"]
114    pub const fn strict_add(self, rhs: Self) -> Self {
115        match self.0.checked_add(rhs.u128()) {
116            None => panic!("attempt to add with overflow"),
117            Some(sum) => Self(sum),
118        }
119    }
120
121    /// Strict integer subtraction. Computes `self - rhs`, panicking if overflow occurred.
122    ///
123    /// This is the same as [`Uint128::sub`] but const.
124    #[must_use = "this returns the result of the operation, without modifying the original"]
125    pub const fn strict_sub(self, other: Self) -> Self {
126        match self.0.checked_sub(other.u128()) {
127            None => panic!("attempt to subtract with overflow"),
128            Some(diff) => Self(diff),
129        }
130    }
131
132}
133
134
135
136
137// uint to Uint
138impl From<u64> for Uint64 {
139    fn from(val: u64) -> Self {
140        Uint64(val)
141    }
142}
143
144
145impl From<Uint64> for String {
146    fn from(original: Uint64) -> Self {
147        original.to_string()
148    }
149}
150
151impl From<Uint64> for u64 {
152    fn from(original: Uint64) -> Self {
153        original.0
154    }
155}
156
157impl fmt::Display for Uint64 {
158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159        self.0.fmt(f)
160    }
161}
162
163impl From<Uint128> for String {
164    fn from(original: Uint128) -> Self {
165        original.to_string()
166    }
167}
168
169impl From<Uint128> for u128 {
170    fn from(original: Uint128) -> Self {
171        original.0
172    }
173}
174
175impl fmt::Display for Uint128 {
176    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177        self.0.fmt(f)
178    }
179}
180
181
182impl Add<Uint64> for Uint64 {
183    type Output = Self;
184
185    fn add(self, rhs: Self) -> Self {
186        self.strict_add(rhs)
187    }
188}
189
190impl Sub<Uint64> for Uint64 {
191    type Output = Self;
192
193    fn sub(self, rhs: Self) -> Self {
194        self.strict_sub(rhs)
195    }
196}
197
198impl Add<Uint128> for Uint128 {
199    type Output = Self;
200
201    fn add(self, rhs: Self) -> Self {
202        self.strict_add(rhs)
203    }
204}
205
206impl Sub<Uint128> for Uint128 {
207    type Output = Self;
208
209    fn sub(self, rhs: Self) -> Self {
210        self.strict_sub(rhs)
211    }
212}
213
214
215impl Serialize for Uint64 {
216    /// Serializes as an integer string using base 10
217    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
218    where
219        S: ser::Serializer,
220    {
221        serializer.serialize_str(&self.to_string())
222    }
223}
224
225impl<'de> Deserialize<'de> for Uint64 {
226    /// Deserialized from an integer string using base 10
227    fn deserialize<D>(deserializer: D) -> Result<Uint64, D::Error>
228    where
229        D: Deserializer<'de>,
230    {
231        deserializer.deserialize_str(Uint64Visitor)
232    }
233}
234
235
236impl Serialize for Uint128 {
237    /// Serializes as an integer string using base 10
238    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
239    where
240        S: ser::Serializer,
241    {
242        serializer.serialize_str(&self.to_string())
243    }
244}
245
246impl<'de> Deserialize<'de> for Uint128 {
247    /// Deserialized from an integer string using base 10
248    fn deserialize<D>(deserializer: D) -> Result<Uint128, D::Error>
249    where
250        D: Deserializer<'de>,
251    {
252        deserializer.deserialize_str(Uint128Visitor)
253    }
254}
255
256
257
258
259struct Uint64Visitor;
260
261impl<'de> de::Visitor<'de> for Uint64Visitor {
262    type Value = Uint64;
263
264    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
265        formatter.write_str("string-encoded integer")
266    }
267
268    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
269    where
270        E: de::Error,
271    {
272        match v.parse::<u64>() {
273            Ok(u) => Ok(Uint64(u)),
274            Err(e) => Err(E::custom(format!("invalid Uint64 '{v}' - {e}"))),
275        }
276    }
277}
278
279impl<A> core::iter::Sum<A> for Uint64
280where
281    Self: Add<A, Output = Self>,
282{
283    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
284        iter.fold(Self::zero(), Add::add)
285    }
286}
287
288
289struct Uint128Visitor;
290
291impl<'de> de::Visitor<'de> for Uint128Visitor {
292    type Value = Uint128;
293
294    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
295        formatter.write_str("string-encoded integer")
296    }
297
298    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
299    where
300        E: de::Error,
301    {
302        match v.parse::<u128>() {
303            Ok(u) => Ok(Uint128(u)),
304            Err(e) => Err(E::custom(format!("invalid Uint128 '{v}' - {e}"))),
305        }
306    }
307}