num256/
uint256.rs

1pub use super::Int256;
2use bnum::types::U256;
3use bnum::BUint;
4use num_integer::Roots;
5use num_traits::{
6    Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow,
7    ToPrimitive, Zero,
8};
9use serde::ser::Serialize;
10use serde::{Deserialize, Deserializer, Serializer};
11use std::default::Default;
12use std::fmt;
13use std::num::IntErrorKind;
14use std::ops::{
15    Add, AddAssign, Deref, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, ShlAssign, Shr,
16    ShrAssign, Sub, SubAssign,
17};
18use std::str::FromStr;
19
20#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
21pub struct Uint256(pub U256);
22
23impl Uint256 {
24    pub fn from_le_bytes(slice: &[u8]) -> Uint256 {
25        // if the length is less than 32, pass that length
26        // if it is greater truncate
27        let end = if slice.len() <= 32 { slice.len() } else { 32 };
28        Uint256(BUint::from_le_slice(&slice[0..end]).unwrap())
29    }
30    pub fn from_be_bytes(slice: &[u8]) -> Uint256 {
31        // if the length is less than 32, pass that length
32        // if it is greater truncate
33        let end = if slice.len() <= 32 { slice.len() } else { 32 };
34        Uint256(BUint::from_be_slice(&slice[0..end]).unwrap())
35    }
36    pub fn to_be_bytes(&self) -> [u8; 32] {
37        let mut res = self.to_le_bytes();
38        res.reverse();
39        res
40    }
41    pub fn to_le_bytes(&self) -> [u8; 32] {
42        let mut res: [u8; 32] = [0; 32];
43        // the only function available to access the internal int representation is a bit by bit query
44        // so in order to turn this into a 256bit array we must mask and shift this data into each byte
45        for i in 0usize..256 {
46            // the target byte and bit we are currently focused on
47            let byte_index = i / 8;
48            let bit_index = i % 8;
49            // the bit we want to copy to the target
50            let bit = self.0.bit(i as u32);
51            // if true we mask a one with the byte at the right index
52            if bit {
53                let scratch_bit = 1u8 << bit_index;
54                res[byte_index] |= scratch_bit
55            }
56        }
57        res
58    }
59    /// Converts value to a signed 256 bit integer
60    pub fn to_int256(&self) -> Option<Int256> {
61        if *self <= Int256::max_value().to_uint256().unwrap() {
62            Some(Int256::from_str_radix(&self.to_str_radix(10), 10).unwrap())
63        } else {
64            None
65        }
66    }
67
68    /// Square root
69    pub fn sqrt(&self) -> Uint256 {
70        Self(self.0.sqrt())
71    }
72}
73
74impl Num for Uint256 {
75    type FromStrRadixErr = crate::error::ParseError;
76
77    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
78        let res = Uint256(U256::from_str_radix(str, radix)?);
79        if res > Uint256::max_value() {
80            return Err(Self::FromStrRadixErr::new(IntErrorKind::PosOverflow));
81        } else if res < Uint256::min_value() {
82            return Err(Self::FromStrRadixErr::new(IntErrorKind::NegOverflow));
83        }
84        Ok(res)
85    }
86}
87
88impl One for Uint256 {
89    fn one() -> Self {
90        Uint256(U256::ONE)
91    }
92}
93
94impl Zero for Uint256 {
95    fn zero() -> Self {
96        Uint256(U256::ZERO)
97    }
98
99    fn is_zero(&self) -> bool {
100        *self == Uint256::zero()
101    }
102}
103
104impl FromPrimitive for Uint256 {
105    fn from_i64(n: i64) -> Option<Self> {
106        let val: Result<U256, _> = n.try_into();
107        match val {
108            Ok(v) => Some(Uint256(v)),
109            Err(_) => None,
110        }
111    }
112
113    fn from_u64(n: u64) -> Option<Self> {
114        let val: U256 = n.into();
115        Some(Uint256(val))
116    }
117
118    fn from_i128(n: i128) -> Option<Self> {
119        let val: Result<U256, _> = n.try_into();
120        match val {
121            Ok(v) => Some(Uint256(v)),
122            Err(_) => None,
123        }
124    }
125
126    fn from_u128(n: u128) -> Option<Self> {
127        let val: U256 = n.into();
128        Some(Uint256(val))
129    }
130}
131
132impl ToPrimitive for Uint256 {
133    fn to_i64(&self) -> Option<i64> {
134        match self.0.try_into() {
135            Ok(v) => Some(v),
136            Err(_) => None,
137        }
138    }
139
140    fn to_u64(&self) -> Option<u64> {
141        match self.0.try_into() {
142            Ok(v) => Some(v),
143            Err(_) => None,
144        }
145    }
146
147    fn to_i128(&self) -> Option<i128> {
148        match self.0.try_into() {
149            Ok(v) => Some(v),
150            Err(_) => None,
151        }
152    }
153
154    fn to_u128(&self) -> Option<u128> {
155        match self.0.try_into() {
156            Ok(v) => Some(v),
157            Err(_) => None,
158        }
159    }
160}
161
162impl Bounded for Uint256 {
163    fn min_value() -> Self {
164        // -2**255
165        Uint256::zero()
166    }
167    fn max_value() -> Self {
168        let max_value: Uint256 =
169            "115792089237316195423570985008687907853269984665640564039457584007913129639935"
170                .parse()
171                .unwrap();
172        max_value
173    }
174}
175
176impl FromStr for Uint256 {
177    type Err = crate::error::ParseError;
178    fn from_str(s: &str) -> Result<Self, Self::Err> {
179        if let Some(val) = s.strip_prefix("0x") {
180            Ok(U256::from_str_radix(val, 16).map(Uint256)?)
181        } else {
182            Ok(U256::from_str_radix(s, 10).map(Uint256)?)
183        }
184    }
185}
186
187impl TryFrom<&str> for Uint256 {
188    type Error = crate::error::ParseError;
189
190    fn try_from(value: &str) -> Result<Self, Self::Error> {
191        value.parse()
192    }
193}
194
195impl fmt::Display for Uint256 {
196    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197        write!(f, "{}", &self.0.to_str_radix(10))
198    }
199}
200
201impl fmt::Debug for Uint256 {
202    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203        write!(f, "Uint256({})", &self.0.to_str_radix(10))
204    }
205}
206
207impl fmt::LowerHex for Uint256 {
208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209        let hex_str = &self.0.to_str_radix(16);
210        let mut width = hex_str.len();
211        if f.alternate() {
212            write!(f, "0x")?;
213            width += 2;
214        }
215        if let Some(desired_width) = f.width() {
216            if desired_width > width {
217                let pad = String::from_utf8(vec![b'0'; desired_width - width]).unwrap();
218                write!(f, "{}", &pad)?;
219            }
220        }
221        write!(f, "{hex_str}")
222    }
223}
224
225impl fmt::UpperHex for Uint256 {
226    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227        let hex_str = &self.0.to_str_radix(16).to_uppercase();
228        let mut width = hex_str.len();
229        if f.alternate() {
230            write!(f, "0x")?;
231            width += 2;
232        }
233        if let Some(desired_width) = f.width() {
234            if desired_width > width {
235                let pad = String::from_utf8(vec![b'0'; desired_width - width]).unwrap();
236                write!(f, "{}", &pad)?;
237            }
238        }
239        write!(f, "{hex_str}")
240    }
241}
242
243impl Deref for Uint256 {
244    type Target = U256;
245
246    fn deref(&self) -> &U256 {
247        &self.0
248    }
249}
250
251impl Serialize for Uint256 {
252    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
253    where
254        S: Serializer,
255    {
256        serializer.serialize_str(&self.0.to_str_radix(10))
257    }
258}
259
260impl<'de> Deserialize<'de> for Uint256 {
261    fn deserialize<D>(deserializer: D) -> Result<Uint256, D::Error>
262    where
263        D: Deserializer<'de>,
264    {
265        let s = String::deserialize(deserializer)?;
266
267        // Decide how to deserialize 256 bit integer based on the representation.
268        // "0x" prefix means the string contains hexadecmial representation of the number,
269        // lack of it means its decimal.
270        let (radix, data) = if let Some(val) = s.strip_prefix("0x") {
271            (16, val)
272        } else {
273            (10, s.as_str())
274        };
275
276        // Create Uint256 given the sliced data, and radix
277        U256::from_str_radix(data, radix)
278            .map(Uint256)
279            .map_err(serde::de::Error::custom)
280    }
281}
282
283impl From<[u8; 32]> for Uint256 {
284    fn from(n: [u8; 32]) -> Uint256 {
285        Uint256::from_be_bytes(&n)
286    }
287}
288
289impl<'a> From<&'a [u8]> for Uint256 {
290    fn from(n: &'a [u8]) -> Uint256 {
291        Uint256::from_be_bytes(n)
292    }
293}
294
295impl TryFrom<Int256> for Uint256 {
296    type Error = ();
297
298    fn try_from(value: Int256) -> Result<Self, Self::Error> {
299        match value.to_uint256() {
300            Some(v) => Ok(v),
301            None => Err(()),
302        }
303    }
304}
305
306#[allow(clippy::from_over_into)]
307impl Into<[u8; 32]> for Uint256 {
308    fn into(self) -> [u8; 32] {
309        self.to_be_bytes()
310    }
311}
312
313impl Pow<u32> for Uint256 {
314    type Output = Self;
315
316    fn pow(self, p: u32) -> Self::Output {
317        Uint256(self.0.pow(p))
318    }
319}
320
321macro_rules! uint_impl_from_uint {
322    ($T:ty) => {
323        impl From<$T> for Uint256 {
324            #[inline]
325            fn from(n: $T) -> Self {
326                Uint256(U256::from(n))
327            }
328        }
329    };
330}
331
332// These implementations are pretty much guaranteed to be panic-free.
333uint_impl_from_uint!(u8);
334uint_impl_from_uint!(u16);
335uint_impl_from_uint!(u32);
336uint_impl_from_uint!(u64);
337uint_impl_from_uint!(u128);
338uint_impl_from_uint!(usize);
339
340/// A macro that forwards an unary operator trait i.e. Add
341macro_rules! forward_op {
342    (impl $trait_: ident for $type_: ident { fn $method: ident }) => {
343        impl $trait_<$type_> for $type_ {
344            type Output = $type_;
345
346            fn $method(self, $type_(b): $type_) -> $type_ {
347                let $type_(a) = self;
348                let res = a.$method(&b);
349                Uint256(res)
350            }
351        }
352    };
353}
354
355/// A macro that forwards a checked operator i.e. CheckedAdd
356macro_rules! forward_checked_op {
357    (impl $trait_: ident for $type_: ident { fn $method: ident }) => {
358        impl $trait_ for $type_ {
359            fn $method(&self, $type_(b): &$type_) -> Option<$type_> {
360                let $type_(a) = self;
361                let value = a.$method(b);
362                match value {
363                    Some(value) => Some(Uint256(value)),
364                    None => None,
365                }
366            }
367        }
368    };
369}
370
371/// A macro that forwards a assignment operator i.e. AddAssign
372macro_rules! forward_assign_op {
373    (impl $trait_: ident for $type_: ident { fn $method: ident }) => {
374        impl $trait_ for $type_ {
375            fn $method(&mut self, $type_(b): $type_) {
376                let a = &mut self.0;
377                a.$method(b);
378            }
379        }
380    };
381}
382
383forward_op! { impl Add for Uint256 { fn add } }
384forward_checked_op! { impl CheckedAdd for Uint256 { fn checked_add } }
385forward_assign_op! { impl AddAssign for Uint256 { fn add_assign } }
386
387forward_op! { impl Sub for Uint256 { fn sub } }
388forward_checked_op! { impl CheckedSub for Uint256 { fn checked_sub } }
389forward_assign_op! { impl SubAssign for Uint256 { fn sub_assign } }
390
391forward_op! { impl Mul for Uint256 { fn mul } }
392forward_checked_op! { impl CheckedMul for Uint256 { fn checked_mul } }
393forward_assign_op! { impl MulAssign for Uint256 { fn mul_assign } }
394
395forward_op! { impl Div for Uint256 { fn div } }
396forward_checked_op! { impl CheckedDiv for Uint256 { fn checked_div } }
397forward_assign_op! { impl DivAssign for Uint256 { fn div_assign } }
398
399forward_op! { impl Shl for Uint256 { fn shl } }
400forward_assign_op! { impl ShlAssign for Uint256 { fn shl_assign } }
401
402forward_op! { impl Shr for Uint256 { fn shr } }
403forward_assign_op! { impl ShrAssign for Uint256 { fn shr_assign } }
404
405forward_op! { impl Rem for Uint256 { fn rem } }
406forward_assign_op! { impl RemAssign for Uint256 { fn rem_assign } }
407
408#[test]
409fn create_from_32_bytes() {
410    let lhs: [u8; 32] = [
411        0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
412        0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
413        0x42, 0x42,
414    ];
415    let lhs: Uint256 = lhs.into();
416    assert_eq!(
417        lhs,
418        "0x4242424242424242424242424242424242424242424242424242424242424242"
419            .parse()
420            .unwrap()
421    );
422}
423
424#[test]
425fn to_hex() {
426    let lhs: Uint256 = "0xbabababababababababababababababababababababababababababababababa"
427        .parse()
428        .unwrap();
429    assert_eq!(
430        format!("{lhs:#x}"),
431        "0xbabababababababababababababababababababababababababababababababa"
432    );
433    assert_eq!(
434        format!("{lhs:x}"),
435        "babababababababababababababababababababababababababababababababa"
436    );
437    assert_eq!(
438        format!("{lhs:X}"),
439        "BABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA"
440    );
441    assert_eq!(
442        format!("{lhs:#X}"),
443        "0xBABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA"
444    );
445}
446
447#[test]
448fn to_hex_with_padding() {
449    let lhs: Uint256 = "0xbababababababababababababababababababababababababababa"
450        .parse()
451        .unwrap();
452    assert_eq!(
453        format!("{lhs:#066x}"),
454        "0x0000000000bababababababababababababababababababababababababababa"
455    );
456    assert_eq!(
457        format!("{lhs:064x}"),
458        "0000000000bababababababababababababababababababababababababababa"
459    );
460    assert_eq!(
461        format!("{lhs:064X}"),
462        "0000000000BABABABABABABABABABABABABABABABABABABABABABABABABABABA"
463    );
464    assert_eq!(
465        format!("{lhs:#066X}"),
466        "0x0000000000BABABABABABABABABABABABABABABABABABABABABABABABABABABA"
467    );
468}
469
470#[test]
471fn into_array() {
472    let val = Uint256::from(1024u16);
473    let data: [u8; 32] = val.into();
474    assert_eq!(
475        data,
476        [
477            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
478            0, 4, 0
479        ]
480    );
481}
482
483#[test]
484fn check_display() {
485    let val = Uint256::max_value();
486    assert_eq!(
487        format!("{val}"),
488        "115792089237316195423570985008687907853269984665640564039457584007913129639935"
489    );
490    assert_eq!(
491        val.to_string(),
492        "115792089237316195423570985008687907853269984665640564039457584007913129639935"
493    );
494}
495
496#[test]
497fn check_from_str_radix_overflow() {
498    let super_huge =
499        "115792089237316195423570985008687907853369984665640564039457584007913129639935";
500    let val = Uint256::from_str_radix(super_huge, 10);
501    assert!(val.is_err())
502}
503
504/// Check the ToPrimitive impl for [0, 100k] + [2^32-100, ~2^32+100k]
505#[test]
506fn test_to_primitive_64() {
507    let u32_max: u64 = u32::MAX.into();
508    use num_traits::ToPrimitive;
509    let mut i = 0u64;
510    while i < 100_000 {
511        let i_uint256: Uint256 = i.into();
512        assert_eq!(i, (i_uint256).to_u64().unwrap());
513        assert_eq!(i as i64, (i_uint256).to_i64().unwrap());
514        i += 1
515    }
516
517    let mut i: u64 = u32_max - 100;
518    let end = i + 100_000;
519    while i < end {
520        let i_uint256: Uint256 = i.into();
521        assert_eq!(i, i_uint256.to_u64().unwrap());
522        if i < u32_max {
523            assert_eq!(i as i64, i_uint256.to_i64().unwrap());
524        }
525        i += 1
526    }
527}
528
529/// Check the ToPrimitive impl for [0, 100k] + [2^64-100, ~2^64+100k]
530/// The default ToPrimitive impl breaks on values above 2^64
531#[test]
532fn test_to_primitive_128() {
533    let u64_max: u128 = u64::MAX.into();
534    use num_traits::ToPrimitive;
535    let mut i = 0u128;
536    while i < 100_000 {
537        let i_uint256: Uint256 = i.into();
538        assert_eq!(i, i_uint256.to_u128().unwrap());
539        assert_eq!(i as i128, i_uint256.to_i128().unwrap());
540        i += 1
541    }
542    let mut i: u128 = u64_max - 100;
543    let end = i + 100_000;
544    while i < end {
545        let i_uint256: Uint256 = i.into();
546        assert_eq!(i, i_uint256.to_u128().unwrap());
547        if i < u64_max {
548            assert_eq!(i as i128, i_uint256.to_i128().unwrap());
549        }
550        i += 1
551    }
552}
553
554#[test]
555fn test_sqrt() {
556    use rand::prelude::*;
557
558    for _ in 1..100000 {
559        let r: u128 = random();
560        let n = Uint256::from(r);
561        let sqrt = (n.mul(n)).sqrt();
562        assert!(sqrt == n);
563    }
564}