arbitrary_int/
traits.rs

1use crate::TryNewError;
2use core::fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex};
3use core::ops::{
4    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
5    Mul, MulAssign, Neg, Not, Sub, SubAssign,
6};
7
8pub(crate) mod sealed {
9    /// Ensures that outside users can not implement the traits provided by this crate.
10    #[cfg_attr(feature = "const_convert_and_const_trait_impl", const_trait)]
11    pub trait Sealed {}
12}
13
14// TODO: Inline this macro once we drop const_convert_and_const_trait_impl
15#[cfg(feature = "const_convert_and_const_trait_impl")]
16macro_rules! define_as {
17    () => {
18        #[inline]
19        fn as_<T: ~const Integer>(self) -> T {
20            T::masked_new(self)
21        }
22    };
23}
24
25#[cfg(not(feature = "const_convert_and_const_trait_impl"))]
26macro_rules! define_as {
27    () => {
28        #[inline]
29        fn as_<T: Integer>(self) -> T {
30            T::masked_new(self)
31        }
32    };
33}
34
35/// Trait that is only implemented for `u8`, `u16`, `u32`, `u64`, `u128` and their signed
36/// counterparts `i8`, `i16`, `i32`, `i64`, `i128`.
37#[cfg_attr(feature = "const_convert_and_const_trait_impl", const_trait)]
38pub trait BuiltinInteger: sealed::Sealed {}
39
40/// The base trait for integer numbers, either built-in (u8, i8, u16, i16, u32, i32, u64, i64,
41/// u128, i128) or arbitrary-int (u1, i1, u7, i7 etc.).
42#[cfg_attr(feature = "const_convert_and_const_trait_impl", const_trait)]
43pub trait Integer:
44    Sized
45    + Copy
46    + Clone
47    + PartialOrd
48    + Ord
49    + PartialEq
50    + Eq
51    + Debug
52    + Display
53    + LowerHex
54    + UpperHex
55    + Octal
56    + Binary
57    + sealed::Sealed
58    + Add<Self, Output = Self>
59    + AddAssign<Self>
60    + Sub<Self, Output = Self>
61    + SubAssign<Self>
62    + Div<Self, Output = Self>
63    + DivAssign<Self>
64    + Mul<Self, Output = Self>
65    + MulAssign<Self>
66    + Not<Output = Self>
67    + BitAnd<Self, Output = Self>
68    + BitAndAssign<Self>
69    + BitOr<Self, Output = Self>
70    + BitOrAssign<Self>
71    + BitXor<Self, Output = Self>
72    + BitXorAssign<Self>
73{
74    type UnderlyingType: Integer
75        + BuiltinInteger
76        + Debug
77        + TryFrom<u8>
78        + TryFrom<u16>
79        + TryFrom<u32>
80        + TryFrom<u64>
81        + TryFrom<u128>;
82
83    /// An equivalent type with the same number of bits but unsigned. If
84    /// the type is already unsigned, this is the same type.
85    /// - i4::UnsignedInteger == u4
86    /// - u60::SignedInteger == u60
87    type UnsignedInteger: UnsignedInteger;
88
89    /// An equivalent type with the same number of bits but signed. If
90    /// the type is already signed, this is the same type.
91    /// - i4::UnsignedInteger == i4
92    /// - u60::SignedInteger == i60
93    type SignedInteger: SignedInteger;
94
95    /// Number of bits that can fit in this type
96    const BITS: usize;
97
98    /// The number 0
99    const ZERO: Self;
100
101    /// Minimum value that can be represented by this type
102    const MIN: Self;
103
104    /// Maximum value that can be represented by this type
105    const MAX: Self;
106
107    /// Creates a number from the given value, throwing an error if the value is too large.
108    /// This constructor is useful when creating a value from a literal.
109    fn new(value: Self::UnderlyingType) -> Self;
110
111    /// Creates a number from the given value, return None if the value is too large
112    fn try_new(value: Self::UnderlyingType) -> Result<Self, TryNewError>;
113
114    fn value(self) -> Self::UnderlyingType;
115
116    /// Creates a number from the given value, throwing an error if the value is too large.
117    /// This constructor is useful when the value is convertible to T. Use [`Self::new`] for literals.
118    #[cfg(not(feature = "const_convert_and_const_trait_impl"))]
119    fn from_<T: Integer>(value: T) -> Self;
120
121    /// Creates an instance from the given `value`. Unlike the various `new...` functions, this
122    /// will never fail as the value is masked to the result size.
123    fn masked_new<T: Integer>(value: T) -> Self;
124
125    fn as_u8(self) -> u8;
126
127    fn as_u16(self) -> u16;
128
129    fn as_u32(self) -> u32;
130
131    fn as_u64(self) -> u64;
132
133    fn as_u128(self) -> u128;
134
135    fn as_usize(self) -> usize;
136
137    fn as_i8(self) -> i8;
138
139    fn as_i16(self) -> i16;
140
141    fn as_i32(self) -> i32;
142
143    fn as_i64(self) -> i64;
144
145    fn as_i128(self) -> i128;
146
147    fn as_isize(self) -> isize;
148
149    /// Converts the number to its unsigned equivalent. For types that have fewer bits
150    /// than the underlying type, this involves a zero extension. Types that are
151    /// already unsigned will return themselves.
152    fn to_unsigned(self) -> Self::UnsignedInteger;
153
154    /// Converts the number from its unsigned equivalent. For types that have fewer bits
155    /// than the underlying type, this involves a sign extension, if this type is a signed type.
156    /// Types that are already unsigned will return themselves.
157    fn from_unsigned(value: Self::UnsignedInteger) -> Self;
158
159    define_as!();
160}
161
162/// The base trait for all signed numbers, either built-in (i8, i16, i32, i64, i128) or
163/// arbitrary-int (i1, i7 etc.).
164#[cfg_attr(feature = "const_convert_and_const_trait_impl", const_trait)]
165pub trait SignedInteger: Integer + Neg<Output = Self> {}
166
167/// The base trait for all unsigned numbers, either built-in (u8, u16, u32, u64, u128) or
168/// arbitrary-int (u1, u7 etc.).
169#[cfg_attr(feature = "const_convert_and_const_trait_impl", const_trait)]
170pub trait UnsignedInteger: Integer {}