use std::{any, mem, slice};
#[derive(Debug, Clone, Copy, Default)]
pub struct Empty;
pub unsafe trait Packed {}
pub trait AsBytes {
fn as_bytes(&self) -> &[u8];
}
impl AsBytes for () {
fn as_bytes(&self) -> &[u8] {
&[]
}
}
impl AsBytes for Empty {
fn as_bytes(&self) -> &[u8] {
&[]
}
}
impl<T> AsBytes for &[T] {
fn as_bytes(&self) -> &[u8] {
let (head, aligned, tail) = unsafe { self.align_to::<u8>() };
assert!(head.is_empty());
assert!(tail.is_empty());
aligned
}
}
impl<T> AsBytes for T
where
T: Packed,
{
fn as_bytes(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>()) }
}
}
pub trait AsBytesMut {
fn as_bytes_mut(&mut self) -> &mut [u8];
}
impl<T> AsBytesMut for &mut [T] {
fn as_bytes_mut(&mut self) -> &mut [u8] {
let (head, aligned, tail) = unsafe { self.align_to_mut::<u8>() };
assert!(head.is_empty());
assert!(tail.is_empty());
aligned
}
}
pub fn align_to<T>(bytes: &[u8]) -> &[T] {
if bytes.len() % mem::size_of::<T>() != 0 {
panic!(
"{}::align_to: byte slice length {} is not a multiple of the size of a {}",
module_path!(),
bytes.len(),
any::type_name::<T>()
);
}
let ptr = bytes.as_ptr() as *const T;
let len = bytes.len() / mem::size_of::<T>();
unsafe { slice::from_raw_parts(ptr, len) }
}