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