use core::{mem, ptr, marker};
use crate::read::Out;
const unsafe fn transmute_slice<IN, OUT>(val: &IN) -> &[OUT] {
&*ptr::slice_from_raw_parts(val as *const IN as *const OUT, mem::size_of::<IN>())
}
unsafe fn transmute_slice_mut<IN, OUT>(val: &mut IN) -> &mut [OUT] {
&mut *ptr::slice_from_raw_parts_mut(val as *mut IN as *mut OUT, mem::size_of::<IN>())
}
const unsafe fn transmute_ref<IN, OUT: Copy>(val: &IN) -> OUT {
*(mem::transmute::<&IN, &mem::MaybeUninit<OUT>>(val).assume_init_ref())
}
pub unsafe trait Pod: Copy {
}
macro_rules! impl_pod {
($($ty:ident),*) => {$(
unsafe impl Pod for $ty {
}
)*};
}
impl_pod!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
unsafe impl<T: Pod> Pod for mem::ManuallyDrop<T> {
}
struct Validator<IN, OUT> {
_result: marker::PhantomData<(IN, OUT)>,
}
impl<IN, OUT: Copy> Validator<IN, OUT> {
const IS_NOT_ZST: () = {
assert!(mem::size_of::<IN>() > 0);
assert!(mem::size_of::<OUT>() > 0);
};
const IS_SAME_SIZE: () = {
assert!(mem::size_of::<IN>() == mem::size_of::<OUT>());
};
const IS_ENOUGH_BYTES: () = {
assert!(mem::size_of::<IN>() >= mem::size_of::<OUT>());
};
}
#[inline]
pub const fn uninit_byte_slice_from<T>(val: &T) -> &[mem::MaybeUninit<u8>] {
let _ = Validator::<T, &[u8]>::IS_NOT_ZST;
unsafe {
transmute_slice(val)
}
}
#[inline]
pub unsafe fn uninit_byte_slice_mut_from<T>(val: &mut T) -> &mut [mem::MaybeUninit<u8>] {
let _ = Validator::<T, &[u8]>::IS_NOT_ZST;
unsafe {
transmute_slice_mut(val)
}
}
#[inline]
pub const fn byte_slice_from<T: Pod>(val: &T) -> &[u8] {
let _ = Validator::<T, &[u8]>::IS_NOT_ZST;
unsafe {
transmute_slice(val)
}
}
#[inline]
pub fn byte_slice_mut_from<T: Pod>(val: &mut T) -> &mut [u8] {
let _ = Validator::<T, &[u8]>::IS_NOT_ZST;
unsafe {
transmute_slice_mut(val)
}
}
#[inline]
pub const fn to_bytes<T: Pod, const N: usize>(val: &T) -> [u8; N] {
let _ = Validator::<T, [u8; N]>::IS_ENOUGH_BYTES;
unsafe {
transmute_ref(val)
}
}
#[inline]
pub const fn from_bytes<T: Pod, const N: usize>(val: &[u8; N]) -> T {
let _ = Validator::<[u8; N], T>::IS_SAME_SIZE;
unsafe {
(*(val.as_ptr() as *const Out<T>)).0
}
}