clickhouse_arrow/native/values/
int256.rs1#![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}