Skip to main content

irox_tools/primitives/
mod.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2025 IROX Contributors
3//
4
5pub mod f32;
6pub mod f64;
7mod u128;
8pub mod u16;
9pub mod u32;
10pub mod u64;
11pub mod u8;
12mod wrapping;
13
14use crate::f64::FloatExt;
15use core::fmt::{Debug, Display};
16use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
17use core::str::FromStr;
18use irox_bits::{Error, MutBits, WriteToBEBits};
19pub use wrapping::*;
20
21///
22/// An integer!
23#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
24pub enum IntegerValue {
25    U8(u8),
26    U16(u16),
27    U32(u32),
28    U64(u64),
29    U128(u128),
30
31    I8(i8),
32    I16(i16),
33    I32(i32),
34    I64(i64),
35    I128(i128),
36}
37
38impl IntegerValue {
39    pub const fn to_be_u128(&self) -> u128 {
40        match self {
41            IntegerValue::U8(i) => *i as u128,
42            IntegerValue::U16(i) => *i as u128,
43            IntegerValue::U32(i) => *i as u128,
44            IntegerValue::U64(i) => *i as u128,
45            IntegerValue::U128(i) => *i,
46            IntegerValue::I8(i) => *i as u128,
47            IntegerValue::I16(i) => *i as u128,
48            IntegerValue::I32(i) => *i as u128,
49            IntegerValue::I64(i) => *i as u128,
50            IntegerValue::I128(i) => *i as u128,
51        }
52    }
53    pub const fn to_be_u64(&self) -> u64 {
54        match self {
55            IntegerValue::U8(i) => *i as u64,
56            IntegerValue::U16(i) => *i as u64,
57            IntegerValue::U32(i) => *i as u64,
58            IntegerValue::U64(i) => *i,
59            IntegerValue::U128(i) => *i as u64,
60            IntegerValue::I8(i) => *i as u64,
61            IntegerValue::I16(i) => *i as u64,
62            IntegerValue::I32(i) => *i as u64,
63            IntegerValue::I64(i) => *i as u64,
64            IntegerValue::I128(i) => *i as u64,
65        }
66    }
67    pub const fn to_be_u32(&self) -> u32 {
68        self.to_be_u64() as u32
69    }
70
71    #[must_use]
72    pub const fn to_le(&self) -> Self {
73        match self {
74            IntegerValue::U8(_) | IntegerValue::I8(_) => *self,
75            IntegerValue::U16(b) => IntegerValue::U16(b.to_le()),
76            IntegerValue::U32(b) => IntegerValue::U32(b.to_le()),
77            IntegerValue::U64(b) => IntegerValue::U64(b.to_le()),
78            IntegerValue::U128(b) => IntegerValue::U128(b.to_le()),
79            IntegerValue::I16(b) => IntegerValue::I16(b.to_le()),
80            IntegerValue::I32(b) => IntegerValue::I32(b.to_le()),
81            IntegerValue::I64(b) => IntegerValue::I64(b.to_le()),
82            IntegerValue::I128(b) => IntegerValue::I128(b.to_le()),
83        }
84    }
85}
86impl WriteToBEBits for IntegerValue {
87    fn write_be_to<T: MutBits + ?Sized>(&self, bits: &mut T) -> Result<usize, Error> {
88        match self {
89            IntegerValue::U8(i) => i.write_be_to(bits),
90            IntegerValue::U16(i) => i.write_be_to(bits),
91            IntegerValue::U32(i) => i.write_be_to(bits),
92            IntegerValue::U64(i) => i.write_be_to(bits),
93            IntegerValue::U128(i) => i.write_be_to(bits),
94            IntegerValue::I8(i) => i.write_be_to(bits),
95            IntegerValue::I16(i) => i.write_be_to(bits),
96            IntegerValue::I32(i) => i.write_be_to(bits),
97            IntegerValue::I64(i) => i.write_be_to(bits),
98            IntegerValue::I128(i) => i.write_be_to(bits),
99        }
100    }
101}
102
103macro_rules! impl_from_integer {
104    ($typ:ty, $($elem:tt)+) => {
105        impl From<$typ> for IntegerValue {
106            fn from(value: $typ) -> Self {
107                $($elem)+(value)
108            }
109        }
110        impl From<&$typ> for IntegerValue {
111            fn from(value: &$typ) -> Self {
112                $($elem)+(*value)
113            }
114        }
115        impl From<&mut $typ> for IntegerValue {
116            fn from(value: &mut $typ) -> Self {
117                $($elem)+(*value)
118            }
119        }
120    };
121}
122impl_from_integer!(u8, IntegerValue::U8);
123impl_from_integer!(i8, IntegerValue::I8);
124impl_from_integer!(u16, IntegerValue::U16);
125impl_from_integer!(i16, IntegerValue::I16);
126impl_from_integer!(u32, IntegerValue::U32);
127impl_from_integer!(i32, IntegerValue::I32);
128impl_from_integer!(u64, IntegerValue::U64);
129impl_from_integer!(i64, IntegerValue::I64);
130impl_from_integer!(u128, IntegerValue::U128);
131impl_from_integer!(i128, IntegerValue::I128);
132
133///
134/// Converts this value into a F64 using the `as` cast operation.
135pub trait ToF64 {
136    fn to_f64(&self) -> f64;
137}
138
139pub trait FromF64 {
140    fn from_f64(value: f64) -> Self;
141}
142
143///
144/// Converts this value to the signed version using the `as` cast operation.
145pub trait ToSigned {
146    type Output;
147    fn to_signed(self) -> Self::Output;
148    fn negative_one() -> Self::Output;
149}
150
151macro_rules! impl_to_signed {
152    ($src:ty, $dst:ty) => {
153        impl ToSigned for $src {
154            type Output = $dst;
155            fn to_signed(self) -> Self::Output {
156                self as $dst
157            }
158            fn negative_one() -> Self::Output {
159                -1 as $dst
160            }
161        }
162        impl ToSigned for $dst {
163            type Output = $dst;
164            fn to_signed(self) -> Self::Output {
165                self
166            }
167            fn negative_one() -> Self::Output {
168                -1 as $dst
169            }
170        }
171    };
172}
173impl_to_signed!(u8, i8);
174impl_to_signed!(u16, i16);
175impl_to_signed!(u32, i32);
176impl_to_signed!(u64, i64);
177impl_to_signed!(u128, i128);
178
179///
180/// Converts this value to the unsigned version using the `as` cast operation.
181pub trait ToUnsigned {
182    type Output;
183    fn to_unsigned(self) -> Self::Output;
184}
185
186macro_rules! impl_to_unsigned {
187    ($src:ty, $dst:ty) => {
188        impl ToUnsigned for $src {
189            type Output = $dst;
190            fn to_unsigned(self) -> Self::Output {
191                self as $dst
192            }
193        }
194        impl ToUnsigned for $dst {
195            type Output = $dst;
196            fn to_unsigned(self) -> Self::Output {
197                self
198            }
199        }
200    };
201}
202impl_to_unsigned!(i8, u8);
203impl_to_unsigned!(i16, u16);
204impl_to_unsigned!(i32, u32);
205impl_to_unsigned!(i64, u64);
206impl_to_unsigned!(i128, u128);
207
208pub trait ToU64 {
209    fn to_u64(&self) -> u64;
210}
211macro_rules! impl_to_u64 {
212    ($ty:ty) => {
213        impl ToU64 for $ty {
214            fn to_u64(&self) -> u64 {
215                *self as u64
216            }
217        }
218    };
219}
220impl_to_u64!(u8);
221impl_to_u64!(i8);
222impl_to_u64!(u16);
223impl_to_u64!(i16);
224impl_to_u64!(u32);
225impl_to_u64!(i32);
226impl_to_u64!(u64);
227impl_to_u64!(i64);
228impl_to_u64!(u128);
229impl_to_u64!(i128);
230impl_to_u64!(f32);
231impl_to_u64!(f64);
232impl_to_u64!(bool);
233impl_to_u64!(char);
234
235pub trait One {
236    const ONE: Self;
237}
238pub trait Zero {
239    const ZERO: Self;
240}
241
242macro_rules! impl_onezero_f {
243    ($typ:ty) => {
244        impl One for $typ {
245            const ONE: Self = 1.0;
246        }
247        impl Zero for $typ {
248            const ZERO: Self = 0.0;
249        }
250    };
251}
252impl_onezero_f!(f32);
253impl_onezero_f!(f64);
254
255macro_rules! impl_onezero_i {
256    ($typ:ty) => {
257        impl One for $typ {
258            const ONE: Self = 1;
259        }
260        impl Zero for $typ {
261            const ZERO: Self = 0;
262        }
263    };
264}
265impl_onezero_i!(u8);
266impl_onezero_i!(i8);
267impl_onezero_i!(u16);
268impl_onezero_i!(i16);
269impl_onezero_i!(u32);
270impl_onezero_i!(i32);
271impl_onezero_i!(u64);
272impl_onezero_i!(i64);
273impl_onezero_i!(u128);
274impl_onezero_i!(i128);
275
276pub trait PrimitiveMath:
277    Sized
278    + Add<Output = Self>
279    + Sub<Output = Self>
280    + Mul<Output = Self>
281    + Div<Output = Self>
282    + AddAssign
283    + SubAssign
284    + MulAssign
285    + DivAssign
286{
287}
288
289pub trait FloatIsh:
290    One
291    + Zero
292    + ToF64
293    + FromF64
294    + FromStr
295    + ToSigned
296    + FloatExt<Type = Self>
297    + Sized
298    + Copy
299    + Clone
300    + PartialEq
301    + PartialOrd
302    + Default
303    + PrimitiveMath
304    + Debug
305    + Display
306{
307}
308
309pub trait Cast<Output = Self> {
310    fn cast(self) -> Output;
311}
312macro_rules! impl_cast {
313    ($src:ty, $($dst:ty)*) => {
314        $(
315            impl Cast<$dst> for $src {
316
317                fn cast(self) -> $dst {
318                    self as $dst
319                }
320            }
321        )*
322    };
323}
324impl_cast!(u8 , u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
325impl_cast!(i8 , u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
326impl_cast!(u16, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
327impl_cast!(i16, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
328impl_cast!(u32, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
329impl_cast!(i32, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
330impl_cast!(u64, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
331impl_cast!(i64, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
332impl_cast!(u128, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
333impl_cast!(i128, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
334impl_cast!(f32, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);
335impl_cast!(f64, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64);