osom_lib_rand/
number.rs

1//! The module contains the definition of the [`Number`] trait
2//! and its implementations for `u32`, `u64` and `u128`.
3#![allow(clippy::cast_possible_truncation)]
4
5use core::fmt::{Debug, Display};
6use core::hash::Hash;
7use core::mem::size_of;
8
9trait Private {}
10
11/// Represents all the number types that [`Number`] trait
12/// is implemented for.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14#[repr(u8)]
15pub enum NumberType {
16    U32,
17    U64,
18    U128,
19}
20
21/// Marker trait that abstracts the following numerical types:
22/// `u32`, `u64` and `u128`.
23///
24/// # Notes
25///
26/// This trait depends on private trait, and thus extending it
27/// is not possible.
28#[allow(private_bounds)]
29pub trait Number:
30    'static + Clone + Copy + Debug + Display + PartialEq + Eq + Hash + PartialOrd + Ord + Default + Private
31{
32    /// Represents the associated byte representation of the number, e.g. `[u8; 4]` for `u32`.
33    type ByteRepr: AsRef<[u8]> + AsMut<[u8]> + Default;
34
35    /// The type of the number.
36    const NUMBER_TYPE: NumberType;
37
38    /// The size of the number in bytes.
39    const SIZE: usize;
40
41    /// The number zero.
42    const ZERO: Self;
43
44    /// The number one.
45    const ONE: Self;
46
47    /// The highest possible value of the number.
48    const HIGHEST: Self;
49
50    /// Returns the sum of two numbers, wrapping around if the result is too large.
51    #[must_use]
52    fn wrapping_add(self, other: Self) -> Self;
53
54    /// Returns the difference of two numbers, wrapping around if the result is too small.
55    #[must_use]
56    fn wrapping_sub(self, other: Self) -> Self;
57
58    /// Returns the product of two numbers, wrapping around if the result is too large.
59    #[must_use]
60    fn wrapping_mul(self, other: Self) -> Self;
61
62    /// Returns the quotient of two numbers, wrapping around if the result is too large.
63    #[must_use]
64    fn wrapping_div(self, other: Self) -> Self;
65
66    /// Returns the remainder of the division of two numbers.
67    #[must_use]
68    fn wrapping_rem(self, other: Self) -> Self;
69
70    /// Returns the result of the left shift of the number by the given number of bits.
71    #[must_use]
72    fn wrapping_shl(self, other: u32) -> Self;
73
74    /// Returns the result of the right shift of the number by the given number of bits.
75    #[must_use]
76    fn wrapping_shr(self, other: u32) -> Self;
77
78    /// Returns the number as a `u128`, which is guaranteed to be big enough to hold
79    /// any [`Number`] value.
80    #[must_use]
81    fn as_u128(self) -> u128;
82
83    /// Creates a number from a `u32` value, which is guaranteed to be small enough
84    /// to fit into the number.
85    #[must_use]
86    fn from_u32(value: u32) -> Self;
87
88    /// Creates a number from its byte representation.
89    ///
90    /// # Notes
91    ///
92    /// This method is not portable, in particular it uses platform-specific
93    /// endianness.
94    #[must_use]
95    fn from_bytes(bytes: &[u8]) -> Self;
96
97    /// Returns the byte representation of the number.
98    ///
99    /// # Notes
100    ///
101    /// This method is not portable, in particular it uses platform-specific
102    /// endianness.
103    #[must_use]
104    fn to_bytes(self) -> Self::ByteRepr;
105
106    /// Creates a number from a `u32` value
107    ///
108    /// # Safety
109    ///
110    /// It does not check whether passed value is small enough to fit into `Self`.
111    unsafe fn from_u64_unchecked(value: u64) -> Self;
112
113    /// Creates a number from a `u128` value
114    ///
115    /// # Safety
116    ///
117    /// It does not check whether passed value is small enough to fit into `Self`.
118    unsafe fn from_u128_unchecked(value: u128) -> Self;
119}
120
121impl Private for u32 {}
122impl Private for u64 {}
123impl Private for u128 {}
124
125impl Number for u32 {
126    type ByteRepr = [u8; 4];
127
128    const NUMBER_TYPE: NumberType = NumberType::U32;
129    const SIZE: usize = size_of::<Self>();
130    const ZERO: Self = 0;
131    const ONE: Self = 1;
132    const HIGHEST: Self = u32::MAX;
133
134    fn wrapping_add(self, other: Self) -> Self {
135        self.wrapping_add(other)
136    }
137    fn wrapping_sub(self, other: Self) -> Self {
138        self.wrapping_sub(other)
139    }
140    fn wrapping_mul(self, other: Self) -> Self {
141        self.wrapping_mul(other)
142    }
143    fn wrapping_div(self, other: Self) -> Self {
144        self.wrapping_div(other)
145    }
146    fn wrapping_rem(self, other: Self) -> Self {
147        self.wrapping_rem(other)
148    }
149    fn wrapping_shl(self, other: u32) -> Self {
150        self.wrapping_shl(other)
151    }
152    fn wrapping_shr(self, other: u32) -> Self {
153        self.wrapping_shr(other)
154    }
155    fn as_u128(self) -> u128 {
156        u128::from(self)
157    }
158
159    #[inline(always)]
160    fn from_u32(value: u32) -> Self {
161        value
162    }
163    fn from_bytes(bytes: &[u8]) -> Self {
164        assert!(bytes.len() >= size_of::<Self>());
165        let mut result = [0u8; size_of::<Self>()];
166        result.copy_from_slice(bytes);
167        Self::from_ne_bytes(result)
168    }
169    fn to_bytes(self) -> Self::ByteRepr {
170        self.to_ne_bytes()
171    }
172
173    #[inline(always)]
174    unsafe fn from_u64_unchecked(value: u64) -> Self {
175        value as u32
176    }
177
178    #[inline(always)]
179    unsafe fn from_u128_unchecked(value: u128) -> Self {
180        value as u32
181    }
182}
183
184impl Number for u64 {
185    type ByteRepr = [u8; 8];
186
187    const NUMBER_TYPE: NumberType = NumberType::U64;
188    const SIZE: usize = size_of::<Self>();
189    const ZERO: Self = 0;
190    const ONE: Self = 1;
191    const HIGHEST: Self = u64::MAX;
192
193    fn wrapping_add(self, other: Self) -> Self {
194        self.wrapping_add(other)
195    }
196    fn wrapping_shl(self, other: u32) -> Self {
197        self.wrapping_shl(other)
198    }
199    fn wrapping_shr(self, other: u32) -> Self {
200        self.wrapping_shr(other)
201    }
202    fn wrapping_sub(self, other: Self) -> Self {
203        self.wrapping_sub(other)
204    }
205    fn wrapping_mul(self, other: Self) -> Self {
206        self.wrapping_mul(other)
207    }
208    fn wrapping_div(self, other: Self) -> Self {
209        self.wrapping_div(other)
210    }
211    fn wrapping_rem(self, other: Self) -> Self {
212        self.wrapping_rem(other)
213    }
214    fn as_u128(self) -> u128 {
215        u128::from(self)
216    }
217
218    #[inline(always)]
219    fn from_u32(value: u32) -> Self {
220        Self::from(value)
221    }
222    fn from_bytes(bytes: &[u8]) -> Self {
223        assert!(bytes.len() >= size_of::<Self>());
224        let mut result = [0u8; size_of::<Self>()];
225        result.copy_from_slice(bytes);
226        Self::from_ne_bytes(result)
227    }
228    fn to_bytes(self) -> Self::ByteRepr {
229        self.to_ne_bytes()
230    }
231
232    #[inline(always)]
233    unsafe fn from_u64_unchecked(value: u64) -> Self {
234        value
235    }
236
237    #[inline(always)]
238    unsafe fn from_u128_unchecked(value: u128) -> Self {
239        value as u64
240    }
241}
242
243impl Number for u128 {
244    type ByteRepr = [u8; 16];
245
246    const NUMBER_TYPE: NumberType = NumberType::U128;
247    const SIZE: usize = size_of::<Self>();
248    const ZERO: Self = 0;
249    const ONE: Self = 1;
250    const HIGHEST: Self = u128::MAX;
251
252    fn wrapping_add(self, other: Self) -> Self {
253        self.wrapping_add(other)
254    }
255    fn wrapping_shl(self, other: u32) -> Self {
256        self.wrapping_shl(other)
257    }
258    fn wrapping_shr(self, other: u32) -> Self {
259        self.wrapping_shr(other)
260    }
261    fn wrapping_sub(self, other: Self) -> Self {
262        self.wrapping_sub(other)
263    }
264    fn wrapping_mul(self, other: Self) -> Self {
265        self.wrapping_mul(other)
266    }
267    fn wrapping_div(self, other: Self) -> Self {
268        self.wrapping_div(other)
269    }
270    fn wrapping_rem(self, other: Self) -> Self {
271        self.wrapping_rem(other)
272    }
273    fn as_u128(self) -> u128 {
274        self
275    }
276
277    #[inline(always)]
278    fn from_u32(value: u32) -> Self {
279        Self::from(value)
280    }
281    fn from_bytes(bytes: &[u8]) -> Self {
282        assert!(bytes.len() >= size_of::<Self>());
283        let mut result = [0u8; size_of::<Self>()];
284        result.copy_from_slice(bytes);
285        Self::from_le_bytes(result)
286    }
287    fn to_bytes(self) -> Self::ByteRepr {
288        self.to_ne_bytes()
289    }
290
291    #[inline(always)]
292    unsafe fn from_u64_unchecked(value: u64) -> Self {
293        u128::from(value)
294    }
295
296    #[inline(always)]
297    unsafe fn from_u128_unchecked(value: u128) -> Self {
298        value
299    }
300}
301
302/// Holds the maximum size of all number types.
303pub const MAX_NUMBER_SIZE: usize = const {
304    let result = size_of::<u128>();
305    assert!(result >= size_of::<u64>());
306    assert!(result >= size_of::<u32>());
307    result
308};