num_primitive/
number.rs

1use crate::PrimitiveError;
2
3trait Sealed {}
4
5/// Trait for all primitive [numeric types].
6///
7/// This encapsulates trait implementations and inherent methods that are common among all of the
8/// primitive numeric types: [`f32`], [`f64`], [`i8`], [`i16`], [`i32`], [`i64`], [`i128`],
9/// [`isize`], [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], and [`usize`]. Unstable types like
10/// [`f16`] and [`f128`] will be added once they are stabilized.
11///
12/// See the corresponding items on the individual types for more documentation and examples.
13///
14/// This trait is sealed with a private trait to prevent downstream implementations, so we may
15/// continue to expand along with the standard library without worrying about breaking changes for
16/// implementors.
17///
18/// [numeric types]: https://doc.rust-lang.org/reference/types/numeric.html
19///
20/// # Examples
21///
22/// ```
23/// use num_primitive::{PrimitiveNumber, PrimitiveNumberRef};
24///
25/// fn dot_product<T: PrimitiveNumber>(a: &[T], b: &[T]) -> T {
26///     assert_eq!(a.len(), b.len());
27///     // Note that we have to dereference to use `T: Mul<&T>`
28///     core::iter::zip(a, b).map(|(a, b)| (*a) * b).sum()
29/// }
30///
31/// fn dot_product_ref<T>(a: &[T], b: &[T]) -> T
32/// where
33///     T: PrimitiveNumber,
34///     for<'a> &'a T: PrimitiveNumberRef<T>,
35/// {
36///     assert_eq!(a.len(), b.len());
37///     // In this case we can use `&T: Mul`
38///     core::iter::zip(a, b).map(|(a, b)| a * b).sum()
39/// }
40///
41/// assert_eq!(dot_product::<i32>(&[1, 3, -5], &[4, -2, -1]), 3);
42/// assert_eq!(dot_product_ref::<f64>(&[1., 3., -5.], &[4., -2., -1.]), 3.);
43/// ```
44#[expect(private_bounds)]
45pub trait PrimitiveNumber:
46    'static
47    + Sealed
48    + core::cmp::PartialEq
49    + core::cmp::PartialOrd
50    + core::convert::From<bool>
51    + core::default::Default
52    + core::fmt::Debug
53    + core::fmt::Display
54    + core::fmt::LowerExp
55    + core::fmt::UpperExp
56    + core::iter::Product<Self>
57    + core::iter::Sum<Self>
58    + core::marker::Copy
59    + core::marker::Send
60    + core::marker::Sync
61    + core::marker::Unpin
62    + core::ops::Add<Self, Output = Self>
63    + core::ops::AddAssign<Self>
64    + core::ops::Div<Self, Output = Self>
65    + core::ops::DivAssign<Self>
66    + core::ops::Mul<Self, Output = Self>
67    + core::ops::MulAssign<Self>
68    + core::ops::Rem<Self, Output = Self>
69    + core::ops::RemAssign<Self>
70    + core::ops::Sub<Self, Output = Self>
71    + core::ops::SubAssign<Self>
72    + core::panic::RefUnwindSafe
73    + core::panic::UnwindSafe
74    + core::str::FromStr<Err: PrimitiveError>
75    + for<'a> core::iter::Product<&'a Self>
76    + for<'a> core::iter::Sum<&'a Self>
77    + for<'a> core::ops::Add<&'a Self, Output = Self>
78    + for<'a> core::ops::AddAssign<&'a Self>
79    + for<'a> core::ops::Div<&'a Self, Output = Self>
80    + for<'a> core::ops::DivAssign<&'a Self>
81    + for<'a> core::ops::Mul<&'a Self, Output = Self>
82    + for<'a> core::ops::MulAssign<&'a Self>
83    + for<'a> core::ops::Rem<&'a Self, Output = Self>
84    + for<'a> core::ops::RemAssign<&'a Self>
85    + for<'a> core::ops::Sub<&'a Self, Output = Self>
86    + for<'a> core::ops::SubAssign<&'a Self>
87{
88    /// An array of bytes used by methods like [`from_be_bytes`][Self::from_be_bytes] and
89    /// [`to_be_bytes`][Self::to_be_bytes]. It is effectively `[u8; size_of::<Self>()]`.
90    type Bytes: core::borrow::Borrow<[u8]> + core::borrow::BorrowMut<[u8]>;
91
92    /// Creates a value from its representation as a byte array in big endian.
93    fn from_be_bytes(bytes: Self::Bytes) -> Self;
94
95    /// Creates a value from its representation as a byte array in little endian.
96    fn from_le_bytes(bytes: Self::Bytes) -> Self;
97
98    /// Creates a value from its representation as a byte array in native endian.
99    fn from_ne_bytes(bytes: Self::Bytes) -> Self;
100
101    /// Returns the memory representation of this number as a byte array in little-endian order.
102    fn to_be_bytes(self) -> Self::Bytes;
103
104    /// Returns the memory representation of this number as a byte array in big-endian order.
105    fn to_le_bytes(self) -> Self::Bytes;
106
107    /// Returns the memory representation of this number as a byte array in native-endian order.
108    fn to_ne_bytes(self) -> Self::Bytes;
109}
110
111/// Trait for references to primitive numbers ([`PrimitiveNumber`]).
112///
113/// This enables traits like the standard operators in generic code,
114/// e.g. `where &T: PrimitiveNumberRef<T>`.
115#[expect(private_bounds)]
116pub trait PrimitiveNumberRef<T>:
117    Sealed
118    + core::borrow::Borrow<T>
119    + core::cmp::PartialEq
120    + core::cmp::PartialOrd
121    + core::fmt::Debug
122    + core::fmt::Display
123    + core::fmt::LowerExp
124    + core::fmt::UpperExp
125    + core::marker::Copy
126    + core::marker::Send
127    + core::marker::Sync
128    + core::marker::Unpin
129    + core::ops::Add<T, Output = T>
130    + core::ops::Deref<Target = T>
131    + core::ops::Div<T, Output = T>
132    + core::ops::Mul<T, Output = T>
133    + core::ops::Rem<T, Output = T>
134    + core::ops::Sub<T, Output = T>
135    + core::panic::RefUnwindSafe
136    + core::panic::UnwindSafe
137    + for<'a> core::ops::Add<&'a T, Output = T>
138    + for<'a> core::ops::Div<&'a T, Output = T>
139    + for<'a> core::ops::Mul<&'a T, Output = T>
140    + for<'a> core::ops::Rem<&'a T, Output = T>
141    + for<'a> core::ops::Sub<&'a T, Output = T>
142{
143}
144
145macro_rules! impl_primitive {
146    ($($Number:ident),*) => {$(
147        impl Sealed for $Number {}
148        impl Sealed for &$Number {}
149
150        impl PrimitiveNumber for $Number {
151            type Bytes = [u8; size_of::<Self>()];
152
153            forward! {
154                fn from_be_bytes(bytes: Self::Bytes) -> Self;
155                fn from_le_bytes(bytes: Self::Bytes) -> Self;
156                fn from_ne_bytes(bytes: Self::Bytes) -> Self;
157            }
158            forward! {
159                fn to_be_bytes(self) -> Self::Bytes;
160                fn to_le_bytes(self) -> Self::Bytes;
161                fn to_ne_bytes(self) -> Self::Bytes;
162            }
163        }
164
165        impl PrimitiveNumberRef<$Number> for &$Number {}
166    )*}
167}
168
169impl_primitive!(f32, f64);
170impl_primitive!(i8, i16, i32, i64, i128, isize);
171impl_primitive!(u8, u16, u32, u64, u128, usize);