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,
45 Minus,
47 Zero,
49}
50
51const SIGN_BIT_MASK: U256 = U256([
52 0xffff_ffff_ffff_ffff,
53 0xffff_ffff_ffff_ffff,
54 0xffff_ffff_ffff_ffff,
55 0x7fff_ffff_ffff_ffff,
56]);
57
58#[derive(Copy, Clone, Eq, PartialEq, Debug)]
60pub struct I256(pub Sign, pub U256);
61
62impl I256 {
63 #[must_use]
65 pub const fn zero() -> I256 {
66 I256(Sign::Zero, U256::zero())
67 }
68 #[must_use]
70 pub fn min_value() -> I256 {
71 I256(Sign::Minus, (U256::MAX & SIGN_BIT_MASK) + U256::from(1u64))
72 }
73}
74
75impl Ord for I256 {
76 fn cmp(&self, other: &I256) -> Ordering {
77 match (self.0, other.0) {
78 (Sign::Zero, Sign::Zero) => Ordering::Equal,
79 (Sign::Zero, Sign::Plus) => Ordering::Less,
80 (Sign::Zero, Sign::Minus) => Ordering::Greater,
81 (Sign::Minus, Sign::Zero) => Ordering::Less,
82 (Sign::Minus, Sign::Plus) => Ordering::Less,
83 (Sign::Minus, Sign::Minus) => self.1.cmp(&other.1).reverse(),
84 (Sign::Plus, Sign::Minus) => Ordering::Greater,
85 (Sign::Plus, Sign::Zero) => Ordering::Greater,
86 (Sign::Plus, Sign::Plus) => self.1.cmp(&other.1),
87 }
88 }
89}
90
91impl PartialOrd for I256 {
92 fn partial_cmp(&self, other: &I256) -> Option<Ordering> {
93 Some(self.cmp(other))
94 }
95}
96
97impl Default for I256 {
98 fn default() -> I256 {
99 I256::zero()
100 }
101}
102
103impl From<U256> for I256 {
104 fn from(val: U256) -> I256 {
105 if val == U256::zero() {
106 I256::zero()
107 } else if val & SIGN_BIT_MASK == val {
108 I256(Sign::Plus, val)
109 } else {
110 I256(Sign::Minus, !val + U256::from(1u64))
111 }
112 }
113}
114
115impl From<I256> for U256 {
116 fn from(value: I256) -> U256 {
117 let sign = value.0;
118 if sign == Sign::Zero {
119 U256::zero()
120 } else if sign == Sign::Plus {
121 value.1
122 } else {
123 !value.1 + U256::from(1u64)
124 }
125 }
126}
127
128impl Div for I256 {
129 type Output = I256;
130
131 fn div(self, other: I256) -> I256 {
132 if other == I256::zero() {
133 return I256::zero();
134 }
135
136 if self == I256::min_value() && other.1 == U256::from(1u64) {
137 return I256::min_value();
138 }
139
140 let d = (self.1 / other.1) & SIGN_BIT_MASK;
141
142 if d == U256::zero() {
143 return I256::zero();
144 }
145
146 match (self.0, other.0) {
147 (Sign::Zero, Sign::Plus)
148 | (Sign::Plus, Sign::Zero)
149 | (Sign::Zero, Sign::Zero)
150 | (Sign::Plus, Sign::Plus)
151 | (Sign::Minus, Sign::Minus) => I256(Sign::Plus, d),
152 (Sign::Zero, Sign::Minus)
153 | (Sign::Plus, Sign::Minus)
154 | (Sign::Minus, Sign::Zero)
155 | (Sign::Minus, Sign::Plus) => I256(Sign::Minus, d),
156 }
157 }
158}
159
160impl Rem for I256 {
161 type Output = I256;
162
163 fn rem(self, other: I256) -> I256 {
164 let r = (self.1 % other.1) & SIGN_BIT_MASK;
165
166 if r == U256::zero() {
167 return I256::zero();
168 }
169
170 I256(self.0, r)
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use std::num::Wrapping;
177
178 use super::*;
179
180 #[test]
181 fn div_i256() {
182 assert_eq!(Wrapping(i8::MIN) / Wrapping(-1), Wrapping(i8::MIN));
185
186 assert_eq!(100i8 / -1, -100i8);
187 assert_eq!(100i8 / 2, 50i8);
188
189 let one = I256(Sign::Zero, U256::from(1));
191 let one_hundred = I256(Sign::Zero, U256::from(100));
192 let fifty = I256(Sign::Plus, U256::from(50));
193 let two = I256(Sign::Zero, U256::from(2));
194 let neg_one_hundred = I256(Sign::Minus, U256::from(100));
195 let minus_one = I256(Sign::Minus, U256::from(1));
196 let max_value = I256(Sign::Plus, U256::from(2).pow(U256::from(255)) - 1);
197 let neg_max_value = I256(Sign::Minus, U256::from(2).pow(U256::from(255)) - 1);
198
199 assert_eq!(I256::min_value() / minus_one, I256::min_value());
200 assert_eq!(I256::min_value() / one, I256::min_value());
201 assert_eq!(max_value / one, max_value);
202 assert_eq!(max_value / minus_one, neg_max_value);
203
204 assert_eq!(one_hundred / minus_one, neg_one_hundred);
205 assert_eq!(one_hundred / two, fifty);
206 }
207}