use crate::{PrimitiveBytes, PrimitiveError};
trait Sealed {}
struct SealedToken;
#[expect(private_bounds)]
pub trait PrimitiveNumber:
'static
+ Sealed
+ PrimitiveNumberAs<f32>
+ PrimitiveNumberAs<f64>
+ PrimitiveNumberAs<i8>
+ PrimitiveNumberAs<i16>
+ PrimitiveNumberAs<i32>
+ PrimitiveNumberAs<i64>
+ PrimitiveNumberAs<i128>
+ PrimitiveNumberAs<isize>
+ PrimitiveNumberAs<u8>
+ PrimitiveNumberAs<u16>
+ PrimitiveNumberAs<u32>
+ PrimitiveNumberAs<u64>
+ PrimitiveNumberAs<u128>
+ PrimitiveNumberAs<usize>
+ core::cmp::PartialEq
+ core::cmp::PartialOrd
+ core::convert::From<bool>
+ core::default::Default
+ core::fmt::Debug
+ core::fmt::Display
+ core::fmt::LowerExp
+ core::fmt::UpperExp
+ core::iter::Product<Self>
+ core::iter::Sum<Self>
+ core::marker::Copy
+ core::marker::Send
+ core::marker::Sync
+ core::marker::Unpin
+ core::ops::Add<Self, Output = Self>
+ core::ops::AddAssign<Self>
+ core::ops::Div<Self, Output = Self>
+ core::ops::DivAssign<Self>
+ core::ops::Mul<Self, Output = Self>
+ core::ops::MulAssign<Self>
+ core::ops::Rem<Self, Output = Self>
+ core::ops::RemAssign<Self>
+ core::ops::Sub<Self, Output = Self>
+ core::ops::SubAssign<Self>
+ core::panic::RefUnwindSafe
+ core::panic::UnwindSafe
+ core::str::FromStr<Err: PrimitiveError>
+ for<'a> core::iter::Product<&'a Self>
+ for<'a> core::iter::Sum<&'a Self>
+ for<'a> core::ops::Add<&'a Self, Output = Self>
+ for<'a> core::ops::AddAssign<&'a Self>
+ for<'a> core::ops::Div<&'a Self, Output = Self>
+ for<'a> core::ops::DivAssign<&'a Self>
+ for<'a> core::ops::Mul<&'a Self, Output = Self>
+ for<'a> core::ops::MulAssign<&'a Self>
+ for<'a> core::ops::Rem<&'a Self, Output = Self>
+ for<'a> core::ops::RemAssign<&'a Self>
+ for<'a> core::ops::Sub<&'a Self, Output = Self>
+ for<'a> core::ops::SubAssign<&'a Self>
{
type Bytes: PrimitiveBytes;
fn from_be_bytes(bytes: Self::Bytes) -> Self;
fn from_le_bytes(bytes: Self::Bytes) -> Self;
fn from_ne_bytes(bytes: Self::Bytes) -> Self;
fn midpoint(self, other: Self) -> Self;
fn to_be_bytes(self) -> Self::Bytes;
fn to_le_bytes(self) -> Self::Bytes;
fn to_ne_bytes(self) -> Self::Bytes;
fn as_from<T>(value: T) -> Self
where
Self: PrimitiveNumberAs<T>,
{
<Self as PrimitiveNumberAs<T>>::__as_from(value, SealedToken)
}
fn as_to<T>(self) -> T
where
Self: PrimitiveNumberAs<T>,
{
<Self as PrimitiveNumberAs<T>>::__as_to(self, SealedToken)
}
}
#[expect(private_bounds)]
pub trait PrimitiveNumberRef<T>:
Sealed
+ core::borrow::Borrow<T>
+ core::cmp::PartialEq
+ core::cmp::PartialOrd
+ core::fmt::Debug
+ core::fmt::Display
+ core::fmt::LowerExp
+ core::fmt::UpperExp
+ core::marker::Copy
+ core::marker::Send
+ core::marker::Sync
+ core::marker::Unpin
+ core::ops::Add<T, Output = T>
+ core::ops::Deref<Target = T>
+ core::ops::Div<T, Output = T>
+ core::ops::Mul<T, Output = T>
+ core::ops::Rem<T, Output = T>
+ core::ops::Sub<T, Output = T>
+ core::panic::RefUnwindSafe
+ core::panic::UnwindSafe
+ for<'a> core::ops::Add<&'a T, Output = T>
+ for<'a> core::ops::Div<&'a T, Output = T>
+ for<'a> core::ops::Mul<&'a T, Output = T>
+ for<'a> core::ops::Rem<&'a T, Output = T>
+ for<'a> core::ops::Sub<&'a T, Output = T>
{
}
pub trait PrimitiveNumberAs<T> {
#[doc(hidden)]
#[expect(private_interfaces)]
fn __as_from(x: T, _: SealedToken) -> Self;
#[doc(hidden)]
#[expect(private_interfaces)]
fn __as_to(x: Self, _: SealedToken) -> T;
}
macro_rules! impl_primitive {
($($Number:ident),+) => {$(
impl Sealed for $Number {}
impl Sealed for &$Number {}
impl PrimitiveNumber for $Number {
type Bytes = [u8; size_of::<Self>()];
forward! {
fn from_be_bytes(bytes: Self::Bytes) -> Self;
fn from_le_bytes(bytes: Self::Bytes) -> Self;
fn from_ne_bytes(bytes: Self::Bytes) -> Self;
}
forward! {
fn midpoint(self, other: Self) -> Self;
fn to_be_bytes(self) -> Self::Bytes;
fn to_le_bytes(self) -> Self::Bytes;
fn to_ne_bytes(self) -> Self::Bytes;
}
}
impl PrimitiveNumberRef<$Number> for &$Number {}
impl_primitive!($Number as f32, f64);
impl_primitive!($Number as i8, i16, i32, i64, i128, isize);
impl_primitive!($Number as u8, u16, u32, u64, u128, usize);
)+};
($Number:ident as $($Other:ident),+) => {$(
impl PrimitiveNumberAs<$Other> for $Number {
#[inline]
#[expect(private_interfaces)]
fn __as_from(x: $Other, _: SealedToken) -> Self {
x as Self
}
#[inline]
#[expect(private_interfaces)]
fn __as_to(x: Self, _: SealedToken) -> $Other {
x as $Other
}
}
)+}
}
impl_primitive!(f32, f64);
impl_primitive!(i8, i16, i32, i64, i128, isize);
impl_primitive!(u8, u16, u32, u64, u128, usize);