snarkvm_console_network_environment/traits/
types.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use crate::prelude::*;
17
18/// Representation of an address.
19pub trait AddressTrait:
20    Copy
21    + Clone
22    + Compare
23    + Debug
24    + Deref
25    + Eq
26    + Equal
27    + Parser
28    + Send
29    + SizeInBits
30    + SizeInBytes
31    + Sync
32    + TypeName
33    + Visibility
34{
35}
36
37/// Representation of a boolean.
38pub trait BooleanTrait:
39    BitAndAssign
40    + BitAnd<Self, Output = Self>
41    + for<'a> BitAnd<&'a Self, Output = Self>
42    + BitOrAssign
43    + BitOr<Self, Output = Self>
44    + for<'a> BitOr<&'a Self, Output = Self>
45    + BitXorAssign
46    + BitXor<Self, Output = Self>
47    + for<'a> BitXor<&'a Self, Output = Self>
48    + Copy
49    + Clone
50    + Debug
51    + Deref
52    + Eq
53    + Equal
54    + Nand
55    + Nor
56    + Not
57    + Parser
58    + Send
59    + SizeInBits
60    + SizeInDataBits
61    + SizeInBytes
62    + Sync
63    + TypeName
64    + Uniform
65{
66}
67
68/// Representation of a base field element.
69pub trait FieldTrait:
70    'static
71    + Add<Self, Output = Self>
72    + for<'a> Add<&'a Self, Output = Self>
73    + AddAssign<Self>
74    + for<'a> AddAssign<&'a Self>
75    + Clone
76    + Copy
77    + Compare
78    + Debug
79    + Deref
80    + Div<Self, Output = Self>
81    + for<'a> Div<&'a Self, Output = Self>
82    + DivAssign<Self>
83    + for<'a> DivAssign<&'a Self>
84    + Double<Output = Self>
85    + Eq
86    + Equal
87    + FromBytes
88    + core::hash::Hash
89    + Inverse<Output = Self>
90    + Mul<Self, Output = Self>
91    + for<'a> Mul<&'a Self, Output = Self>
92    + MulAssign<Self>
93    + for<'a> MulAssign<&'a Self>
94    + Neg<Output = Self>
95    + One
96    + Ord
97    + Parser
98    + Pow<Self, Output = Self>
99    + for<'a> Pow<&'a Self, Output = Self>
100    + Product<Self>
101    + for<'a> Product<&'a Self>
102    + Send
103    + SizeInBits
104    + SizeInDataBits
105    + SizeInBytes
106    + Sync
107    + Square<Output = Self>
108    + SquareRoot<Output = Self>
109    + Sub<Self, Output = Self>
110    + for<'a> Sub<&'a Self, Output = Self>
111    + SubAssign<Self>
112    + for<'a> SubAssign<&'a Self>
113    + Sum<Self>
114    + for<'a> Sum<&'a Self>
115    + ToBytes
116    + TypeName
117    + Uniform
118    + Zero
119{
120}
121
122/// Representation of a group element.
123pub trait GroupTrait<S: ScalarTrait>:
124    'static
125    + Add<Self, Output = Self>
126    + for<'a> Add<&'a Self, Output = Self>
127    + AddAssign<Self>
128    + for<'a> AddAssign<&'a Self>
129    + Clone
130    + Copy
131    + Debug
132    + Double<Output = Self>
133    + Eq
134    + Equal
135    + Mul<S>
136    + for<'a> Mul<&'a S>
137    + MulAssign<S>
138    + for<'a> MulAssign<&'a S>
139    + Neg<Output = Self>
140    + Parser
141    + Send
142    + SizeInBits
143    + SizeInBytes
144    + Sync
145    + Sub<Self, Output = Self>
146    + for<'a> Sub<&'a Self, Output = Self>
147    + SubAssign<Self>
148    + for<'a> SubAssign<&'a Self>
149    + Sum<Self>
150    + for<'a> Sum<&'a Self>
151    + TypeName
152    + Uniform
153    + Visibility
154    + Zero
155{
156}
157
158/// Representation of a scalar field element.
159pub trait ScalarTrait:
160    'static
161    + Add<Self, Output = Self>
162    + for<'a> Add<&'a Self, Output = Self>
163    + AddAssign<Self>
164    + for<'a> AddAssign<&'a Self>
165    + Clone
166    + Copy
167    + Compare
168    + Debug
169    + Deref
170    + Div<Self, Output = Self>
171    + for<'a> Div<&'a Self, Output = Self>
172    + DivAssign<Self>
173    + for<'a> DivAssign<&'a Self>
174    + Double<Output = Self>
175    + Eq
176    + Equal
177    + Inverse<Output = Self>
178    + Mul<Self, Output = Self>
179    + for<'a> Mul<&'a Self, Output = Self>
180    + MulAssign<Self>
181    + for<'a> MulAssign<&'a Self>
182    + Neg<Output = Self>
183    + One
184    + Parser
185    + Pow<Self, Output = Self>
186    + for<'a> Pow<&'a Self, Output = Self>
187    + Product<Self>
188    + for<'a> Product<&'a Self>
189    + Send
190    + SizeInBits
191    + SizeInDataBits
192    + SizeInBytes
193    + Sync
194    + Square<Output = Self>
195    + Sub<Self, Output = Self>
196    + for<'a> Sub<&'a Self, Output = Self>
197    + SubAssign<Self>
198    + for<'a> SubAssign<&'a Self>
199    + Sum<Self>
200    + for<'a> Sum<&'a Self>
201    + TypeName
202    + Uniform
203    + Zero
204{
205}
206
207/// Representation of a string.
208pub trait StringTrait:
209    Clone + Debug + Display + Eq + Equal + FromBytes + Parser + Send + Sync + ToBytes + TypeName + Uniform
210{
211}
212
213/// Representation of an integer.
214pub trait IntegerTrait<I: integer_type::IntegerType, U8: IntegerCore<u8>, U16: IntegerCore<u16>, U32: IntegerCore<u32>>:
215    IntegerCore<I>
216    + Pow<U8, Output = Self>
217    + Shl<U8, Output = Self>
218    + for<'a> Shl<&'a U8, Output = Self>
219    + ShlChecked<U8, Output = Self>
220    + ShlWrapped<U8, Output = Self>
221    + ShlAssign<U8>
222    + Shr<U8, Output = Self>
223    + for<'a> Shr<&'a U8, Output = Self>
224    + ShrChecked<U8, Output = Self>
225    + ShrWrapped<U8, Output = Self>
226    + ShrAssign<U8>
227    + Pow<U16, Output = Self>
228    + Shl<U16, Output = Self>
229    + for<'a> Shl<&'a U16, Output = Self>
230    + ShlChecked<U16, Output = Self>
231    + ShlWrapped<U16, Output = Self>
232    + ShlAssign<U16>
233    + Shr<U16, Output = Self>
234    + for<'a> Shr<&'a U16, Output = Self>
235    + ShrChecked<U16, Output = Self>
236    + ShrWrapped<U16, Output = Self>
237    + ShrAssign<U16>
238    + Pow<U32, Output = Self>
239    + Shl<U32, Output = Self>
240    + for<'a> Shl<&'a U32, Output = Self>
241    + ShlChecked<U32, Output = Self>
242    + ShlWrapped<U32, Output = Self>
243    + ShlAssign<U32>
244    + Shr<U32, Output = Self>
245    + for<'a> Shr<&'a U32, Output = Self>
246    + ShrChecked<U32, Output = Self>
247    + ShrWrapped<U32, Output = Self>
248    + ShrAssign<U32>
249{
250}
251
252pub trait IntegerCore<I: integer_type::IntegerType>:
253    'static
254    + Add<Self, Output = Self>
255    + for<'a> Add<&'a Self, Output = Self>
256    + AddAssign<Self>
257    + for<'a> AddAssign<&'a Self>
258    + BitAndAssign
259    + BitAnd<Self, Output = Self>
260    + for<'a> BitAnd<&'a Self, Output = Self>
261    + BitOrAssign
262    + BitOr<Self, Output = Self>
263    + for<'a> BitOr<&'a Self, Output = Self>
264    + BitXorAssign
265    + BitXor<Self, Output = Self>
266    + for<'a> BitXor<&'a Self, Output = Self>
267    + Copy
268    + Clone
269    + Compare
270    + Debug
271    + Deref
272    + Div<Self, Output = Self>
273    + for<'a> Div<&'a Self, Output = Self>
274    + DivAssign<Self>
275    + for<'a> DivAssign<&'a Self>
276    + Eq
277    + Equal
278    + Modulo
279    + Mul<Self, Output = Self>
280    + for<'a> Mul<&'a Self, Output = Self>
281    + MulAssign<Self>
282    + for<'a> MulAssign<&'a Self>
283    + Neg<Output = Self>
284    + Not<Output = Self>
285    + One
286    + Parser
287    + Rem<Self, Output = Self>
288    + for<'a> Rem<&'a Self, Output = Self>
289    + RemAssign<Self>
290    + for<'a> RemAssign<&'a Self>
291    + Send
292    + SizeInBits
293    + SizeInBytes
294    + Sync
295    + Sub<Self, Output = Self>
296    + for<'a> Sub<&'a Self, Output = Self>
297    + SubAssign<Self>
298    + for<'a> SubAssign<&'a Self>
299    + TypeName
300    + Uniform
301    + Visibility
302    + Zero
303{
304}
305
306pub mod integer_type {
307    use snarkvm_utilities::{FromBits, FromBytes, ToBits, ToBytes, Uniform};
308
309    use core::{
310        fmt::{Debug, Display},
311        hash::Hash,
312        num::ParseIntError,
313        ops::{Div, Rem},
314        str::FromStr,
315    };
316    use num_traits::{
317        CheckedNeg,
318        CheckedRem,
319        CheckedShr,
320        One as NumOne,
321        PrimInt,
322        ToPrimitive,
323        WrappingAdd,
324        WrappingMul,
325        WrappingNeg,
326        WrappingShl,
327        WrappingShr,
328        WrappingSub,
329        Zero as NumZero,
330    };
331
332    /// Trait bound for integer values. Common to both signed and unsigned integers.
333    pub trait IntegerType:
334        'static
335        + CheckedAbs
336        + CheckedNeg
337        + CheckedPow
338        + CheckedRem
339        + CheckedShl
340        + CheckedShr
341        + Debug
342        + Default
343        + Display
344        + FromBits
345        + FromBytes
346        + FromStr<Err = ParseIntError>
347        + Hash
348        + Modulo
349        + NumZero
350        + NumOne
351        + PartialOrd
352        + Send
353        + Sync
354        + ToBits
355        + ToBytes
356        + ToPrimitive
357        + Uniform
358        + WrappingAbs
359        + WrappingAdd
360        + WrappingMul
361        + WrappingNeg
362        + WrappingPow
363        + WrappingRem
364        + WrappingShl
365        + WrappingShr
366        + WrappingSub
367        + WrappingDiv
368        + IntegerProperties
369    {
370    }
371
372    impl IntegerType for i8 {}
373    impl IntegerType for i16 {}
374    impl IntegerType for i32 {}
375    impl IntegerType for i64 {}
376    impl IntegerType for i128 {}
377
378    impl IntegerType for u8 {}
379    impl IntegerType for u16 {}
380    impl IntegerType for u32 {}
381    impl IntegerType for u64 {}
382    impl IntegerType for u128 {}
383
384    macro_rules! binary_impl {
385        ($trait_name:ident, $t:ty, $method:ident, $arg1: ident, $argname:ident, $arg2: ident, $rt:ty, $body:expr) => {
386            impl $trait_name for $t {
387                #[inline]
388                fn $method(&$arg1, $argname: &$arg2) -> $rt {
389                    $body
390                }
391            }
392        };
393    }
394
395    pub trait CheckedPow: Sized {
396        fn checked_pow(&self, v: &u32) -> Option<Self>;
397    }
398
399    binary_impl!(CheckedPow, u8, checked_pow, self, v, u32, Option<u8>, u8::checked_pow(*self, *v));
400    binary_impl!(CheckedPow, u16, checked_pow, self, v, u32, Option<u16>, u16::checked_pow(*self, *v));
401    binary_impl!(CheckedPow, u32, checked_pow, self, v, u32, Option<u32>, u32::checked_pow(*self, *v));
402    binary_impl!(CheckedPow, u64, checked_pow, self, v, u32, Option<u64>, u64::checked_pow(*self, *v));
403    binary_impl!(CheckedPow, u128, checked_pow, self, v, u32, Option<u128>, u128::checked_pow(*self, *v));
404    binary_impl!(CheckedPow, i8, checked_pow, self, v, u32, Option<i8>, i8::checked_pow(*self, *v));
405    binary_impl!(CheckedPow, i16, checked_pow, self, v, u32, Option<i16>, i16::checked_pow(*self, *v));
406    binary_impl!(CheckedPow, i32, checked_pow, self, v, u32, Option<i32>, i32::checked_pow(*self, *v));
407    binary_impl!(CheckedPow, i64, checked_pow, self, v, u32, Option<i64>, i64::checked_pow(*self, *v));
408    binary_impl!(CheckedPow, i128, checked_pow, self, v, u32, Option<i128>, i128::checked_pow(*self, *v));
409
410    pub trait CheckedShl: Sized {
411        fn checked_shl(&self, v: &u32) -> Option<Self>;
412    }
413
414    #[rustfmt::skip]
415    binary_impl!(CheckedShl, u8, checked_shl, self, v, u32, Option<u8>, u8::checked_pow(2u8, *v).and_then(|x| u8::checked_mul(*self, x)));
416    #[rustfmt::skip]
417    binary_impl!(CheckedShl, u16, checked_shl, self, v, u32, Option<u16>, u16::checked_pow(2u16, *v).and_then(|x| u16::checked_mul(*self, x)));
418    #[rustfmt::skip]
419    binary_impl!(CheckedShl, u32, checked_shl, self, v, u32, Option<u32>, u32::checked_pow(2u32, *v).and_then(|x| u32::checked_mul(*self, x)));
420    #[rustfmt::skip]
421    binary_impl!(CheckedShl, u64, checked_shl, self, v, u32, Option<u64>, u64::checked_pow(2u64, *v).and_then(|x| u64::checked_mul(*self, x)));
422    #[rustfmt::skip]
423    binary_impl!(CheckedShl, u128, checked_shl, self, v, u32, Option<u128>, u128::checked_pow(2u128, *v).and_then(|x| u128::checked_mul(*self, x)));
424    #[rustfmt::skip]
425    binary_impl!(CheckedShl, i8, checked_shl, self, v, u32, Option<i8>, u8::checked_pow(2u8, *v).and_then(|x| i8::checked_mul(if (x as i8) == i8::MIN { self.wrapping_neg() } else { *self }, x as i8)));
426    #[rustfmt::skip]
427    binary_impl!(CheckedShl, i16, checked_shl, self, v, u32, Option<i16>, u16::checked_pow(2u16, *v).and_then(|x| i16::checked_mul(if (x as i16) == i16::MIN { self.wrapping_neg() } else { *self }, x as i16)));
428    #[rustfmt::skip]
429    binary_impl!(CheckedShl, i32, checked_shl, self, v, u32, Option<i32>, u32::checked_pow(2u32, *v).and_then(|x| i32::checked_mul(if (x as i32) == i32::MIN { self.wrapping_neg() } else { *self }, x as i32)));
430    #[rustfmt::skip]
431    binary_impl!(CheckedShl, i64, checked_shl, self, v, u32, Option<i64>, u64::checked_pow(2u64, *v).and_then(|x| i64::checked_mul(if (x as i64) == i64::MIN { self.wrapping_neg() } else { *self }, x as i64)));
432    #[rustfmt::skip]
433    binary_impl!(CheckedShl, i128, checked_shl, self, v, u32, Option<i128>, u128::checked_pow(2u128, *v).and_then(|x| i128::checked_mul(if (x as i128) == i128::MIN { self.wrapping_neg() } else { *self }, x as i128)));
434
435    pub trait Modulo: Sized + Rem<Self, Output = Self> {
436        fn modulo(&self, v: &Self) -> Self;
437    }
438
439    binary_impl!(Modulo, u8, modulo, self, v, Self, u8, u8::wrapping_rem(*self, *v));
440    binary_impl!(Modulo, u16, modulo, self, v, Self, u16, u16::wrapping_rem(*self, *v));
441    binary_impl!(Modulo, u32, modulo, self, v, Self, u32, u32::wrapping_rem(*self, *v));
442    binary_impl!(Modulo, u64, modulo, self, v, Self, u64, u64::wrapping_rem(*self, *v));
443    binary_impl!(Modulo, u128, modulo, self, v, Self, u128, u128::wrapping_rem(*self, *v));
444    #[rustfmt::skip]
445    binary_impl!(Modulo, i8, modulo, self, _v, Self, i8, panic!("modulo is not implemented for i8"));
446    #[rustfmt::skip]
447    binary_impl!(Modulo, i16, modulo, self, _v, Self, i16, panic!("modulo is not implemented for i16"));
448    #[rustfmt::skip]
449    binary_impl!(Modulo, i32, modulo, self, _v, Self, i32, panic!("modulo is not implemented for i32"));
450    #[rustfmt::skip]
451    binary_impl!(Modulo, i64, modulo, self, _v, Self, i64, panic!("modulo is not implemented for i64"));
452    #[rustfmt::skip]
453    binary_impl!(Modulo, i128, modulo, self, _v, Self, i128, panic!("modulo is not implemented for i128"));
454
455    pub trait WrappingDiv: Sized + Div<Self, Output = Self> {
456        fn wrapping_div(&self, v: &Self) -> Self;
457    }
458
459    binary_impl!(WrappingDiv, u8, wrapping_div, self, v, Self, u8, u8::wrapping_div(*self, *v));
460    binary_impl!(WrappingDiv, u16, wrapping_div, self, v, Self, u16, u16::wrapping_div(*self, *v));
461    binary_impl!(WrappingDiv, u32, wrapping_div, self, v, Self, u32, u32::wrapping_div(*self, *v));
462    binary_impl!(WrappingDiv, u64, wrapping_div, self, v, Self, u64, u64::wrapping_div(*self, *v));
463    binary_impl!(WrappingDiv, u128, wrapping_div, self, v, Self, u128, u128::wrapping_div(*self, *v));
464    binary_impl!(WrappingDiv, i8, wrapping_div, self, v, Self, i8, i8::wrapping_div(*self, *v));
465    binary_impl!(WrappingDiv, i16, wrapping_div, self, v, Self, i16, i16::wrapping_div(*self, *v));
466    binary_impl!(WrappingDiv, i32, wrapping_div, self, v, Self, i32, i32::wrapping_div(*self, *v));
467    binary_impl!(WrappingDiv, i64, wrapping_div, self, v, Self, i64, i64::wrapping_div(*self, *v));
468    binary_impl!(WrappingDiv, i128, wrapping_div, self, v, Self, i128, i128::wrapping_div(*self, *v));
469
470    pub trait WrappingRem: Sized + Rem<Self, Output = Self> {
471        fn wrapping_rem(&self, v: &Self) -> Self;
472    }
473
474    binary_impl!(WrappingRem, u8, wrapping_rem, self, v, Self, u8, u8::wrapping_rem(*self, *v));
475    binary_impl!(WrappingRem, u16, wrapping_rem, self, v, Self, u16, u16::wrapping_rem(*self, *v));
476    binary_impl!(WrappingRem, u32, wrapping_rem, self, v, Self, u32, u32::wrapping_rem(*self, *v));
477    binary_impl!(WrappingRem, u64, wrapping_rem, self, v, Self, u64, u64::wrapping_rem(*self, *v));
478    binary_impl!(WrappingRem, u128, wrapping_rem, self, v, Self, u128, u128::wrapping_rem(*self, *v));
479    binary_impl!(WrappingRem, i8, wrapping_rem, self, v, Self, i8, i8::wrapping_rem(*self, *v));
480    binary_impl!(WrappingRem, i16, wrapping_rem, self, v, Self, i16, i16::wrapping_rem(*self, *v));
481    binary_impl!(WrappingRem, i32, wrapping_rem, self, v, Self, i32, i32::wrapping_rem(*self, *v));
482    binary_impl!(WrappingRem, i64, wrapping_rem, self, v, Self, i64, i64::wrapping_rem(*self, *v));
483    binary_impl!(WrappingRem, i128, wrapping_rem, self, v, Self, i128, i128::wrapping_rem(*self, *v));
484
485    pub trait WrappingPow: Sized {
486        fn wrapping_pow(&self, v: &u32) -> Self;
487    }
488
489    binary_impl!(WrappingPow, u8, wrapping_pow, self, v, u32, u8, u8::wrapping_pow(*self, *v));
490    binary_impl!(WrappingPow, u16, wrapping_pow, self, v, u32, u16, u16::wrapping_pow(*self, *v));
491    binary_impl!(WrappingPow, u32, wrapping_pow, self, v, u32, u32, u32::wrapping_pow(*self, *v));
492    binary_impl!(WrappingPow, u64, wrapping_pow, self, v, u32, u64, u64::wrapping_pow(*self, *v));
493    binary_impl!(WrappingPow, u128, wrapping_pow, self, v, u32, u128, u128::wrapping_pow(*self, *v));
494    binary_impl!(WrappingPow, i8, wrapping_pow, self, v, u32, i8, i8::wrapping_pow(*self, *v));
495    binary_impl!(WrappingPow, i16, wrapping_pow, self, v, u32, i16, i16::wrapping_pow(*self, *v));
496    binary_impl!(WrappingPow, i32, wrapping_pow, self, v, u32, i32, i32::wrapping_pow(*self, *v));
497    binary_impl!(WrappingPow, i64, wrapping_pow, self, v, u32, i64, i64::wrapping_pow(*self, *v));
498    binary_impl!(WrappingPow, i128, wrapping_pow, self, v, u32, i128, i128::wrapping_pow(*self, *v));
499
500    macro_rules! unary_impl {
501        ($trait_name:ident, $t:ty, $method:ident, $arg: ident, $rt:ty, $body:expr) => {
502            impl $trait_name for $t {
503                #[inline]
504                fn $method(&$arg) -> $rt {
505                    $body
506                }
507            }
508        };
509    }
510
511    pub trait CheckedAbs: Sized {
512        fn checked_abs(&self) -> Option<Self>;
513    }
514
515    unary_impl!(CheckedAbs, u8, checked_abs, self, Option<u8>, Some(*self));
516    unary_impl!(CheckedAbs, u16, checked_abs, self, Option<u16>, Some(*self));
517    unary_impl!(CheckedAbs, u32, checked_abs, self, Option<u32>, Some(*self));
518    unary_impl!(CheckedAbs, u64, checked_abs, self, Option<u64>, Some(*self));
519    unary_impl!(CheckedAbs, u128, checked_abs, self, Option<u128>, Some(*self));
520    unary_impl!(CheckedAbs, i8, checked_abs, self, Option<i8>, i8::checked_abs(*self));
521    unary_impl!(CheckedAbs, i16, checked_abs, self, Option<i16>, i16::checked_abs(*self));
522    unary_impl!(CheckedAbs, i32, checked_abs, self, Option<i32>, i32::checked_abs(*self));
523    unary_impl!(CheckedAbs, i64, checked_abs, self, Option<i64>, i64::checked_abs(*self));
524    unary_impl!(CheckedAbs, i128, checked_abs, self, Option<i128>, i128::checked_abs(*self));
525
526    pub trait WrappingAbs: Sized {
527        fn wrapping_abs(&self) -> Self;
528    }
529
530    unary_impl!(WrappingAbs, u8, wrapping_abs, self, u8, *self);
531    unary_impl!(WrappingAbs, u16, wrapping_abs, self, u16, *self);
532    unary_impl!(WrappingAbs, u32, wrapping_abs, self, u32, *self);
533    unary_impl!(WrappingAbs, u64, wrapping_abs, self, u64, *self);
534    unary_impl!(WrappingAbs, u128, wrapping_abs, self, u128, *self);
535    unary_impl!(WrappingAbs, i8, wrapping_abs, self, i8, i8::wrapping_abs(*self));
536    unary_impl!(WrappingAbs, i16, wrapping_abs, self, i16, i16::wrapping_abs(*self));
537    unary_impl!(WrappingAbs, i32, wrapping_abs, self, i32, i32::wrapping_abs(*self));
538    unary_impl!(WrappingAbs, i64, wrapping_abs, self, i64, i64::wrapping_abs(*self));
539    unary_impl!(WrappingAbs, i128, wrapping_abs, self, i128, i128::wrapping_abs(*self));
540
541    /// Properties common to all integer types.
542    pub trait IntegerProperties: PrimInt + Debug + Display {
543        type Dual: IntegerType;
544        /// Returns the number of bits required to represent this integer.
545        const BITS: u64;
546        /// Returns the maximum value representable by this integer.
547        const MAX: Self;
548        /// Returns the minimum value representable by this integer.
549        const MIN: Self;
550
551        /// Returns `true` if `Self` is a signed integer and `false` otherwise.
552        fn is_signed() -> bool;
553
554        /// Returns the name of the integer type as a string slice. (i.e. "u8")
555        fn type_name() -> &'static str;
556
557        /// Casts `self` into its dual.
558        fn into_dual(self) -> Self::Dual;
559    }
560
561    macro_rules! integer_properties_impl {
562        ($t:ty, $dual:ty, $is_signed:expr) => {
563            impl IntegerProperties for $t {
564                type Dual = $dual;
565
566                const BITS: u64 = <$t>::BITS as u64;
567                const MAX: $t = <$t>::MAX;
568                const MIN: $t = <$t>::MIN;
569
570                #[inline]
571                fn is_signed() -> bool {
572                    $is_signed
573                }
574
575                #[inline]
576                fn type_name() -> &'static str {
577                    std::any::type_name::<$t>()
578                }
579
580                #[inline]
581                fn into_dual(self) -> Self::Dual {
582                    self as $dual
583                }
584            }
585        };
586    }
587
588    integer_properties_impl!(u8, i8, false);
589    integer_properties_impl!(u16, i16, false);
590    integer_properties_impl!(u32, i32, false);
591    integer_properties_impl!(u64, i64, false);
592    integer_properties_impl!(u128, i128, false);
593    integer_properties_impl!(i8, u8, true);
594    integer_properties_impl!(i16, u16, true);
595    integer_properties_impl!(i32, u32, true);
596    integer_properties_impl!(i64, u64, true);
597    integer_properties_impl!(i128, u128, true);
598}
599
600/// Trait pattern to prevent abuse of Magnitude.
601pub mod integer_magnitude {
602    use super::integer_type::IntegerType;
603    use num_traits::{ToPrimitive, Unsigned};
604
605    /// Trait for integers that can be used as an unsigned magnitude.
606    /// `Magnitude`s are either used to represent an integer exponent
607    /// or the right operand in integer shift operations.
608    pub trait Magnitude: IntegerType + ToPrimitive + Unsigned {}
609    impl Magnitude for u8 {}
610    impl Magnitude for u16 {}
611    impl Magnitude for u32 {}
612}