1#![expect(clippy::cast_sign_loss)]
2use std::fmt;
3
4use crate::{FromSql, Result, ToSql, Type, Value, unexpected_type};
5
6#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Debug, Default)]
8#[allow(non_camel_case_types)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct i256(pub [u8; 32]);
11
12impl From<i256> for u256 {
13 fn from(i: i256) -> Self { u256(i.0) }
14}
15
16impl ToSql for i256 {
17 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> { Ok(Value::Int256(self)) }
18}
19
20impl FromSql for i256 {
21 fn from_sql(type_: &Type, value: Value) -> Result<Self> {
22 if !matches!(type_, Type::Int256) {
23 return Err(unexpected_type(type_));
24 }
25 match value {
26 Value::Int256(x) => Ok(x),
27 _ => unimplemented!(),
28 }
29 }
30}
31
32impl From<i256> for (u128, u128) {
33 fn from(i: i256) -> Self {
34 let mut buf = [0u8; 16];
35 buf.copy_from_slice(&i.0[..16]);
36 let n1 = u128::from_be_bytes(buf);
37 buf.copy_from_slice(&i.0[16..]);
38 let n2 = u128::from_be_bytes(buf);
39 (n1, n2)
40 }
41}
42
43impl From<(u128, u128)> for i256 {
44 fn from(other: (u128, u128)) -> Self {
45 let mut buf = [0u8; 32];
46 buf[..16].copy_from_slice(&other.0.to_be_bytes()[..]);
47 buf[16..].copy_from_slice(&other.1.to_be_bytes()[..]);
48 i256(buf)
49 }
50}
51
52impl From<i128> for i256 {
53 fn from(value: i128) -> Self {
54 if value < 0 {
55 let abs_value = value.unsigned_abs();
57 i256::from((u128::MAX, u128::MAX - abs_value + 1))
58 } else {
59 i256::from((0, value as u128))
61 }
62 }
63}
64
65impl From<(i128, u8)> for i256 {
66 fn from((value, scale): (i128, u8)) -> Self {
67 let scaled_value = value * 10i128.pow(u32::from(scale));
68
69 if scaled_value < 0 {
70 let abs_value = scaled_value.unsigned_abs();
72
73 i256::from((u128::MAX, u128::MAX - abs_value + 1))
77 } else {
78 i256::from((0u128, scaled_value as u128))
82 }
83 }
84}
85
86impl fmt::Display for i256 {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 write!(f, "0x")?;
89 for b in self.0 {
90 write!(f, "{b:02X}")?;
91 }
92 Ok(())
93 }
94}
95
96impl std::ops::Mul<i256> for i256 {
98 type Output = Self;
99
100 fn mul(self, rhs: Self) -> Self {
101 let (a_high, a_low) = self.into();
103 let (b_high, b_low) = rhs.into();
104
105 if a_high == 0 && b_high == 0 {
107 let result = a_low.wrapping_mul(b_low);
109 return i256::from((0, result));
110 }
111
112 let a_negative = (a_high & (1u128 << 127)) != 0;
114 let b_negative = (b_high & (1u128 << 127)) != 0;
115
116 let (_, a_abs_low) = if a_negative {
118 let low_bits = !a_low;
119 let high_bits = !a_high;
120
121 let new_low = low_bits.wrapping_add(1);
122 let new_high = if new_low == 0 { high_bits.wrapping_add(1) } else { high_bits };
123
124 (new_high, new_low)
125 } else {
126 (a_high, a_low)
127 };
128
129 let (_, abs_b_low) = if b_negative {
130 let low_bits = !b_low;
131 let high_bits = !b_high;
132
133 let new_low = low_bits.wrapping_add(1);
134 let new_high = if new_low == 0 { high_bits.wrapping_add(1) } else { high_bits };
135
136 (new_high, new_low)
137 } else {
138 (b_high, b_low)
139 };
140
141 let result = a_abs_low.wrapping_mul(abs_b_low);
145
146 let result_negative = a_negative != b_negative;
148
149 if result_negative {
150 let low_bits = !result;
152 let new_low = low_bits.wrapping_add(1);
153
154 i256::from((u128::MAX, new_low))
155 } else {
156 i256::from((0, result))
157 }
158 }
159}
160
161#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Debug, Default)]
163#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
164#[allow(non_camel_case_types)]
165pub struct u256(pub [u8; 32]);
166
167impl ToSql for u256 {
168 fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> { Ok(Value::UInt256(self)) }
169}
170
171impl FromSql for u256 {
172 fn from_sql(type_: &Type, value: Value) -> Result<Self> {
173 if !matches!(type_, Type::UInt256) {
174 return Err(unexpected_type(type_));
175 }
176 match value {
177 Value::UInt256(x) => Ok(x),
178 _ => unimplemented!(),
179 }
180 }
181}
182
183impl From<u256> for i256 {
184 fn from(u: u256) -> Self { i256(u.0) }
185}
186
187impl From<u256> for (u128, u128) {
188 fn from(u: u256) -> Self {
189 let mut buf = [0u8; 16];
190 buf.copy_from_slice(&u.0[..16]);
191 let n1 = u128::from_be_bytes(buf);
192 buf.copy_from_slice(&u.0[16..]);
193 let n2 = u128::from_be_bytes(buf);
194 (n1, n2)
195 }
196}
197
198impl From<(u128, u128)> for u256 {
199 fn from(other: (u128, u128)) -> Self {
200 let mut buf = [0u8; 32];
201 buf[..16].copy_from_slice(&other.0.to_be_bytes()[..]);
202 buf[16..].copy_from_slice(&other.1.to_be_bytes()[..]);
203 u256(buf)
204 }
205}
206
207impl fmt::Display for u256 {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 write!(f, "0x")?;
210 for b in self.0 {
211 write!(f, "{b:02X}")?;
212 }
213 Ok(())
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220 use crate::{Type, Value};
221
222 #[test]
223 fn test_i256_to_u128_tuple() {
224 let zero = i256([0u8; 32]);
226 let (high, low) = zero.into();
227 assert_eq!(high, 0u128);
228 assert_eq!(low, 0u128);
229
230 let max = i256([0xFFu8; 32]);
232 let (high, low) = max.into();
233 assert_eq!(high, u128::MAX);
234 assert_eq!(low, u128::MAX);
235
236 let mut bytes = [0u8; 32];
238 bytes[15] = 0x12; bytes[31] = 0x34; let mixed = i256(bytes);
241 let (high, low) = mixed.into();
242 assert_eq!(high, 0x12);
243 assert_eq!(low, 0x34);
244 }
245
246 #[test]
247 fn test_i256_from_i128_scale() {
248 let result = i256::from((123i128, 2u8));
250 let expected = i256::from((0u128, 12300u128));
251 assert_eq!(result, expected);
252
253 let result = i256::from((-456i128, 3u8));
255 let scaled_value = -456_000i128;
256 let abs_value = scaled_value.unsigned_abs();
257 let expected = i256::from((u128::MAX, u128::MAX - abs_value + 1));
258 assert_eq!(result, expected);
259
260 let result = i256::from((0i128, 5u8));
262 let expected = i256::from((0u128, 0u128));
263 assert_eq!(result, expected);
264
265 let result = i256::from((42i128, 10u8));
267 let expected = i256::from((0u128, 420_000_000_000u128));
268 assert_eq!(result, expected);
269 }
270
271 #[test]
272 fn test_i256_multiplication_simple_cases() {
273 let a = i256::from((0u128, 100u128));
275 let b = i256::from((0u128, 200u128));
276 let result = a * b;
277 let expected = i256::from((0u128, 20000u128));
278 assert_eq!(result, expected);
279
280 let a = i256::from((0u128, 12345u128));
282 let b = i256::from((0u128, 0u128));
283 let result = a * b;
284 let expected = i256::from((0u128, 0u128));
285 assert_eq!(result, expected);
286
287 let a = i256::from((0u128, 9876u128));
289 let b = i256::from((0u128, 1u128));
290 let result = a * b;
291 assert_eq!(result, a);
292 }
293
294 #[test]
295 fn test_i256_multiplication_negative_numbers() {
296 let a = i256::from((u128::MAX, u128::MAX - 100 + 1)); let b = i256::from((0u128, 50u128)); let result = a * b;
300
301 let (high, _) = result.into();
303 assert_eq!(high, u128::MAX);
304
305 let a = i256::from((0u128, 75u128)); let b = i256::from((u128::MAX, u128::MAX - 25 + 1)); let result = a * b;
309
310 let (high, _) = result.into();
312 assert_eq!(high, u128::MAX);
313
314 let a = i256::from((u128::MAX, u128::MAX - 10 + 1)); let b = i256::from((u128::MAX, u128::MAX - 20 + 1)); let result = a * b;
318
319 let (high, low) = result.into();
321 assert_eq!(high, 0u128);
322 assert_eq!(low, 200u128);
323 }
324
325 #[test]
326 fn test_i256_multiplication_complex_cases() {
327 let a = i256::from((1u128, 100u128));
329 let b = i256::from((2u128, 200u128));
330 let result = a * b;
331
332 let _: (u128, u128) = result.into();
336 }
337
338 #[test]
339 fn test_u256_to_i256_conversion() {
340 let u = u256([0x12u8; 32]);
341 let i: i256 = u.into();
342 assert_eq!(i.0, [0x12u8; 32]);
343 }
344
345 #[test]
346 fn test_u256_to_u128_tuple() {
347 let zero = u256([0u8; 32]);
349 let (high, low) = zero.into();
350 assert_eq!(high, 0u128);
351 assert_eq!(low, 0u128);
352
353 let max = u256([0xFFu8; 32]);
355 let (high, low) = max.into();
356 assert_eq!(high, u128::MAX);
357 assert_eq!(low, u128::MAX);
358
359 let mut bytes = [0u8; 32];
361 bytes[15] = 0xAB; bytes[31] = 0xCD; let mixed = u256(bytes);
364 let (high, low) = mixed.into();
365 assert_eq!(high, 0xAB);
366 assert_eq!(low, 0xCD);
367 }
368
369 #[test]
370 fn test_from_sql_error_handling() {
371 let result = i256::from_sql(&Type::UInt256, Value::Int256(i256([0u8; 32])));
373 assert!(result.is_err(), "i256::from_sql should fail with UInt256 type");
374
375 let result = u256::from_sql(&Type::Int256, Value::UInt256(u256([0u8; 32])));
377 assert!(result.is_err(), "u256::from_sql should fail with Int256 type");
378
379 let result = i256::from_sql(&Type::Int256, Value::Int256(i256([0u8; 32])));
381 assert!(result.is_ok(), "i256::from_sql should succeed with Int256 type");
382
383 let result = u256::from_sql(&Type::UInt256, Value::UInt256(u256([0u8; 32])));
384 assert!(result.is_ok(), "u256::from_sql should succeed with UInt256 type");
385 }
386
387 #[test]
388 fn test_from_sql_unimplemented_values() {
389 let result = std::panic::catch_unwind(|| i256::from_sql(&Type::Int256, Value::Int32(42)));
391 assert!(result.is_err()); let result = std::panic::catch_unwind(|| u256::from_sql(&Type::UInt256, Value::UInt32(42)));
395 assert!(result.is_err()); }
397
398 #[test]
399 fn test_display_formatting() {
400 let i = i256([
402 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
403 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
404 0x1C, 0x1D, 0x1E, 0x1F,
405 ]);
406 let formatted = format!("{i}");
407 assert_eq!(formatted, "0x000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
408
409 let u = u256([0xFF; 32]);
411 let formatted = format!("{u}");
412 assert_eq!(formatted, "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
413 }
414
415 #[test]
416 fn test_conversion_roundtrips() {
417 let original = i256([
419 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
420 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x12, 0x34, 0x56, 0x78,
421 0x9A, 0xBC, 0xDE, 0xF0,
422 ]);
423 let tuple: (u128, u128) = original.into();
424 let reconstructed = i256::from(tuple);
425 assert_eq!(original, reconstructed);
426
427 let original = u256([
429 0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33,
430 0x22, 0x11, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0xF0, 0xDE, 0xBC, 0x9A,
431 0x78, 0x56, 0x34, 0x12,
432 ]);
433 let tuple: (u128, u128) = original.into();
434 let reconstructed = u256::from(tuple);
435 assert_eq!(original, reconstructed);
436 }
437
438 #[test]
439 fn test_edge_cases() {
440 let result = i256::from((1i128, 20u8));
442 let _: (u128, u128) = result.into();
444
445 let min_result = i256::from(i128::MIN);
447 let max_result = i256::from(i128::MAX);
448
449 let _: (u128, u128) = min_result.into();
451 let _: (u128, u128) = max_result.into();
452 }
453}