use std::borrow::{Borrow, BorrowMut};
use crate::{BigEndian, LittleEndian};
pub trait Sealed {}
pub trait ByteArray: Sealed + Default + Borrow<[u8]> + BorrowMut<[u8]> + Copy {}
pub trait Endianness: Sealed {
fn from_representable<R: Representable>(representable: &R) -> R::Representation;
fn to_representable<R: Representable>(representation: &R::Representation) -> R;
}
pub trait Representable {
type Representation: ByteArray;
fn from_le_bytes(bytes: &Self::Representation) -> Self;
fn from_be_bytes(bytes: &Self::Representation) -> Self;
fn to_le_bytes(&self) -> Self::Representation;
fn to_be_bytes(&self) -> Self::Representation;
}
impl<const N: usize> Sealed for [u8; N] {}
impl<const N: usize> ByteArray for [u8; N] where [u8; N]: Default + Borrow<[u8]> + BorrowMut<[u8]> {}
impl Sealed for BigEndian {}
impl Endianness for BigEndian {
fn from_representable<R: Representable>(representable: &R) -> R::Representation {
representable.to_be_bytes()
}
fn to_representable<R: Representable>(representation: &R::Representation) -> R {
R::from_be_bytes(representation)
}
}
impl Sealed for LittleEndian {}
impl Endianness for LittleEndian {
fn from_representable<R: Representable>(representable: &R) -> R::Representation {
representable.to_le_bytes()
}
fn to_representable<R: Representable>(representation: &R::Representation) -> R {
R::from_le_bytes(representation)
}
}
macro_rules! impl_representable {
($($num:ty),* $(,)?) => {
$(impl Representable for $num {
type Representation = [u8; std::mem::size_of::<$num>()];
fn from_le_bytes(bytes: &Self::Representation) -> Self {
Self::from_le_bytes(*bytes)
}
fn from_be_bytes(bytes: &Self::Representation) -> Self {
Self::from_be_bytes(*bytes)
}
fn to_le_bytes(&self) -> Self::Representation {
Self::to_le_bytes(*self)
}
fn to_be_bytes(&self) -> Self::Representation {
Self::to_be_bytes(*self)
}
})*
}
}
impl_representable!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);