1use core::{
4 cmp::Ordering,
5 ops::{Div, Rem},
6};
7
8use primitive_types::{H160, H256, U256};
9
10use crate::error::{ExitError, ExitFatal};
11
12#[must_use]
14pub fn u256_to_h256(v: U256) -> H256 {
15 let mut r = H256::default();
16 v.to_big_endian(&mut r[..]);
17 r
18}
19
20#[must_use]
22pub fn h256_to_u256(v: H256) -> U256 {
23 U256::from_big_endian(&v[..])
24}
25
26#[must_use]
28pub fn u256_to_h160(v: U256) -> H160 {
29 u256_to_h256(v).into()
30}
31
32pub fn u256_to_usize(v: U256) -> Result<usize, ExitError> {
34 if v > U256::from(usize::MAX) {
35 return Err(ExitFatal::NotSupported.into());
36 }
37 Ok(v.as_usize())
38}
39
40#[derive(Copy, Clone, Eq, PartialEq, Debug)]
42pub enum Sign {
43 Plus,
44 Minus,
45 Zero,
46}
47
48const SIGN_BIT_MASK: U256 = U256([
49 0xffff_ffff_ffff_ffff,
50 0xffff_ffff_ffff_ffff,
51 0xffff_ffff_ffff_ffff,
52 0x7fff_ffff_ffff_ffff,
53]);
54
55#[derive(Copy, Clone, Eq, PartialEq, Debug)]
57pub struct I256(pub Sign, pub U256);
58
59impl I256 {
60 #[must_use]
62 pub const fn zero() -> I256 {
63 I256(Sign::Zero, U256::zero())
64 }
65 #[must_use]
67 pub fn min_value() -> I256 {
68 I256(Sign::Minus, (U256::MAX & SIGN_BIT_MASK) + U256::from(1u64))
69 }
70}
71
72impl Ord for I256 {
73 fn cmp(&self, other: &I256) -> Ordering {
74 match (self.0, other.0) {
75 (Sign::Zero, Sign::Zero) => Ordering::Equal,
76 (Sign::Zero, Sign::Plus) => Ordering::Less,
77 (Sign::Zero, Sign::Minus) => Ordering::Greater,
78 (Sign::Minus, Sign::Zero) => Ordering::Less,
79 (Sign::Minus, Sign::Plus) => Ordering::Less,
80 (Sign::Minus, Sign::Minus) => self.1.cmp(&other.1).reverse(),
81 (Sign::Plus, Sign::Minus) => Ordering::Greater,
82 (Sign::Plus, Sign::Zero) => Ordering::Greater,
83 (Sign::Plus, Sign::Plus) => self.1.cmp(&other.1),
84 }
85 }
86}
87
88impl PartialOrd for I256 {
89 fn partial_cmp(&self, other: &I256) -> Option<Ordering> {
90 Some(self.cmp(other))
91 }
92}
93
94impl Default for I256 {
95 fn default() -> I256 {
96 I256::zero()
97 }
98}
99
100impl From<U256> for I256 {
101 fn from(val: U256) -> I256 {
102 if val == U256::zero() {
103 I256::zero()
104 } else if val & SIGN_BIT_MASK == val {
105 I256(Sign::Plus, val)
106 } else {
107 I256(Sign::Minus, !val + U256::from(1u64))
108 }
109 }
110}
111
112impl From<I256> for U256 {
113 fn from(value: I256) -> U256 {
114 let sign = value.0;
115 if sign == Sign::Zero {
116 U256::zero()
117 } else if sign == Sign::Plus {
118 value.1
119 } else {
120 !value.1 + U256::from(1u64)
121 }
122 }
123}
124
125impl Div for I256 {
126 type Output = I256;
127
128 fn div(self, other: I256) -> I256 {
129 if other == I256::zero() {
130 return I256::zero();
131 }
132
133 if self == I256::min_value() && other.1 == U256::from(1u64) {
134 return I256::min_value();
135 }
136
137 let d = (self.1 / other.1) & SIGN_BIT_MASK;
138
139 if d == U256::zero() {
140 return I256::zero();
141 }
142
143 match (self.0, other.0) {
144 (Sign::Zero, Sign::Plus)
145 | (Sign::Plus, Sign::Zero)
146 | (Sign::Zero, Sign::Zero)
147 | (Sign::Plus, Sign::Plus)
148 | (Sign::Minus, Sign::Minus) => I256(Sign::Plus, d),
149 (Sign::Zero, Sign::Minus)
150 | (Sign::Plus, Sign::Minus)
151 | (Sign::Minus, Sign::Zero)
152 | (Sign::Minus, Sign::Plus) => I256(Sign::Minus, d),
153 }
154 }
155}
156
157impl Rem for I256 {
158 type Output = I256;
159
160 fn rem(self, other: I256) -> I256 {
161 let r = (self.1 % other.1) & SIGN_BIT_MASK;
162
163 if r == U256::zero() {
164 return I256::zero();
165 }
166
167 I256(self.0, r)
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use std::num::Wrapping;
174
175 use super::*;
176
177 #[test]
178 fn div_i256() {
179 assert_eq!(Wrapping(i8::MIN) / Wrapping(-1), Wrapping(i8::MIN));
182
183 assert_eq!(100i8 / -1, -100i8);
184 assert_eq!(100i8 / 2, 50i8);
185
186 let one = I256(Sign::Zero, U256::from(1));
188 let one_hundred = I256(Sign::Zero, U256::from(100));
189 let fifty = I256(Sign::Plus, U256::from(50));
190 let two = I256(Sign::Zero, U256::from(2));
191 let neg_one_hundred = I256(Sign::Minus, U256::from(100));
192 let minus_one = I256(Sign::Minus, U256::from(1));
193 let max_value = I256(Sign::Plus, U256::from(2).pow(U256::from(255)) - 1);
194 let neg_max_value = I256(Sign::Minus, U256::from(2).pow(U256::from(255)) - 1);
195
196 assert_eq!(I256::min_value() / minus_one, I256::min_value());
197 assert_eq!(I256::min_value() / one, I256::min_value());
198 assert_eq!(max_value / one, max_value);
199 assert_eq!(max_value / minus_one, neg_max_value);
200
201 assert_eq!(one_hundred / minus_one, neg_one_hundred);
202 assert_eq!(one_hundred / two, fifty);
203 }
204}