use std::{array::TryFromSliceError, convert::TryInto, u8};
pub trait FromBytes<const T: usize>: Sized {
fn from_le_bytes(bytes: [u8; T]) -> Self;
fn from_be_bytes(bytes: [u8; T]) -> Self;
}
pub trait TryFromBytes: Sized {
fn try_from_le_bytes(bytes: &[u8]) -> Result<Self, TryFromSliceError>;
fn try_from_be_bytes(bytes: &[u8]) -> Result<Self, TryFromSliceError>;
}
pub trait IntoBytes<const T: usize>: Sized {
fn into_le_bytes(self) -> [u8; T];
fn into_be_bytes(self) -> [u8; T];
}
macro_rules! impl_from_bytes {
($T: ty, $N:tt) => {
impl FromBytes<$N> for $T {
fn from_le_bytes(bytes: [u8; $N]) -> Self {
Self::from_le_bytes(bytes)
}
fn from_be_bytes(bytes: [u8; $N]) -> Self {
Self::from_be_bytes(bytes)
}
}
};
}
macro_rules! impl_try_from_bytes {
($T: ty) => {
impl TryFromBytes for $T {
fn try_from_le_bytes(bytes: &[u8]) -> Result<Self, TryFromSliceError> {
Ok(Self::from_le_bytes(bytes.try_into()?))
}
fn try_from_be_bytes(bytes: &[u8]) -> Result<Self, TryFromSliceError> {
Ok(Self::from_be_bytes(bytes.try_into()?))
}
}
};
}
macro_rules! impl_into_bytes {
($T: ty, $N:tt) => {
impl IntoBytes<$N> for $T {
fn into_le_bytes(self) -> [u8; $N] {
self.to_le_bytes()
}
fn into_be_bytes(self) -> [u8; $N] {
self.to_be_bytes()
}
}
};
}
impl_try_from_bytes!(i8);
impl_try_from_bytes!(i16);
impl_try_from_bytes!(i32);
impl_try_from_bytes!(i64);
impl_try_from_bytes!(u8);
impl_try_from_bytes!(u16);
impl_try_from_bytes!(u32);
impl_try_from_bytes!(u64);
impl_try_from_bytes!(f32);
impl_try_from_bytes!(f64);
impl_try_from_bytes!(isize);
impl_try_from_bytes!(usize);
impl_into_bytes!(i8, 1);
impl_into_bytes!(i16, 2);
impl_into_bytes!(i32, 4);
impl_into_bytes!(i64, 8);
impl_into_bytes!(u8, 1);
impl_into_bytes!(u16, 2);
impl_into_bytes!(u32, 4);
impl_into_bytes!(u64, 8);
impl_into_bytes!(f32, 4);
impl_into_bytes!(f64, 8);
#[cfg(target_pointer_width = "16")]
impl_into_bytes!(isize, 2);
#[cfg(target_pointer_width = "32")]
impl_into_bytes!(isize, 4);
#[cfg(target_pointer_width = "64")]
impl_into_bytes!(isize, 8);
#[cfg(target_pointer_width = "16")]
impl_into_bytes!(usize, 2);
#[cfg(target_pointer_width = "32")]
impl_into_bytes!(usize, 4);
#[cfg(target_pointer_width = "64")]
impl_into_bytes!(usize, 8);
impl_from_bytes!(i8, 1);
impl_from_bytes!(i16, 2);
impl_from_bytes!(i32, 4);
impl_from_bytes!(i64, 8);
impl_from_bytes!(u8, 1);
impl_from_bytes!(u16, 2);
impl_from_bytes!(u32, 4);
impl_from_bytes!(u64, 8);
impl_from_bytes!(f32, 4);
impl_from_bytes!(f64, 8);
#[cfg(target_pointer_width = "16")]
impl_from_bytes!(isize, 2);
#[cfg(target_pointer_width = "32")]
impl_from_bytes!(isize, 4);
#[cfg(target_pointer_width = "64")]
impl_from_bytes!(isize, 8);
#[cfg(target_pointer_width = "16")]
impl_from_bytes!(usize, 2);
#[cfg(target_pointer_width = "32")]
impl_from_bytes!(usize, 4);
#[cfg(target_pointer_width = "64")]
impl_from_bytes!(usize, 8);