Skip to main content

neo_types/
integer.rs

1// Copyright (c) 2025-2026 R3E Network
2// Licensed under the MIT License
3
4use 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/// Neo N3 Integer type (arbitrary precision)
13#[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 fn min_i32() -> Self {
31        Self(BigInt::from(i32::MIN))
32    }
33
34    pub fn max_i32() -> Self {
35        Self(BigInt::from(i32::MAX))
36    }
37
38    pub fn as_bigint(&self) -> &BigInt {
39        &self.0
40    }
41
42    /// Convert to i32, returning None if the value is out of range.
43    /// This is the safe alternative to `as_i32()` that doesn't panic.
44    pub fn try_as_i32(&self) -> Option<i32> {
45        self.0.to_i32()
46    }
47
48    /// Convert to u32, returning None if the value is out of range.
49    /// This is the safe alternative to `as_u32()` that doesn't panic.
50    pub fn try_as_u32(&self) -> Option<u32> {
51        self.0.to_u32()
52    }
53
54    /// Convert to i64, returning None if the value is out of range.
55    pub fn try_as_i64(&self) -> Option<i64> {
56        self.0.to_i64()
57    }
58
59    /// Convert to u64, returning None if the value is out of range.
60    pub fn try_as_u64(&self) -> Option<u64> {
61        self.0.to_u64()
62    }
63
64    /// Convert to i32, returning `Result` for ergonomic `?` usage.
65    pub fn try_into_i32(&self) -> crate::NeoResult<i32> {
66        self.0.to_i32().ok_or(crate::NeoError::Overflow)
67    }
68
69    /// Convert to u32, returning `Result` for ergonomic `?` usage.
70    pub fn try_into_u32(&self) -> crate::NeoResult<u32> {
71        self.0.to_u32().ok_or(crate::NeoError::Overflow)
72    }
73
74    /// Convert to i64, returning `Result` for ergonomic `?` usage.
75    pub fn try_into_i64(&self) -> crate::NeoResult<i64> {
76        self.0.to_i64().ok_or(crate::NeoError::Overflow)
77    }
78
79    /// Convert to u64, returning `Result` for ergonomic `?` usage.
80    pub fn try_into_u64(&self) -> crate::NeoResult<u64> {
81        self.0.to_u64().ok_or(crate::NeoError::Overflow)
82    }
83
84    /// Convert to i32, saturating at the boundaries if the value is out of range.
85    /// This never panics.
86    pub fn as_i32_saturating(&self) -> i32 {
87        self.0.to_i32().unwrap_or_else(|| {
88            if self.0.sign() == num_bigint::Sign::Minus {
89                i32::MIN
90            } else {
91                i32::MAX
92            }
93        })
94    }
95
96    /// Convert to u32, saturating at the boundaries if the value is out of range.
97    /// This never panics.
98    pub fn as_u32_saturating(&self) -> u32 {
99        self.0.to_u32().unwrap_or_else(|| {
100            if self.0.sign() == num_bigint::Sign::Minus {
101                0
102            } else {
103                u32::MAX
104            }
105        })
106    }
107
108    /// Convert to i64, saturating at the boundaries if the value is out of range.
109    /// This never panics.
110    pub fn as_i64_saturating(&self) -> i64 {
111        self.0.to_i64().unwrap_or_else(|| {
112            if self.0.sign() == num_bigint::Sign::Minus {
113                i64::MIN
114            } else {
115                i64::MAX
116            }
117        })
118    }
119
120    /// Deprecated compatibility helper that converts to `i32` using saturating semantics.
121    #[deprecated(
122        since = "0.1.0",
123        note = "Use try_as_i32() or as_i32_saturating() explicitly"
124    )]
125    pub fn as_i32(&self) -> i32 {
126        self.as_i32_saturating()
127    }
128
129    /// Deprecated compatibility helper that converts to `u32` using saturating semantics.
130    #[deprecated(
131        since = "0.1.0",
132        note = "Use try_as_u32() or as_u32_saturating() explicitly"
133    )]
134    pub fn as_u32(&self) -> u32 {
135        self.as_u32_saturating()
136    }
137
138    /// Deprecated: use `try_as_i32()` instead.
139    #[deprecated(since = "0.1.0", note = "Use try_as_i32() instead")]
140    pub fn to_i32(&self) -> Option<i32> {
141        self.0.to_i32()
142    }
143
144    /// Deprecated: use `try_as_u32()` instead.
145    #[deprecated(since = "0.1.0", note = "Use try_as_u32() instead")]
146    pub fn to_u32(&self) -> Option<u32> {
147        self.0.to_u32()
148    }
149
150    /// Deprecated: use `try_as_i64()` instead.
151    #[deprecated(since = "0.1.0", note = "Use try_as_i64() instead")]
152    pub fn to_i64(&self) -> Option<i64> {
153        self.0.to_i64()
154    }
155}
156
157impl fmt::Display for NeoInteger {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        write!(f, "{}", self.0)
160    }
161}
162
163impl Not for NeoInteger {
164    type Output = Self;
165    fn not(self) -> Self::Output {
166        Self(!self.0)
167    }
168}
169
170impl Shl<u32> for NeoInteger {
171    type Output = Self;
172    fn shl(self, rhs: u32) -> Self::Output {
173        Self(self.0 << rhs)
174    }
175}
176
177impl Shl<u32> for &NeoInteger {
178    type Output = NeoInteger;
179    fn shl(self, rhs: u32) -> Self::Output {
180        NeoInteger::new(self.0.clone() << rhs)
181    }
182}
183
184impl Shr<u32> for NeoInteger {
185    type Output = Self;
186    fn shr(self, rhs: u32) -> Self::Output {
187        Self(self.0 >> rhs)
188    }
189}
190
191impl Shr<u32> for &NeoInteger {
192    type Output = NeoInteger;
193    fn shr(self, rhs: u32) -> Self::Output {
194        NeoInteger::new(self.0.clone() >> rhs)
195    }
196}
197
198impl From<i8> for NeoInteger {
199    fn from(value: i8) -> Self {
200        NeoInteger::new(value)
201    }
202}
203
204impl From<u8> for NeoInteger {
205    fn from(value: u8) -> Self {
206        NeoInteger::new(value)
207    }
208}
209
210impl From<i16> for NeoInteger {
211    fn from(value: i16) -> Self {
212        NeoInteger::new(value)
213    }
214}
215
216impl From<u16> for NeoInteger {
217    fn from(value: u16) -> Self {
218        NeoInteger::new(value)
219    }
220}
221
222impl From<i32> for NeoInteger {
223    fn from(value: i32) -> Self {
224        NeoInteger::new(value)
225    }
226}
227
228impl From<u32> for NeoInteger {
229    fn from(value: u32) -> Self {
230        NeoInteger::new(value)
231    }
232}
233
234impl From<i64> for NeoInteger {
235    fn from(value: i64) -> Self {
236        NeoInteger::new(value)
237    }
238}
239
240impl From<u64> for NeoInteger {
241    fn from(value: u64) -> Self {
242        NeoInteger::new(value)
243    }
244}
245
246impl From<i128> for NeoInteger {
247    fn from(value: i128) -> Self {
248        NeoInteger::new(value)
249    }
250}
251
252impl From<u128> for NeoInteger {
253    fn from(value: u128) -> Self {
254        NeoInteger::new(value)
255    }
256}
257
258impl From<BigInt> for NeoInteger {
259    fn from(value: BigInt) -> Self {
260        NeoInteger::new(value)
261    }
262}
263
264impl From<&BigInt> for NeoInteger {
265    fn from(value: &BigInt) -> Self {
266        NeoInteger::new(value.clone())
267    }
268}
269
270impl Add for NeoInteger {
271    type Output = Self;
272    fn add(self, rhs: Self) -> Self::Output {
273        Self(self.0 + rhs.0)
274    }
275}
276
277impl Add<&NeoInteger> for NeoInteger {
278    type Output = Self;
279    fn add(self, rhs: &NeoInteger) -> Self::Output {
280        Self(self.0 + &rhs.0)
281    }
282}
283
284impl Add<NeoInteger> for &NeoInteger {
285    type Output = NeoInteger;
286    fn add(self, rhs: NeoInteger) -> Self::Output {
287        NeoInteger::new(&self.0 + rhs.0)
288    }
289}
290
291impl Add<&NeoInteger> for &NeoInteger {
292    type Output = NeoInteger;
293    fn add(self, rhs: &NeoInteger) -> Self::Output {
294        NeoInteger::new(&self.0 + &rhs.0)
295    }
296}
297
298impl Sub for NeoInteger {
299    type Output = Self;
300    fn sub(self, rhs: Self) -> Self::Output {
301        Self(self.0 - rhs.0)
302    }
303}
304
305impl Sub<&NeoInteger> for NeoInteger {
306    type Output = Self;
307    fn sub(self, rhs: &NeoInteger) -> Self::Output {
308        Self(self.0 - &rhs.0)
309    }
310}
311
312impl Sub<NeoInteger> for &NeoInteger {
313    type Output = NeoInteger;
314    fn sub(self, rhs: NeoInteger) -> Self::Output {
315        NeoInteger::new(&self.0 - rhs.0)
316    }
317}
318
319impl Sub<&NeoInteger> for &NeoInteger {
320    type Output = NeoInteger;
321    fn sub(self, rhs: &NeoInteger) -> Self::Output {
322        NeoInteger::new(&self.0 - &rhs.0)
323    }
324}
325
326impl Mul for NeoInteger {
327    type Output = Self;
328    fn mul(self, rhs: Self) -> Self::Output {
329        Self(self.0 * rhs.0)
330    }
331}
332
333impl Mul<&NeoInteger> for NeoInteger {
334    type Output = Self;
335    fn mul(self, rhs: &NeoInteger) -> Self::Output {
336        Self(self.0 * &rhs.0)
337    }
338}
339
340impl Mul<NeoInteger> for &NeoInteger {
341    type Output = NeoInteger;
342    fn mul(self, rhs: NeoInteger) -> Self::Output {
343        NeoInteger::new(&self.0 * rhs.0)
344    }
345}
346
347impl Mul<&NeoInteger> for &NeoInteger {
348    type Output = NeoInteger;
349    fn mul(self, rhs: &NeoInteger) -> Self::Output {
350        NeoInteger::new(&self.0 * &rhs.0)
351    }
352}
353
354impl Div for NeoInteger {
355    type Output = Self;
356    fn div(self, rhs: Self) -> Self::Output {
357        Self(self.0 / rhs.0)
358    }
359}
360
361impl Div<&NeoInteger> for NeoInteger {
362    type Output = Self;
363    fn div(self, rhs: &NeoInteger) -> Self::Output {
364        Self(self.0 / &rhs.0)
365    }
366}
367
368impl Div<NeoInteger> for &NeoInteger {
369    type Output = NeoInteger;
370    fn div(self, rhs: NeoInteger) -> Self::Output {
371        NeoInteger::new(&self.0 / rhs.0)
372    }
373}
374
375impl Div<&NeoInteger> for &NeoInteger {
376    type Output = NeoInteger;
377    fn div(self, rhs: &NeoInteger) -> Self::Output {
378        NeoInteger::new(&self.0 / &rhs.0)
379    }
380}
381
382impl Rem for NeoInteger {
383    type Output = Self;
384    fn rem(self, rhs: Self) -> Self::Output {
385        Self(self.0 % rhs.0)
386    }
387}
388
389impl Rem<&NeoInteger> for NeoInteger {
390    type Output = Self;
391    fn rem(self, rhs: &NeoInteger) -> Self::Output {
392        Self(self.0 % &rhs.0)
393    }
394}
395
396impl Rem<NeoInteger> for &NeoInteger {
397    type Output = NeoInteger;
398    fn rem(self, rhs: NeoInteger) -> Self::Output {
399        NeoInteger::new(&self.0 % rhs.0)
400    }
401}
402
403impl Rem<&NeoInteger> for &NeoInteger {
404    type Output = NeoInteger;
405    fn rem(self, rhs: &NeoInteger) -> Self::Output {
406        NeoInteger::new(&self.0 % &rhs.0)
407    }
408}
409
410impl BitAnd for NeoInteger {
411    type Output = Self;
412    fn bitand(self, rhs: Self) -> Self::Output {
413        Self(self.0 & rhs.0)
414    }
415}
416
417impl BitAnd<&NeoInteger> for NeoInteger {
418    type Output = Self;
419    fn bitand(self, rhs: &NeoInteger) -> Self::Output {
420        Self(self.0 & &rhs.0)
421    }
422}
423
424impl BitAnd<NeoInteger> for &NeoInteger {
425    type Output = NeoInteger;
426    fn bitand(self, rhs: NeoInteger) -> Self::Output {
427        NeoInteger::new(&self.0 & rhs.0)
428    }
429}
430
431impl BitAnd<&NeoInteger> for &NeoInteger {
432    type Output = NeoInteger;
433    fn bitand(self, rhs: &NeoInteger) -> Self::Output {
434        NeoInteger::new(&self.0 & &rhs.0)
435    }
436}
437
438impl BitOr for NeoInteger {
439    type Output = Self;
440    fn bitor(self, rhs: Self) -> Self::Output {
441        Self(self.0 | rhs.0)
442    }
443}
444
445impl BitOr<&NeoInteger> for NeoInteger {
446    type Output = Self;
447    fn bitor(self, rhs: &NeoInteger) -> Self::Output {
448        Self(self.0 | &rhs.0)
449    }
450}
451
452impl BitOr<NeoInteger> for &NeoInteger {
453    type Output = NeoInteger;
454    fn bitor(self, rhs: NeoInteger) -> Self::Output {
455        NeoInteger::new(&self.0 | rhs.0)
456    }
457}
458
459impl BitOr<&NeoInteger> for &NeoInteger {
460    type Output = NeoInteger;
461    fn bitor(self, rhs: &NeoInteger) -> Self::Output {
462        NeoInteger::new(&self.0 | &rhs.0)
463    }
464}
465
466impl BitXor for NeoInteger {
467    type Output = Self;
468    fn bitxor(self, rhs: Self) -> Self::Output {
469        Self(self.0 ^ rhs.0)
470    }
471}
472
473impl BitXor<&NeoInteger> for NeoInteger {
474    type Output = Self;
475    fn bitxor(self, rhs: &NeoInteger) -> Self::Output {
476        Self(self.0 ^ &rhs.0)
477    }
478}
479
480impl BitXor<NeoInteger> for &NeoInteger {
481    type Output = NeoInteger;
482    fn bitxor(self, rhs: NeoInteger) -> Self::Output {
483        NeoInteger::new(&self.0 ^ rhs.0)
484    }
485}
486
487impl BitXor<&NeoInteger> for &NeoInteger {
488    type Output = NeoInteger;
489    fn bitxor(self, rhs: &NeoInteger) -> Self::Output {
490        NeoInteger::new(&self.0 ^ &rhs.0)
491    }
492}
493
494impl Default for NeoInteger {
495    fn default() -> Self {
496        NeoInteger::zero()
497    }
498}