use std::num::*;
use std::mem::{
MaybeUninit,
transmute_copy,
};
use bytemuck::Pod;
pub trait ByteRepr: Sized + Pod + Clone {
const BYTE_LEN: usize;
fn try_from_le_bytes(b: &[u8]) -> Option<Self> {
if b.len() >= Self::BYTE_LEN {
Some(<Self as ByteRepr>::from_le_bytes(b))
} else {
None
}
}
fn from_le_bytes(b: &[u8]) -> Self;
fn copy_to_le_bytes(self, dest: &mut [u8]);
fn into_le_bytes(self) -> Vec<u8>;
fn try_from_be_bytes(b: &[u8]) -> Option<Self> {
if b.len() >= Self::BYTE_LEN {
Some(<Self as ByteRepr>::from_be_bytes(b))
} else {
None
}
}
fn from_be_bytes(b: &[u8]) -> Self;
fn copy_to_be_bytes(self, dest: &mut [u8]);
fn into_be_bytes(self) -> Vec<u8>;
fn try_from_ne_bytes(b: &[u8]) -> Option<Self> {
if b.len() >= Self::BYTE_LEN {
Some(<Self as ByteRepr>::from_ne_bytes(b))
} else {
None
}
}
fn from_ne_bytes(b: &[u8]) -> Self {
if cfg!(endianness = "little") {
<Self as ByteRepr>::from_le_bytes(b)
} else {
<Self as ByteRepr>::from_be_bytes(b)
}
}
fn copy_to_ne_bytes(self, dest: &mut [u8]) {
if cfg!(endianness = "little") {
<Self as ByteRepr>::copy_to_le_bytes(self, dest)
} else {
<Self as ByteRepr>::copy_to_be_bytes(self, dest)
}
}
fn into_ne_bytes(self) -> Vec<u8> {
if cfg!(endianness = "little") {
<Self as ByteRepr>::into_le_bytes(self)
} else {
<Self as ByteRepr>::into_be_bytes(self)
}
}
}
pub trait ByteReprNum: ByteRepr {}
macro_rules! gen_byterepr_impls_nums {
($($T:ty)+) => {
$(
impl ByteRepr for $T {
const BYTE_LEN: usize = std::mem::size_of::<$T>();
#[inline]
fn from_le_bytes(b: &[u8]) -> Self {
assert!(b.len() >= Self::BYTE_LEN);
let mut boilerplate: [u8; Self::BYTE_LEN] = [0; Self::BYTE_LEN];
boilerplate.copy_from_slice(&b[0..Self::BYTE_LEN]);
Self::from_le_bytes(boilerplate)
}
#[inline]
fn from_be_bytes(b: &[u8]) -> Self {
let mut boilerplate: [u8; Self::BYTE_LEN] = [0; Self::BYTE_LEN];
boilerplate.copy_from_slice(&b[0..Self::BYTE_LEN]);
Self::from_be_bytes(boilerplate)
}
#[inline]
fn copy_to_le_bytes(self, dest: &mut [u8]) {
let bytes = self.to_le_bytes();
dest[..Self::BYTE_LEN].copy_from_slice(&bytes[0..Self::BYTE_LEN]);
}
#[inline]
fn copy_to_be_bytes(self, dest: &mut [u8]) {
let bytes = self.to_be_bytes();
dest[..Self::BYTE_LEN].copy_from_slice(&bytes[0..Self::BYTE_LEN]);
}
fn into_be_bytes(self) -> Vec<u8> {
self.to_be_bytes().to_vec()
}
fn into_le_bytes(self) -> Vec<u8> {
self.to_le_bytes().to_vec()
}
}
impl ByteReprNum for $T {}
)+
}
}
gen_byterepr_impls_nums!(u8 i8 u16 i16 u32 i32 f32 u64 i64 f64 u128 i128);
macro_rules! gen_byterepr_impls_nonzero_nums {
($($T:ty, $J:ty)+) => {
$(
impl ByteRepr for Option<$T> {
const BYTE_LEN: usize = std::mem::size_of::<Option<$T>>();
#[inline]
fn from_le_bytes(b: &[u8]) -> Self {
let val = <$J as ByteRepr>::from_le_bytes(b);
<$T>::new(val)
}
#[inline]
fn from_be_bytes(b: &[u8]) -> Self {
let val = <$J as ByteRepr>::from_be_bytes(b);
<$T>::new(val)
}
#[inline]
fn copy_to_le_bytes(self, dest: &mut [u8]) {
match self {
Some(v) => <$J as ByteRepr>::copy_to_le_bytes(v.get(), dest),
None => <$J as ByteRepr>::copy_to_le_bytes(0, dest),
}
}
#[inline]
fn copy_to_be_bytes(self, dest: &mut [u8]) {
match self {
Some(v) => <$J as ByteRepr>::copy_to_be_bytes(v.get(), dest),
None => <$J as ByteRepr>::copy_to_be_bytes(0, dest),
}
}
fn into_be_bytes(self) -> Vec<u8> {
let val = match self {
Some(v) => v.get(),
None => 0 as $J,
};
val.to_be_bytes().to_vec()
}
fn into_le_bytes(self) -> Vec<u8> {
let val = match self {
Some(v) => v.get(),
None => 0 as $J,
};
val.to_le_bytes().to_vec()
}
}
)+
}
}
gen_byterepr_impls_nonzero_nums!(NonZeroI8, i8 NonZeroU8, u8 NonZeroI16, i16 NonZeroU16, u16);
impl<T: ByteRepr> ByteRepr for Wrapping<T> {
const BYTE_LEN: usize = T::BYTE_LEN;
fn from_le_bytes(b: &[u8]) -> Self {
Wrapping(<T as ByteRepr>::from_le_bytes(b))
}
fn from_be_bytes(b: &[u8]) -> Self {
Wrapping(<T as ByteRepr>::from_be_bytes(b))
}
fn copy_to_le_bytes(self, dest: &mut [u8]) {
self.0.copy_to_le_bytes(dest);
}
fn copy_to_be_bytes(self, dest: &mut [u8]) {
self.0.copy_to_be_bytes(dest);
}
fn into_be_bytes(self) -> Vec<u8> {
self.0.into_be_bytes()
}
fn into_le_bytes(self) -> Vec<u8> {
self.0.into_le_bytes()
}
}
macro_rules! gen_byterepr_impls_array {
($($arrlen:literal)+) => {
$(
impl<T: ByteRepr + Copy> ByteRepr for [T; $arrlen] {
const BYTE_LEN: usize = T::BYTE_LEN * $arrlen;
fn from_le_bytes(b: &[u8]) -> Self {
assert!(b.len() >= Self::BYTE_LEN);
let mut out: [MaybeUninit<T>; $arrlen] = unsafe {
MaybeUninit::uninit().assume_init()
};
if cfg!(endianness = "little") {
let bptr: *const u8 = b.as_ptr();
let optr: *mut [MaybeUninit<T>; $arrlen] = &mut out;
unsafe {
bptr.copy_to(optr as *mut u8, Self::BYTE_LEN);
}
} else {
for i in 0..(out.len()) {
let val_start = T::BYTE_LEN * i;
let val_end = val_start + T::BYTE_LEN;
out[i] = MaybeUninit::new(T::from_le_bytes(&b[val_start..val_end]));
}
}
unsafe { transmute_copy::<_, [T; $arrlen]>(&out) }
}
fn from_be_bytes(b: &[u8]) -> Self {
assert!(b.len() >= Self::BYTE_LEN);
let mut out: [MaybeUninit<T>; $arrlen] = unsafe {
MaybeUninit::uninit().assume_init()
};
if cfg!(endianness = "big") {
let bptr: *const u8 = b.as_ptr();
let optr: *mut [MaybeUninit<T>; $arrlen] = &mut out;
unsafe {
bptr.copy_to(optr as *mut u8, Self::BYTE_LEN);
}
} else {
for i in 0..(out.len()) {
let val_start = T::BYTE_LEN * i;
let val_end = val_start + T::BYTE_LEN;
out[i] = MaybeUninit::new(T::from_be_bytes(&b[val_start..val_end]));
}
}
unsafe { transmute_copy::<_, [T; $arrlen]>(&out) }
}
fn copy_to_le_bytes(self, dest: &mut [u8]) {
assert!(dest.len() >= Self::BYTE_LEN);
for i in 0..$arrlen {
let val_start = T::BYTE_LEN * i;
let val_end = val_start + T::BYTE_LEN;
self[i].copy_to_le_bytes(&mut dest[val_start..val_end]);
}
}
fn copy_to_be_bytes(self, dest: &mut [u8]) {
assert!(dest.len() >= Self::BYTE_LEN);
for i in 0..$arrlen {
let val_start = T::BYTE_LEN * i;
let val_end = val_start + T::BYTE_LEN;
self[i].copy_to_be_bytes(&mut dest[val_start..val_end]);
}
}
fn into_be_bytes(self) -> Vec<u8> {
let mut out_vec = vec![Default::default(); Self::BYTE_LEN];
self.copy_to_be_bytes(&mut out_vec);
out_vec
}
fn into_le_bytes(self) -> Vec<u8> {
let mut out_vec = vec![Default::default(); Self::BYTE_LEN];
self.copy_to_le_bytes(&mut out_vec);
out_vec
}
}
)+
};
}
#[allow(unused_variables)]
gen_byterepr_impls_array!(
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 48 64 96 128 256 512 1024 2048 4096
);