stable_swap_math/
bn.rs

1//! Big number types
2#![allow(clippy::assign_op_pattern)]
3#![allow(clippy::ptr_offset_with_cast)]
4#![allow(clippy::manual_range_contains)]
5#![allow(clippy::integer_arithmetic)]
6
7use borsh::{BorshDeserialize, BorshSerialize};
8use stable_swap_client::error::SwapError;
9use std::borrow::BorrowMut;
10use std::io::{Error, ErrorKind, Write};
11use std::mem::size_of;
12use uint::construct_uint;
13
14macro_rules! impl_borsh_serialize_for_bn {
15    ($type: ident) => {
16        impl BorshSerialize for $type {
17            #[inline]
18            fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
19                let bytes = self.to_le_bytes();
20                writer.write_all(&bytes)
21            }
22        }
23    };
24}
25
26macro_rules! impl_borsh_deserialize_for_bn {
27    ($type: ident) => {
28        impl BorshDeserialize for $type {
29            #[inline]
30            fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
31                if buf.len() < size_of::<$type>() {
32                    return Err(Error::new(
33                        ErrorKind::InvalidInput,
34                        "Unexpected length of input",
35                    ));
36                }
37                let res = $type::from_le_bytes(buf[..size_of::<$type>()].try_into().unwrap());
38                *buf = &buf[size_of::<$type>()..];
39                Ok(res)
40            }
41        }
42    };
43}
44
45construct_uint! {
46    /// 256-bit unsigned integer.
47    pub struct U256(4);
48}
49
50impl U256 {
51    /// Convert [U256] to u64
52    pub fn to_u64(self) -> Option<u64> {
53        self.try_to_u64().map_or_else(|_| None, Some)
54    }
55
56    /// Convert [U256] to u64
57    pub fn try_to_u64(self) -> Result<u64, SwapError> {
58        self.try_into().map_err(|_| SwapError::ConversionFailure)
59    }
60
61    /// Convert [U256] to u128
62    pub fn to_u128(self) -> Option<u128> {
63        self.try_to_u128().map_or_else(|_| None, Some)
64    }
65
66    /// Convert [U256] to u128
67    pub fn try_to_u128(self) -> Result<u128, SwapError> {
68        self.try_into().map_err(|_| SwapError::ConversionFailure)
69    }
70
71    /// Convert from little endian bytes
72    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
73        U256::from_little_endian(&bytes)
74    }
75
76    /// Convert to little endian bytes
77    pub fn to_le_bytes(self) -> [u8; 32] {
78        let mut buf: Vec<u8> = Vec::with_capacity(size_of::<Self>());
79        self.to_little_endian(buf.borrow_mut());
80
81        let mut bytes: [u8; 32] = [0u8; 32];
82        bytes.copy_from_slice(buf.as_slice());
83        bytes
84    }
85}
86
87impl_borsh_deserialize_for_bn!(U256);
88impl_borsh_serialize_for_bn!(U256);
89
90construct_uint! {
91    /// 192-bit unsigned integer.
92    pub struct U192(3);
93}
94
95impl U192 {
96    /// Convert [U192] to u64
97    pub fn to_u64(self) -> Option<u64> {
98        self.try_to_u64().map_or_else(|_| None, Some)
99    }
100
101    /// Convert [U192] to u64
102    pub fn try_to_u64(self) -> Result<u64, SwapError> {
103        self.try_into().map_err(|_| SwapError::ConversionFailure)
104    }
105
106    /// Convert [U192] to u128
107    pub fn to_u128(self) -> Option<u128> {
108        self.try_to_u128().map_or_else(|_| None, Some)
109    }
110
111    /// Convert [U192] to u128
112    pub fn try_to_u128(self) -> Result<u128, SwapError> {
113        self.try_into().map_err(|_| SwapError::ConversionFailure)
114    }
115
116    /// Convert from little endian bytes
117    pub fn from_le_bytes(bytes: [u8; 24]) -> Self {
118        U192::from_little_endian(&bytes)
119    }
120
121    /// Convert to little endian bytes
122    pub fn to_le_bytes(self) -> [u8; 24] {
123        let mut buf: Vec<u8> = Vec::with_capacity(size_of::<Self>());
124        self.to_little_endian(buf.borrow_mut());
125
126        let mut bytes: [u8; 24] = [0u8; 24];
127        bytes.copy_from_slice(buf.as_slice());
128        bytes
129    }
130}
131
132impl_borsh_deserialize_for_bn!(U192);
133impl_borsh_serialize_for_bn!(U192);