1use std::fmt;
5use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Rem, Shl, Shr, Sub};
6
7use num_bigint::BigInt;
8use num_traits::{One, ToPrimitive, Zero};
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct NeoInteger(BigInt);
16
17impl NeoInteger {
18 pub fn new<T: Into<BigInt>>(value: T) -> Self {
19 Self(value.into())
20 }
21
22 pub fn zero() -> Self {
23 Self(BigInt::zero())
24 }
25
26 pub fn one() -> Self {
27 Self(BigInt::one())
28 }
29
30 pub const MAX_BYTE_LENGTH: usize = 32;
35
36 pub fn fits_in_neovm(&self) -> bool {
45 if self.0.is_zero() {
46 return true;
47 }
48 self.0.to_signed_bytes_le().len() <= Self::MAX_BYTE_LENGTH
49 }
50
51 pub fn try_div(&self, rhs: &NeoInteger) -> crate::NeoResult<NeoInteger> {
56 if rhs.0.is_zero() {
57 return Err(crate::NeoError::DivisionByZero);
58 }
59 Ok(NeoInteger::new(&self.0 / &rhs.0))
60 }
61
62 pub fn try_rem(&self, rhs: &NeoInteger) -> crate::NeoResult<NeoInteger> {
65 if rhs.0.is_zero() {
66 return Err(crate::NeoError::DivisionByZero);
67 }
68 Ok(NeoInteger::new(&self.0 % &rhs.0))
69 }
70
71 pub fn min_i32() -> Self {
72 Self(BigInt::from(i32::MIN))
73 }
74
75 pub fn max_i32() -> Self {
76 Self(BigInt::from(i32::MAX))
77 }
78
79 pub fn as_bigint(&self) -> &BigInt {
80 &self.0
81 }
82
83 pub fn to_bigint(&self) -> BigInt {
87 self.0.clone()
88 }
89
90 pub fn from_bigint(value: &BigInt) -> Self {
95 Self(value.clone())
96 }
97
98 pub fn try_as_i32(&self) -> Option<i32> {
101 self.0.to_i32()
102 }
103
104 pub fn try_as_u32(&self) -> Option<u32> {
107 self.0.to_u32()
108 }
109
110 pub fn try_as_i64(&self) -> Option<i64> {
112 self.0.to_i64()
113 }
114
115 pub fn try_as_u64(&self) -> Option<u64> {
117 self.0.to_u64()
118 }
119
120 pub fn try_into_i32(&self) -> crate::NeoResult<i32> {
122 self.0.to_i32().ok_or(crate::NeoError::Overflow)
123 }
124
125 pub fn try_into_u32(&self) -> crate::NeoResult<u32> {
127 self.0.to_u32().ok_or(crate::NeoError::Overflow)
128 }
129
130 pub fn try_into_i64(&self) -> crate::NeoResult<i64> {
132 self.0.to_i64().ok_or(crate::NeoError::Overflow)
133 }
134
135 pub fn try_into_u64(&self) -> crate::NeoResult<u64> {
137 self.0.to_u64().ok_or(crate::NeoError::Overflow)
138 }
139
140 pub fn as_i32_saturating(&self) -> i32 {
143 self.0.to_i32().unwrap_or_else(|| {
144 if self.0.sign() == num_bigint::Sign::Minus {
145 i32::MIN
146 } else {
147 i32::MAX
148 }
149 })
150 }
151
152 pub fn as_u32_saturating(&self) -> u32 {
155 self.0.to_u32().unwrap_or_else(|| {
156 if self.0.sign() == num_bigint::Sign::Minus {
157 0
158 } else {
159 u32::MAX
160 }
161 })
162 }
163
164 pub fn as_i64_saturating(&self) -> i64 {
167 self.0.to_i64().unwrap_or_else(|| {
168 if self.0.sign() == num_bigint::Sign::Minus {
169 i64::MIN
170 } else {
171 i64::MAX
172 }
173 })
174 }
175
176 #[deprecated(
178 since = "0.1.0",
179 note = "Use try_as_i32() or as_i32_saturating() explicitly"
180 )]
181 pub fn as_i32(&self) -> i32 {
182 self.as_i32_saturating()
183 }
184
185 #[deprecated(
187 since = "0.1.0",
188 note = "Use try_as_u32() or as_u32_saturating() explicitly"
189 )]
190 pub fn as_u32(&self) -> u32 {
191 self.as_u32_saturating()
192 }
193
194 #[deprecated(since = "0.1.0", note = "Use try_as_i32() instead")]
196 pub fn to_i32(&self) -> Option<i32> {
197 self.0.to_i32()
198 }
199
200 #[deprecated(since = "0.1.0", note = "Use try_as_u32() instead")]
202 pub fn to_u32(&self) -> Option<u32> {
203 self.0.to_u32()
204 }
205
206 #[deprecated(since = "0.1.0", note = "Use try_as_i64() instead")]
208 pub fn to_i64(&self) -> Option<i64> {
209 self.0.to_i64()
210 }
211}
212
213impl fmt::Display for NeoInteger {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 write!(f, "{}", self.0)
216 }
217}
218
219impl Not for NeoInteger {
220 type Output = Self;
221 fn not(self) -> Self::Output {
222 Self(!self.0)
223 }
224}
225
226impl Shl<u32> for NeoInteger {
227 type Output = Self;
228 fn shl(self, rhs: u32) -> Self::Output {
229 Self(self.0 << rhs)
230 }
231}
232
233impl Shl<u32> for &NeoInteger {
234 type Output = NeoInteger;
235 fn shl(self, rhs: u32) -> Self::Output {
236 NeoInteger::new(self.0.clone() << rhs)
237 }
238}
239
240impl Shr<u32> for NeoInteger {
241 type Output = Self;
242 fn shr(self, rhs: u32) -> Self::Output {
243 Self(self.0 >> rhs)
244 }
245}
246
247impl Shr<u32> for &NeoInteger {
248 type Output = NeoInteger;
249 fn shr(self, rhs: u32) -> Self::Output {
250 NeoInteger::new(self.0.clone() >> rhs)
251 }
252}
253
254impl From<i8> for NeoInteger {
255 fn from(value: i8) -> Self {
256 NeoInteger::new(value)
257 }
258}
259
260impl From<u8> for NeoInteger {
261 fn from(value: u8) -> Self {
262 NeoInteger::new(value)
263 }
264}
265
266impl From<i16> for NeoInteger {
267 fn from(value: i16) -> Self {
268 NeoInteger::new(value)
269 }
270}
271
272impl From<u16> for NeoInteger {
273 fn from(value: u16) -> Self {
274 NeoInteger::new(value)
275 }
276}
277
278impl From<i32> for NeoInteger {
279 fn from(value: i32) -> Self {
280 NeoInteger::new(value)
281 }
282}
283
284impl From<u32> for NeoInteger {
285 fn from(value: u32) -> Self {
286 NeoInteger::new(value)
287 }
288}
289
290impl From<i64> for NeoInteger {
291 fn from(value: i64) -> Self {
292 NeoInteger::new(value)
293 }
294}
295
296impl From<u64> for NeoInteger {
297 fn from(value: u64) -> Self {
298 NeoInteger::new(value)
299 }
300}
301
302impl From<i128> for NeoInteger {
303 fn from(value: i128) -> Self {
304 NeoInteger::new(value)
305 }
306}
307
308impl From<u128> for NeoInteger {
309 fn from(value: u128) -> Self {
310 NeoInteger::new(value)
311 }
312}
313
314impl From<BigInt> for NeoInteger {
315 fn from(value: BigInt) -> Self {
316 NeoInteger::new(value)
317 }
318}
319
320impl From<&BigInt> for NeoInteger {
321 fn from(value: &BigInt) -> Self {
322 NeoInteger::new(value.clone())
323 }
324}
325
326impl Add for NeoInteger {
327 type Output = Self;
328 fn add(self, rhs: Self) -> Self::Output {
329 Self(self.0 + rhs.0)
330 }
331}
332
333impl Add<&NeoInteger> for NeoInteger {
334 type Output = Self;
335 fn add(self, rhs: &NeoInteger) -> Self::Output {
336 Self(self.0 + &rhs.0)
337 }
338}
339
340impl Add<NeoInteger> for &NeoInteger {
341 type Output = NeoInteger;
342 fn add(self, rhs: NeoInteger) -> Self::Output {
343 NeoInteger::new(&self.0 + rhs.0)
344 }
345}
346
347impl Add<&NeoInteger> for &NeoInteger {
348 type Output = NeoInteger;
349 fn add(self, rhs: &NeoInteger) -> Self::Output {
350 NeoInteger::new(&self.0 + &rhs.0)
351 }
352}
353
354impl Sub for NeoInteger {
355 type Output = Self;
356 fn sub(self, rhs: Self) -> Self::Output {
357 Self(self.0 - rhs.0)
358 }
359}
360
361impl Sub<&NeoInteger> for NeoInteger {
362 type Output = Self;
363 fn sub(self, rhs: &NeoInteger) -> Self::Output {
364 Self(self.0 - &rhs.0)
365 }
366}
367
368impl Sub<NeoInteger> for &NeoInteger {
369 type Output = NeoInteger;
370 fn sub(self, rhs: NeoInteger) -> Self::Output {
371 NeoInteger::new(&self.0 - rhs.0)
372 }
373}
374
375impl Sub<&NeoInteger> for &NeoInteger {
376 type Output = NeoInteger;
377 fn sub(self, rhs: &NeoInteger) -> Self::Output {
378 NeoInteger::new(&self.0 - &rhs.0)
379 }
380}
381
382impl Mul for NeoInteger {
383 type Output = Self;
384 fn mul(self, rhs: Self) -> Self::Output {
385 Self(self.0 * rhs.0)
386 }
387}
388
389impl Mul<&NeoInteger> for NeoInteger {
390 type Output = Self;
391 fn mul(self, rhs: &NeoInteger) -> Self::Output {
392 Self(self.0 * &rhs.0)
393 }
394}
395
396impl Mul<NeoInteger> for &NeoInteger {
397 type Output = NeoInteger;
398 fn mul(self, rhs: NeoInteger) -> Self::Output {
399 NeoInteger::new(&self.0 * rhs.0)
400 }
401}
402
403impl Mul<&NeoInteger> for &NeoInteger {
404 type Output = NeoInteger;
405 fn mul(self, rhs: &NeoInteger) -> Self::Output {
406 NeoInteger::new(&self.0 * &rhs.0)
407 }
408}
409
410impl Div for NeoInteger {
411 type Output = Self;
412 fn div(self, rhs: Self) -> Self::Output {
413 Self(self.0 / rhs.0)
414 }
415}
416
417impl Div<&NeoInteger> for NeoInteger {
418 type Output = Self;
419 fn div(self, rhs: &NeoInteger) -> Self::Output {
420 Self(self.0 / &rhs.0)
421 }
422}
423
424impl Div<NeoInteger> for &NeoInteger {
425 type Output = NeoInteger;
426 fn div(self, rhs: NeoInteger) -> Self::Output {
427 NeoInteger::new(&self.0 / rhs.0)
428 }
429}
430
431impl Div<&NeoInteger> for &NeoInteger {
432 type Output = NeoInteger;
433 fn div(self, rhs: &NeoInteger) -> Self::Output {
434 NeoInteger::new(&self.0 / &rhs.0)
435 }
436}
437
438impl Rem for NeoInteger {
439 type Output = Self;
440 fn rem(self, rhs: Self) -> Self::Output {
441 Self(self.0 % rhs.0)
442 }
443}
444
445impl Rem<&NeoInteger> for NeoInteger {
446 type Output = Self;
447 fn rem(self, rhs: &NeoInteger) -> Self::Output {
448 Self(self.0 % &rhs.0)
449 }
450}
451
452impl Rem<NeoInteger> for &NeoInteger {
453 type Output = NeoInteger;
454 fn rem(self, rhs: NeoInteger) -> Self::Output {
455 NeoInteger::new(&self.0 % rhs.0)
456 }
457}
458
459impl Rem<&NeoInteger> for &NeoInteger {
460 type Output = NeoInteger;
461 fn rem(self, rhs: &NeoInteger) -> Self::Output {
462 NeoInteger::new(&self.0 % &rhs.0)
463 }
464}
465
466impl BitAnd for NeoInteger {
467 type Output = Self;
468 fn bitand(self, rhs: Self) -> Self::Output {
469 Self(self.0 & rhs.0)
470 }
471}
472
473impl BitAnd<&NeoInteger> for NeoInteger {
474 type Output = Self;
475 fn bitand(self, rhs: &NeoInteger) -> Self::Output {
476 Self(self.0 & &rhs.0)
477 }
478}
479
480impl BitAnd<NeoInteger> for &NeoInteger {
481 type Output = NeoInteger;
482 fn bitand(self, rhs: NeoInteger) -> Self::Output {
483 NeoInteger::new(&self.0 & rhs.0)
484 }
485}
486
487impl BitAnd<&NeoInteger> for &NeoInteger {
488 type Output = NeoInteger;
489 fn bitand(self, rhs: &NeoInteger) -> Self::Output {
490 NeoInteger::new(&self.0 & &rhs.0)
491 }
492}
493
494impl BitOr for NeoInteger {
495 type Output = Self;
496 fn bitor(self, rhs: Self) -> Self::Output {
497 Self(self.0 | rhs.0)
498 }
499}
500
501impl BitOr<&NeoInteger> for NeoInteger {
502 type Output = Self;
503 fn bitor(self, rhs: &NeoInteger) -> Self::Output {
504 Self(self.0 | &rhs.0)
505 }
506}
507
508impl BitOr<NeoInteger> for &NeoInteger {
509 type Output = NeoInteger;
510 fn bitor(self, rhs: NeoInteger) -> Self::Output {
511 NeoInteger::new(&self.0 | rhs.0)
512 }
513}
514
515impl BitOr<&NeoInteger> for &NeoInteger {
516 type Output = NeoInteger;
517 fn bitor(self, rhs: &NeoInteger) -> Self::Output {
518 NeoInteger::new(&self.0 | &rhs.0)
519 }
520}
521
522impl BitXor for NeoInteger {
523 type Output = Self;
524 fn bitxor(self, rhs: Self) -> Self::Output {
525 Self(self.0 ^ rhs.0)
526 }
527}
528
529impl BitXor<&NeoInteger> for NeoInteger {
530 type Output = Self;
531 fn bitxor(self, rhs: &NeoInteger) -> Self::Output {
532 Self(self.0 ^ &rhs.0)
533 }
534}
535
536impl BitXor<NeoInteger> for &NeoInteger {
537 type Output = NeoInteger;
538 fn bitxor(self, rhs: NeoInteger) -> Self::Output {
539 NeoInteger::new(&self.0 ^ rhs.0)
540 }
541}
542
543impl BitXor<&NeoInteger> for &NeoInteger {
544 type Output = NeoInteger;
545 fn bitxor(self, rhs: &NeoInteger) -> Self::Output {
546 NeoInteger::new(&self.0 ^ &rhs.0)
547 }
548}
549
550impl Default for NeoInteger {
551 fn default() -> Self {
552 NeoInteger::zero()
553 }
554}
555
556#[cfg(test)]
557mod d5_tests {
558 use super::*;
559
560 #[test]
561 fn try_div_returns_division_by_zero_instead_of_panicking() {
562 let a = NeoInteger::new(10);
563 let zero = NeoInteger::zero();
564 assert_eq!(a.try_div(&zero), Err(crate::NeoError::DivisionByZero));
565 let two = NeoInteger::new(2);
566 assert_eq!(a.try_div(&two).unwrap(), NeoInteger::new(5));
567 }
568
569 #[test]
570 fn try_rem_returns_division_by_zero_instead_of_panicking() {
571 let a = NeoInteger::new(10);
572 let zero = NeoInteger::zero();
573 assert_eq!(a.try_rem(&zero), Err(crate::NeoError::DivisionByZero));
574 let three = NeoInteger::new(3);
575 assert_eq!(a.try_rem(&three).unwrap(), NeoInteger::new(1));
576 }
577
578 #[test]
579 fn fits_in_neovm_tracks_the_256_bit_bound() {
580 assert!(NeoInteger::zero().fits_in_neovm());
581 assert!(NeoInteger::new(i64::MAX).fits_in_neovm());
582 assert!(NeoInteger::new(i64::MIN).fits_in_neovm());
583
584 let max_pos = (BigInt::one() << 255) - BigInt::one();
586 assert!(NeoInteger::from_bigint(&max_pos).fits_in_neovm());
587 assert_eq!(
588 max_pos.to_signed_bytes_le().len(),
589 NeoInteger::MAX_BYTE_LENGTH
590 );
591
592 let over = BigInt::one() << 255;
594 assert!(!NeoInteger::from_bigint(&over).fits_in_neovm());
595
596 assert!(!NeoInteger::from_bigint(&(BigInt::one() << 256)).fits_in_neovm());
598 }
599}