use core::{mem, slice};
pub unsafe trait Pod {
fn as_bytes(&self) -> &[u8] {
unsafe {
let len = mem::size_of_val(self);
slice::from_raw_parts(self as *const Self as *const u8, len)
}
}
fn ref_from_bytes(bytes: &[u8]) -> Option<&Self>
where
Self: Sized,
{
if bytes.len() != mem::size_of::<Self>()
|| !crate::utils::is_aligned_to(bytes, mem::align_of::<Self>())
{
return None;
}
Some(unsafe { &*(bytes.as_ptr() as *const Self) })
}
fn ref_from_prefix(bytes: &[u8]) -> Option<(&Self, &[u8])>
where
Self: Sized,
{
if bytes.len() < mem::size_of::<Self>()
|| !crate::utils::is_aligned_to(bytes, mem::align_of::<Self>())
{
return None;
}
let (bytes, suffix) = bytes.split_at(mem::size_of::<Self>());
Some((unsafe { &*(bytes.as_ptr() as *const Self) }, suffix))
}
fn slice_from_bytes(bytes: &[u8]) -> Option<&[Self]>
where
Self: Sized,
{
assert_ne!(mem::size_of::<Self>(), 0);
let len = bytes.len();
let elem_size = mem::size_of::<Self>();
if len % elem_size != 0 || !crate::utils::is_aligned_to(bytes, mem::align_of::<Self>()) {
return None;
}
let elems = len / elem_size;
Some(unsafe { slice::from_raw_parts(bytes.as_ptr() as *const Self, elems) })
}
fn slice_from_prefix(bytes: &[u8], elems: usize) -> Option<(&[Self], &[u8])>
where
Self: Sized,
{
assert_ne!(mem::size_of::<Self>(), 0);
let elem_size = mem::size_of::<Self>();
let expected_len = elem_size.checked_mul(elems)?;
if bytes.len() < expected_len
|| !crate::utils::is_aligned_to(bytes, mem::align_of::<Self>())
{
return None;
}
let (bytes, suffix) = bytes.split_at(expected_len);
Some((
unsafe { slice::from_raw_parts(bytes.as_ptr() as *const Self, elems) },
suffix,
))
}
}
unsafe impl<T: Pod> Pod for [T] {}
unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
macro_rules! impl_for_types {
($trait:ident, $type:ty) => (
unsafe impl $trait for $type {}
);
($trait:ident, $type:ty, $($types:ty),*) => (
unsafe impl $trait for $type {}
impl_for_types!($trait, $($types),*);
);
}
impl_for_types!(Pod, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64);