ethereum_mysql/sql_uint/
primitive_ops.rs1use super::{SqlU256, U256};
8use std::ops::{Add, Div, Mul, Rem, Sub};
9
10macro_rules! impl_primitive_ops {
12 ($prim_type:ty) => {
13 impl Add<$prim_type> for SqlU256 {
15 type Output = Self;
16
17 fn add(self, rhs: $prim_type) -> Self::Output {
18 SqlU256::from(self.0 + U256::from(rhs))
19 }
20 }
21
22 impl Sub<$prim_type> for SqlU256 {
23 type Output = Self;
24
25 fn sub(self, rhs: $prim_type) -> Self::Output {
26 SqlU256::from(self.0 - U256::from(rhs))
27 }
28 }
29
30 impl Mul<$prim_type> for SqlU256 {
31 type Output = Self;
32
33 fn mul(self, rhs: $prim_type) -> Self::Output {
34 SqlU256::from(self.0 * U256::from(rhs))
35 }
36 }
37
38 impl Div<$prim_type> for SqlU256 {
39 type Output = Self;
40
41 fn div(self, rhs: $prim_type) -> Self::Output {
42 SqlU256::from(self.0 / U256::from(rhs))
43 }
44 }
45
46 impl Rem<$prim_type> for SqlU256 {
47 type Output = Self;
48
49 fn rem(self, rhs: $prim_type) -> Self::Output {
50 SqlU256::from(self.0 % U256::from(rhs))
51 }
52 }
53
54 impl Add<SqlU256> for $prim_type {
56 type Output = SqlU256;
57
58 fn add(self, rhs: SqlU256) -> Self::Output {
59 SqlU256::from(U256::from(self) + rhs.0)
60 }
61 }
62
63 impl Sub<SqlU256> for $prim_type {
64 type Output = SqlU256;
65
66 fn sub(self, rhs: SqlU256) -> Self::Output {
67 SqlU256::from(U256::from(self) - rhs.0)
68 }
69 }
70
71 impl Mul<SqlU256> for $prim_type {
72 type Output = SqlU256;
73
74 fn mul(self, rhs: SqlU256) -> Self::Output {
75 SqlU256::from(U256::from(self) * rhs.0)
76 }
77 }
78
79 impl Div<SqlU256> for $prim_type {
80 type Output = SqlU256;
81
82 fn div(self, rhs: SqlU256) -> Self::Output {
83 SqlU256::from(U256::from(self) / rhs.0)
84 }
85 }
86
87 impl Rem<SqlU256> for $prim_type {
88 type Output = SqlU256;
89
90 fn rem(self, rhs: SqlU256) -> Self::Output {
91 SqlU256::from(U256::from(self) % rhs.0)
92 }
93 }
94
95 impl Add<&$prim_type> for SqlU256 {
97 type Output = Self;
98
99 fn add(self, rhs: &$prim_type) -> Self::Output {
100 SqlU256::from(self.0 + U256::from(*rhs))
101 }
102 }
103
104 impl Sub<&$prim_type> for SqlU256 {
105 type Output = Self;
106
107 fn sub(self, rhs: &$prim_type) -> Self::Output {
108 SqlU256::from(self.0 - U256::from(*rhs))
109 }
110 }
111
112 impl Mul<&$prim_type> for SqlU256 {
113 type Output = Self;
114
115 fn mul(self, rhs: &$prim_type) -> Self::Output {
116 SqlU256::from(self.0 * U256::from(*rhs))
117 }
118 }
119
120 impl Div<&$prim_type> for SqlU256 {
121 type Output = Self;
122
123 fn div(self, rhs: &$prim_type) -> Self::Output {
124 SqlU256::from(self.0 / U256::from(*rhs))
125 }
126 }
127
128 impl Rem<&$prim_type> for SqlU256 {
129 type Output = Self;
130
131 fn rem(self, rhs: &$prim_type) -> Self::Output {
132 SqlU256::from(self.0 % U256::from(*rhs))
133 }
134 }
135
136 impl Add<$prim_type> for &SqlU256 {
138 type Output = SqlU256;
139
140 fn add(self, rhs: $prim_type) -> Self::Output {
141 SqlU256::from(self.0 + U256::from(rhs))
142 }
143 }
144
145 impl Sub<$prim_type> for &SqlU256 {
146 type Output = SqlU256;
147
148 fn sub(self, rhs: $prim_type) -> Self::Output {
149 SqlU256::from(self.0 - U256::from(rhs))
150 }
151 }
152
153 impl Mul<$prim_type> for &SqlU256 {
154 type Output = SqlU256;
155
156 fn mul(self, rhs: $prim_type) -> Self::Output {
157 SqlU256::from(self.0 * U256::from(rhs))
158 }
159 }
160
161 impl Div<$prim_type> for &SqlU256 {
162 type Output = SqlU256;
163
164 fn div(self, rhs: $prim_type) -> Self::Output {
165 SqlU256::from(self.0 / U256::from(rhs))
166 }
167 }
168
169 impl Rem<$prim_type> for &SqlU256 {
170 type Output = SqlU256;
171
172 fn rem(self, rhs: $prim_type) -> Self::Output {
173 SqlU256::from(self.0 % U256::from(rhs))
174 }
175 }
176
177 impl Add<&$prim_type> for &SqlU256 {
179 type Output = SqlU256;
180
181 fn add(self, rhs: &$prim_type) -> Self::Output {
182 SqlU256::from(self.0 + U256::from(*rhs))
183 }
184 }
185
186 impl Sub<&$prim_type> for &SqlU256 {
187 type Output = SqlU256;
188
189 fn sub(self, rhs: &$prim_type) -> Self::Output {
190 SqlU256::from(self.0 - U256::from(*rhs))
191 }
192 }
193
194 impl Mul<&$prim_type> for &SqlU256 {
195 type Output = SqlU256;
196
197 fn mul(self, rhs: &$prim_type) -> Self::Output {
198 SqlU256::from(self.0 * U256::from(*rhs))
199 }
200 }
201
202 impl Div<&$prim_type> for &SqlU256 {
203 type Output = SqlU256;
204
205 fn div(self, rhs: &$prim_type) -> Self::Output {
206 SqlU256::from(self.0 / U256::from(*rhs))
207 }
208 }
209
210 impl Rem<&$prim_type> for &SqlU256 {
211 type Output = SqlU256;
212
213 fn rem(self, rhs: &$prim_type) -> Self::Output {
214 SqlU256::from(self.0 % U256::from(*rhs))
215 }
216 }
217 };
218}
219
220impl_primitive_ops!(u8);
222impl_primitive_ops!(u16);
223impl_primitive_ops!(u32);
224impl_primitive_ops!(u64);
225impl_primitive_ops!(u128);
226impl_primitive_ops!(usize);
227
228macro_rules! impl_signed_ops {
231 ($prim_type:ty) => {
232 impl Add<$prim_type> for SqlU256 {
234 type Output = Self;
235
236 fn add(self, rhs: $prim_type) -> Self::Output {
237 if rhs >= 0 {
238 SqlU256::from(self.0 + U256::from(rhs as u64))
239 } else {
240 SqlU256::from(self.0 - U256::from((-rhs) as u64))
241 }
242 }
243 }
244
245 impl Sub<$prim_type> for SqlU256 {
246 type Output = Self;
247
248 fn sub(self, rhs: $prim_type) -> Self::Output {
249 if rhs >= 0 {
250 SqlU256::from(self.0 - U256::from(rhs as u64))
251 } else {
252 SqlU256::from(self.0 + U256::from((-rhs) as u64))
253 }
254 }
255 }
256
257 impl Mul<$prim_type> for SqlU256 {
258 type Output = Self;
259
260 fn mul(self, rhs: $prim_type) -> Self::Output {
261 if rhs >= 0 {
262 SqlU256::from(self.0 * U256::from(rhs as u64))
263 } else {
264 panic!("Cannot multiply SqlU256 by negative number")
267 }
268 }
269 }
270
271 impl Div<$prim_type> for SqlU256 {
272 type Output = Self;
273
274 fn div(self, rhs: $prim_type) -> Self::Output {
275 if rhs > 0 {
276 SqlU256::from(self.0 / U256::from(rhs as u64))
277 } else if rhs == 0 {
278 panic!("attempt to divide by zero")
279 } else {
280 panic!("Cannot divide SqlU256 by negative number")
281 }
282 }
283 }
284
285 impl Add<SqlU256> for $prim_type {
287 type Output = SqlU256;
288
289 fn add(self, rhs: SqlU256) -> Self::Output {
290 if self >= 0 {
291 SqlU256::from(U256::from(self as u64) + rhs.0)
292 } else {
293 if rhs.0 >= U256::from((-self) as u64) {
294 SqlU256::from(rhs.0 - U256::from((-self) as u64))
295 } else {
296 panic!("Cannot subtract larger value from smaller in unsigned context")
297 }
298 }
299 }
300 }
301
302 impl Mul<SqlU256> for $prim_type {
303 type Output = SqlU256;
304
305 fn mul(self, rhs: SqlU256) -> Self::Output {
306 if self >= 0 {
307 SqlU256::from(U256::from(self as u64) * rhs.0)
308 } else {
309 panic!("Cannot multiply negative number by SqlU256")
310 }
311 }
312 }
313 };
314}
315
316impl_signed_ops!(i8);
317impl_signed_ops!(i16);
318impl_signed_ops!(i32);
319impl_signed_ops!(i64);
320impl_signed_ops!(i128);
321impl_signed_ops!(isize);
322
323#[cfg(test)]
324mod tests {
325 use super::*;
326
327 #[test]
328 fn test_unsigned_primitive_operations() {
329 let value = SqlU256::from(100u64);
330
331 assert_eq!(value + 50u64, SqlU256::from(150u64));
333 assert_eq!(value - 30u64, SqlU256::from(70u64));
334 assert_eq!(value * 2u64, SqlU256::from(200u64));
335 assert_eq!(value / 2u64, SqlU256::from(50u64));
336 assert_eq!(value % 30u64, SqlU256::from(10u64));
337
338 assert_eq!(50u64 + value, SqlU256::from(150u64));
340 assert_eq!(200u64 - value, SqlU256::from(100u64));
341 assert_eq!(2u64 * value, SqlU256::from(200u64));
342 assert_eq!(1000u64 / value, SqlU256::from(10u64));
343 assert_eq!(250u64 % value, SqlU256::from(50u64));
344 }
345
346 #[test]
347 fn test_different_unsigned_types() {
348 let value = SqlU256::from(100u64);
349
350 assert_eq!(value * 2u8, SqlU256::from(200u64));
352 assert_eq!(value * 2u16, SqlU256::from(200u64));
353 assert_eq!(value * 2u32, SqlU256::from(200u64));
354 assert_eq!(value * 2u128, SqlU256::from(200u64));
355 assert_eq!(value * 2usize, SqlU256::from(200u64));
356
357 assert_eq!(2u8 * value, SqlU256::from(200u64));
358 assert_eq!(2u16 * value, SqlU256::from(200u64));
359 assert_eq!(2u32 * value, SqlU256::from(200u64));
360 assert_eq!(2u128 * value, SqlU256::from(200u64));
361 assert_eq!(2usize * value, SqlU256::from(200u64));
362 }
363
364 #[test]
365 fn test_reference_operations() {
366 let value = SqlU256::from(100u64);
367 let multiplier = 2u64;
368
369 assert_eq!(value * &multiplier, SqlU256::from(200u64));
371 assert_eq!(&value * multiplier, SqlU256::from(200u64));
372 assert_eq!(&value * &multiplier, SqlU256::from(200u64));
373 }
374
375 #[test]
376 fn test_signed_positive_operations() {
377 let value = SqlU256::from(100u64);
378
379 assert_eq!(value + 50i64, SqlU256::from(150u64));
381 assert_eq!(value * 2i64, SqlU256::from(200u64));
382 assert_eq!(50i64 + value, SqlU256::from(150u64));
383 assert_eq!(2i64 * value, SqlU256::from(200u64));
384 }
385
386 #[test]
387 fn test_signed_negative_addition() {
388 let value = SqlU256::from(100u64);
389
390 assert_eq!(value + (-30i64), SqlU256::from(70u64));
392
393 assert_eq!((-30i64) + value, SqlU256::from(70u64));
395 }
396
397 #[test]
398 #[should_panic(expected = "Cannot multiply SqlU256 by negative number")]
399 fn test_signed_negative_multiplication_panic() {
400 let value = SqlU256::from(100u64);
401 let _ = value * (-2i64);
402 }
403
404 #[test]
405 #[should_panic(expected = "Cannot multiply negative number by SqlU256")]
406 fn test_negative_multiply_sqlu256_panic() {
407 let value = SqlU256::from(100u64);
408 let _ = (-2i64) * value;
409 }
410
411 #[test]
412 #[should_panic(expected = "Cannot subtract larger value from smaller in unsigned context")]
413 fn test_negative_addition_underflow_panic() {
414 let value = SqlU256::from(50u64);
415 let _ = (-100i64) + value; }
417
418 #[test]
419 fn test_common_ethereum_scenarios() {
420 let balance = SqlU256::from(1_000_000_000_000_000_000u64); let gas_price = SqlU256::from(20_000_000_000u64); let doubled_balance = balance * 2;
426 assert_eq!(doubled_balance, SqlU256::from(2_000_000_000_000_000_000u64));
427
428 let gas_limit = 21000u64;
430 let tx_cost = gas_price * gas_limit;
431 assert_eq!(tx_cost, SqlU256::from(420_000_000_000_000u64));
432
433 let remaining = balance - tx_cost;
435 assert_eq!(remaining, SqlU256::from(999_580_000_000_000_000u64));
436
437 let fee_percentage = 5u64;
439 let fee = balance * fee_percentage / 100u64;
440 assert_eq!(fee, SqlU256::from(50_000_000_000_000_000u64));
441 }
442}