defituna_client/math/
u256.rs

1use crate::math::U256;
2use crate::TunaError as ErrorCode;
3use std::borrow::BorrowMut;
4use std::convert::TryInto;
5use std::mem::size_of;
6
7impl U256 {
8    pub fn try_into_u64(self) -> Result<u64, ErrorCode> {
9        self.try_into().map_err(|_| ErrorCode::TypeCastOverflow)
10    }
11
12    pub fn try_into_u128(self) -> Result<u128, ErrorCode> {
13        self.try_into().map_err(|_| ErrorCode::TypeCastOverflow)
14    }
15
16    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
17        U256::from_little_endian(&bytes)
18    }
19
20    pub fn to_le_bytes(self) -> [u8; 32] {
21        let mut buf: Vec<u8> = Vec::with_capacity(size_of::<Self>());
22        self.to_little_endian(buf.borrow_mut());
23
24        let mut bytes: [u8; 32] = [0u8; 32];
25        bytes.copy_from_slice(buf.as_slice());
26        bytes
27    }
28
29    pub fn checked_shl(self, shl: u32) -> Option<U256> {
30        if self == U256::zero() {
31            return Some(Self::zero());
32        }
33
34        if shl >= 256 {
35            return None;
36        }
37
38        let mask = ((U256::one() << shl) - 1) << (256 - shl);
39        if self & mask != U256::zero() {
40            return None;
41        }
42
43        Some(self << shl)
44    }
45}
46
47#[cfg(test)]
48mod test_u256 {
49    use super::*;
50    use std::ops::Shl;
51
52    #[test]
53    fn test_into_u128_ok() {
54        let a = U256::from(2653u128);
55        let b = U256::from(1232u128);
56        let sum = a + b;
57        let d: u128 = sum.try_into_u128().unwrap();
58        assert_eq!(d, 3885u128);
59    }
60
61    #[test]
62    fn test_into_u128_error() {
63        let a = U256::from(u128::MAX);
64        let b = U256::from(u128::MAX);
65        let sum = a + b;
66        let c: Result<u128, ErrorCode> = sum.try_into_u128();
67        assert!(c.is_err());
68    }
69
70    #[test]
71    fn test_as_u128_ok() {
72        let a = U256::from(2653u128);
73        let b = U256::from(1232u128);
74        let sum = a + b;
75        let d: u128 = sum.as_u128();
76        assert_eq!(d, 3885u128);
77    }
78
79    #[test]
80    #[should_panic(expected = "Integer overflow when casting to u128")]
81    fn test_as_u128_panic() {
82        let a = U256::from(u128::MAX);
83        let b = U256::from(u128::MAX);
84        let sum = a + b;
85        let _: u128 = sum.as_u128();
86    }
87
88    #[test]
89    fn test_into_u64_ok() {
90        let a = U256::from(2653u64);
91        let b = U256::from(1232u64);
92        let sum = a + b;
93        let d: u64 = sum.try_into_u64().unwrap();
94        assert_eq!(d, 3885u64);
95    }
96
97    #[test]
98    fn test_into_u64_error() {
99        let a = U256::from(u64::MAX);
100        let b = U256::from(u64::MAX);
101        let sum = a + b;
102        let c: Result<u64, ErrorCode> = sum.try_into_u64();
103        assert!(c.is_err());
104    }
105
106    #[test]
107    fn test_as_u64_ok() {
108        let a = U256::from(2653u64);
109        let b = U256::from(1232u64);
110        let sum = a + b;
111        let d: u64 = sum.as_u64();
112        assert_eq!(d, 3885u64);
113    }
114
115    #[test]
116    #[should_panic(expected = "Integer overflow when casting to u64")]
117    fn test_as_u64_panic() {
118        let a = U256::from(u64::MAX);
119        let b = U256::from(u64::MAX);
120        let sum = a + b;
121        let _: u64 = sum.as_u64(); // panic overflow
122    }
123
124    #[test]
125    fn test_checked_shl() {
126        assert_eq!(U256::zero().checked_shl(256), Some(U256::zero()));
127        assert_eq!(U256::one().checked_shl(1), Some(U256::from(2)));
128        assert_eq!(U256::one().checked_shl(255), Some(U256::one().shl(255)));
129        assert_eq!(U256::one().checked_shl(256), None);
130        assert_eq!(U256::from(3).checked_shl(255), None);
131        assert_eq!(U256::from(4).checked_shl(254), None);
132        assert_eq!(U256::zero().checked_shl(256).unwrap(), U256::zero());
133    }
134}