moverox_types/
u256.rs

1// Copyright (c) The Move Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4use std::fmt;
5use std::mem::size_of;
6use std::ops::{
7    Add,
8    AddAssign,
9    BitAnd,
10    BitAndAssign,
11    BitOr,
12    BitXor,
13    Div,
14    DivAssign,
15    Mul,
16    MulAssign,
17    Rem,
18    RemAssign,
19    Shl,
20    Shr,
21    Sub,
22    SubAssign,
23};
24
25// This U256 impl was chosen for now but we are open to changing it as needed
26use primitive_types::U256 as PrimitiveU256;
27use uint::FromStrRadixErr;
28
29const NUM_BITS_PER_BYTE: usize = 8;
30const U256_NUM_BITS: usize = 256;
31pub const U256_NUM_BYTES: usize = U256_NUM_BITS / NUM_BITS_PER_BYTE;
32
33#[derive(Debug)]
34pub struct U256FromStrError(FromStrRadixErr);
35
36/// A list of error categories encountered when parsing numbers.
37#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
38pub enum U256CastErrorKind {
39    /// Value too large to fit in U8.
40    TooLargeForU8,
41
42    /// Value too large to fit in U16.
43    TooLargeForU16,
44
45    /// Value too large to fit in U32.
46    TooLargeForU32,
47
48    /// Value too large to fit in U64.
49    TooLargeForU64,
50
51    /// Value too large to fit in U128.
52    TooLargeForU128,
53}
54
55#[derive(Debug)]
56pub struct U256CastError {
57    kind: U256CastErrorKind,
58    val: U256,
59}
60
61impl U256CastError {
62    pub fn new<T: std::convert::Into<U256>>(val: T, kind: U256CastErrorKind) -> Self {
63        Self {
64            kind,
65            val: val.into(),
66        }
67    }
68}
69
70impl std::error::Error for U256CastError {}
71
72impl fmt::Display for U256CastError {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        let type_str = match self.kind {
75            U256CastErrorKind::TooLargeForU8 => "u8",
76            U256CastErrorKind::TooLargeForU16 => "u16",
77            U256CastErrorKind::TooLargeForU32 => "u32",
78            U256CastErrorKind::TooLargeForU64 => "u64",
79            U256CastErrorKind::TooLargeForU128 => "u128",
80        };
81        let err_str = format!("Cast failed. {} too large for {}.", self.val, type_str);
82        write!(f, "{err_str}")
83    }
84}
85
86impl std::error::Error for U256FromStrError {
87    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
88        self.0.source()
89    }
90}
91
92impl fmt::Display for U256FromStrError {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        write!(f, "{}", self.0)
95    }
96}
97
98#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, PartialOrd, Ord, Default)]
99pub struct U256(PrimitiveU256);
100
101impl fmt::Display for U256 {
102    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
103        self.0.fmt(f)
104    }
105}
106
107impl fmt::UpperHex for U256 {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        fmt::UpperHex::fmt(&self.0, f)
110    }
111}
112
113impl fmt::LowerHex for U256 {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        fmt::LowerHex::fmt(&self.0, f)
116    }
117}
118
119impl std::str::FromStr for U256 {
120    type Err = U256FromStrError;
121
122    fn from_str(s: &str) -> Result<Self, Self::Err> {
123        Self::from_str_radix(s, 10)
124    }
125}
126
127#[cfg(feature = "serde")]
128impl<'de> serde::Deserialize<'de> for U256 {
129    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
130    where
131        D: serde::Deserializer<'de>,
132    {
133        Ok(Self::from_le_bytes(
134            &(<[u8; U256_NUM_BYTES]>::deserialize(deserializer)?),
135        ))
136    }
137}
138
139#[cfg(feature = "serde")]
140impl serde::Serialize for U256 {
141    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
142    where
143        S: serde::Serializer,
144    {
145        self.to_le_bytes().serialize(serializer)
146    }
147}
148
149impl Shl<u32> for U256 {
150    type Output = Self;
151
152    fn shl(self, rhs: u32) -> Self::Output {
153        let Self(lhs) = self;
154        Self(lhs << rhs)
155    }
156}
157
158impl Shl<u8> for U256 {
159    type Output = Self;
160
161    fn shl(self, rhs: u8) -> Self::Output {
162        let Self(lhs) = self;
163        Self(lhs << rhs)
164    }
165}
166
167impl Shr<u8> for U256 {
168    type Output = Self;
169
170    fn shr(self, rhs: u8) -> Self::Output {
171        let Self(lhs) = self;
172        Self(lhs >> rhs)
173    }
174}
175
176impl BitOr<Self> for U256 {
177    type Output = Self;
178
179    fn bitor(self, rhs: Self) -> Self::Output {
180        let Self(lhs) = self;
181        let Self(rhs) = rhs;
182        Self(lhs | rhs)
183    }
184}
185
186impl BitAnd<Self> for U256 {
187    type Output = Self;
188
189    fn bitand(self, rhs: Self) -> Self::Output {
190        let Self(lhs) = self;
191        let Self(rhs) = rhs;
192        Self(lhs & rhs)
193    }
194}
195
196impl BitXor<Self> for U256 {
197    type Output = Self;
198
199    fn bitxor(self, rhs: Self) -> Self::Output {
200        let Self(lhs) = self;
201        let Self(rhs) = rhs;
202        Self(lhs ^ rhs)
203    }
204}
205
206impl BitAndAssign<Self> for U256 {
207    fn bitand_assign(&mut self, rhs: Self) {
208        *self = *self & rhs;
209    }
210}
211
212// Ignores overflows
213impl Add<Self> for U256 {
214    type Output = Self;
215
216    fn add(self, rhs: Self) -> Self::Output {
217        self.wrapping_add(rhs)
218    }
219}
220
221impl AddAssign<Self> for U256 {
222    fn add_assign(&mut self, rhs: Self) {
223        *self = *self + rhs;
224    }
225}
226
227// Ignores underflows
228impl Sub<Self> for U256 {
229    type Output = Self;
230
231    fn sub(self, rhs: Self) -> Self::Output {
232        self.wrapping_sub(rhs)
233    }
234}
235
236impl SubAssign<Self> for U256 {
237    fn sub_assign(&mut self, rhs: Self) {
238        *self = *self - rhs;
239    }
240}
241
242// Ignores overflows
243impl Mul<Self> for U256 {
244    type Output = Self;
245
246    fn mul(self, rhs: Self) -> Self::Output {
247        self.wrapping_mul(rhs)
248    }
249}
250
251impl MulAssign<Self> for U256 {
252    fn mul_assign(&mut self, rhs: Self) {
253        *self = *self * rhs;
254    }
255}
256
257impl Div<Self> for U256 {
258    type Output = Self;
259
260    fn div(self, rhs: Self) -> Self::Output {
261        Self(self.0 / rhs.0)
262    }
263}
264
265impl DivAssign<Self> for U256 {
266    fn div_assign(&mut self, rhs: Self) {
267        *self = *self / rhs;
268    }
269}
270
271impl Rem<Self> for U256 {
272    type Output = Self;
273
274    fn rem(self, rhs: Self) -> Self::Output {
275        Self(self.0 % rhs.0)
276    }
277}
278
279impl RemAssign<Self> for U256 {
280    fn rem_assign(&mut self, rhs: Self) {
281        *self = Self(self.0 % rhs.0);
282    }
283}
284
285impl U256 {
286    /// Zero value as U256
287    pub const fn zero() -> Self {
288        Self(PrimitiveU256::zero())
289    }
290
291    /// One value as U256
292    pub const fn one() -> Self {
293        Self(PrimitiveU256::one())
294    }
295
296    /// Max value of U256: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
297    pub const fn max_value() -> Self {
298        Self(PrimitiveU256::max_value())
299    }
300
301    /// U256 from string with radix 10 or 16
302    pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, U256FromStrError> {
303        PrimitiveU256::from_str_radix(src.trim_start_matches('0'), radix)
304            .map(Self)
305            .map_err(U256FromStrError)
306    }
307
308    /// U256 from 32 little endian bytes
309    pub fn from_le_bytes(slice: &[u8; U256_NUM_BYTES]) -> Self {
310        Self(PrimitiveU256::from_little_endian(slice))
311    }
312
313    /// U256 to 32 little endian bytes
314    pub fn to_le_bytes(self) -> [u8; U256_NUM_BYTES] {
315        let mut bytes = [0u8; U256_NUM_BYTES];
316        self.0.to_little_endian(&mut bytes);
317        bytes
318    }
319
320    /// Leading zeros of the number
321    pub fn leading_zeros(&self) -> u32 {
322        self.0.leading_zeros()
323    }
324
325    // Unchecked downcasting. Values as truncated if larger than target max
326    pub const fn unchecked_as_u8(&self) -> u8 {
327        self.0.low_u128() as u8
328    }
329
330    pub const fn unchecked_as_u16(&self) -> u16 {
331        self.0.low_u128() as u16
332    }
333
334    pub const fn unchecked_as_u32(&self) -> u32 {
335        self.0.low_u128() as u32
336    }
337
338    pub const fn unchecked_as_u64(&self) -> u64 {
339        self.0.low_u128() as u64
340    }
341
342    pub const fn unchecked_as_u128(&self) -> u128 {
343        self.0.low_u128()
344    }
345
346    // Check arithmetic
347    /// Checked integer addition. Computes self + rhs, returning None if overflow occurred.
348    pub fn checked_add(self, rhs: Self) -> Option<Self> {
349        self.0.checked_add(rhs.0).map(Self)
350    }
351
352    /// Checked integer subtraction. Computes self - rhs, returning None if overflow occurred.
353    pub fn checked_sub(self, rhs: Self) -> Option<Self> {
354        self.0.checked_sub(rhs.0).map(Self)
355    }
356
357    /// Checked integer multiplication. Computes self * rhs, returning None if overflow occurred.
358    pub fn checked_mul(self, rhs: Self) -> Option<Self> {
359        self.0.checked_mul(rhs.0).map(Self)
360    }
361
362    /// Checked integer division. Computes self / rhs, returning None if rhs == 0.
363    pub fn checked_div(self, rhs: Self) -> Option<Self> {
364        self.0.checked_div(rhs.0).map(Self)
365    }
366
367    /// Checked integer remainder. Computes self % rhs, returning None if rhs == 0.
368    pub fn checked_rem(self, rhs: Self) -> Option<Self> {
369        self.0.checked_rem(rhs.0).map(Self)
370    }
371
372    /// Checked integer remainder. Computes self % rhs, returning None if rhs == 0.
373    pub fn checked_shl(self, rhs: u32) -> Option<Self> {
374        if rhs >= U256_NUM_BITS as u32 {
375            return None;
376        }
377        Some(Self(self.0.shl(rhs)))
378    }
379
380    /// Checked shift right. Computes self >> rhs, returning None if rhs is larger than or equal to the number of bits in self.
381    pub fn checked_shr(self, rhs: u32) -> Option<Self> {
382        if rhs >= U256_NUM_BITS as u32 {
383            return None;
384        }
385        Some(Self(self.0.shr(rhs)))
386    }
387
388    /// Downcast to a an unsigned value of type T
389    /// T must be at most u128
390    pub fn down_cast_lossy<T: std::convert::TryFrom<u128>>(self) -> T {
391        // Size of this type
392        let type_size = size_of::<T>();
393        // Maximum value for this type
394        let max_val: u128 = if type_size < 16 {
395            (1u128 << (NUM_BITS_PER_BYTE * type_size)) - 1u128
396        } else {
397            u128::MAX
398        };
399        // This should never fail
400        #[expect(clippy::option_if_let_else)]
401        match T::try_from(self.0.low_u128() & max_val) {
402            Ok(w) => w,
403            Err(_) => panic!("Fatal! Downcast failed"),
404        }
405    }
406
407    /// Wrapping integer addition. Computes self + rhs,  wrapping around at the boundary of the type.
408    /// By definition in std::instrinsics, a.wrapping_add(b) = (a + b) % (2^N), where N is bit width
409    pub fn wrapping_add(self, rhs: Self) -> Self {
410        Self(self.0.overflowing_add(rhs.0).0)
411    }
412
413    /// Wrapping integer subtraction. Computes self - rhs,  wrapping around at the boundary of the type.
414    /// By definition in std::instrinsics, a.wrapping_add(b) = (a - b) % (2^N), where N is bit width
415    pub fn wrapping_sub(self, rhs: Self) -> Self {
416        Self(self.0.overflowing_sub(rhs.0).0)
417    }
418
419    /// Wrapping integer multiplication. Computes self * rhs,  wrapping around at the boundary of the type.
420    /// By definition in std::instrinsics, a.wrapping_mul(b) = (a * b) % (2^N), where N is bit width
421    pub fn wrapping_mul(self, rhs: Self) -> Self {
422        Self(self.0.overflowing_mul(rhs.0).0)
423    }
424
425    pub fn from_f64_lossy(value: f64) -> Self {
426        Self(PrimitiveU256::from_f64_lossy(value))
427    }
428
429    pub fn to_f64_lossy(self) -> f64 {
430        self.0.to_f64_lossy()
431    }
432}
433
434impl From<u8> for U256 {
435    fn from(n: u8) -> Self {
436        Self(PrimitiveU256::from(n))
437    }
438}
439
440impl From<u16> for U256 {
441    fn from(n: u16) -> Self {
442        Self(PrimitiveU256::from(n))
443    }
444}
445
446impl From<u32> for U256 {
447    fn from(n: u32) -> Self {
448        Self(PrimitiveU256::from(n))
449    }
450}
451
452impl From<u64> for U256 {
453    fn from(n: u64) -> Self {
454        Self(PrimitiveU256::from(n))
455    }
456}
457
458impl From<u128> for U256 {
459    fn from(n: u128) -> Self {
460        Self(PrimitiveU256::from(n))
461    }
462}
463
464impl TryFrom<U256> for u8 {
465    type Error = U256CastError;
466    fn try_from(n: U256) -> Result<Self, Self::Error> {
467        let n = n.0.low_u64();
468        if n > Self::MAX as u64 {
469            Err(U256CastError::new(n, U256CastErrorKind::TooLargeForU8))
470        } else {
471            Ok(n as Self)
472        }
473    }
474}
475
476impl TryFrom<U256> for u16 {
477    type Error = U256CastError;
478
479    fn try_from(n: U256) -> Result<Self, Self::Error> {
480        let n = n.0.low_u64();
481        if n > Self::MAX as u64 {
482            Err(U256CastError::new(n, U256CastErrorKind::TooLargeForU16))
483        } else {
484            Ok(n as Self)
485        }
486    }
487}
488
489impl TryFrom<U256> for u32 {
490    type Error = U256CastError;
491
492    fn try_from(n: U256) -> Result<Self, Self::Error> {
493        let n = n.0.low_u64();
494        if n > Self::MAX as u64 {
495            Err(U256CastError::new(n, U256CastErrorKind::TooLargeForU32))
496        } else {
497            Ok(n as Self)
498        }
499    }
500}
501
502impl TryFrom<U256> for u64 {
503    type Error = U256CastError;
504
505    fn try_from(n: U256) -> Result<Self, Self::Error> {
506        let n = n.0.low_u128();
507        if n > Self::MAX as u128 {
508            Err(U256CastError::new(n, U256CastErrorKind::TooLargeForU64))
509        } else {
510            Ok(n as Self)
511        }
512    }
513}
514
515impl TryFrom<U256> for u128 {
516    type Error = U256CastError;
517
518    fn try_from(n: U256) -> Result<Self, Self::Error> {
519        if n > U256::from(Self::MAX) {
520            Err(U256CastError::new(n, U256CastErrorKind::TooLargeForU128))
521        } else {
522            Ok(n.0.low_u128())
523        }
524    }
525}
526
527// Rand impl below are inspired by u128 impl found in https://rust-random.github.io/rand/src/rand/distributions/uniform.rs.html
528
529#[cfg(feature = "proptest")]
530impl proptest::prelude::Arbitrary for U256 {
531    type Strategy = proptest::prelude::BoxedStrategy<Self>;
532    type Parameters = ();
533    fn arbitrary_with(_params: Self::Parameters) -> Self::Strategy {
534        use proptest::strategy::Strategy as _;
535        proptest::arbitrary::any::<[u8; U256_NUM_BYTES]>()
536            .prop_map(|q| Self::from_le_bytes(&q))
537            .boxed()
538    }
539}
540
541#[test]
542#[allow(clippy::unwrap_used)]
543fn wrapping_add() {
544    // a + b overflows U256::MAX by 100
545    // By definition in std::instrinsics, a.wrapping_add(b) = (a + b) % (2^N), where N is bit width
546
547    let a = U256::from(1234u32);
548    let b = U256::from_str_radix(
549        "115792089237316195423570985008687907853269984665640564039457584007913129638801",
550        10,
551    )
552    .unwrap();
553
554    assert!(a.wrapping_add(b) == U256::from(99u8));
555}