use crate::{emplacer::Emplacer, error::Error, utils::mem::check_align_and_min_size};
use core::{
mem::{align_of, size_of},
ptr,
};
pub unsafe trait FlatBase: Send + Sync {
const ALIGN: usize;
const MIN_SIZE: usize;
fn size(&self) -> usize;
}
pub unsafe trait FlatUnsized: FlatBase {
type AlignAs: Sized + Send + Sync;
unsafe fn ptr_from_bytes(bytes: *mut [u8]) -> *mut Self;
unsafe fn ptr_to_bytes(this: *mut Self) -> *mut [u8];
unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
&*Self::ptr_from_bytes(bytes as *const _ as *mut _)
}
unsafe fn from_mut_bytes_unchecked(bytes: &mut [u8]) -> &mut Self {
&mut *Self::ptr_from_bytes(bytes)
}
fn as_bytes(&self) -> &[u8] {
unsafe { &*Self::ptr_to_bytes(self as *const _ as *mut _) }
}
unsafe fn as_mut_bytes(&mut self) -> &mut [u8] {
unsafe { &mut *Self::ptr_to_bytes(self as *mut _) }
}
fn new_in_place<I: Emplacer<Self>>(bytes: &mut [u8], emplacer: I) -> Result<&mut Self, Error> {
emplacer.emplace(bytes)?;
Ok(unsafe { Self::from_mut_bytes_unchecked(bytes) })
}
fn assign_in_place<I: Emplacer<Self>>(&mut self, emplacer: I) -> Result<&mut Self, Error> {
unsafe {
let bytes = self.as_mut_bytes();
emplacer.emplace_unchecked(bytes)?;
Ok(Self::from_mut_bytes_unchecked(bytes))
}
}
}
pub unsafe trait FlatValidate: FlatUnsized {
unsafe fn validate_unchecked(bytes: &[u8]) -> Result<(), Error>;
unsafe fn validate_ptr(this: *const Self) -> Result<(), Error> {
unsafe { Self::validate_unchecked(&*Self::ptr_to_bytes(this as *mut _)) }
}
fn validate(bytes: &[u8]) -> Result<(), Error> {
check_align_and_min_size::<Self>(bytes)?;
unsafe { Self::validate_unchecked(bytes) }
}
fn from_bytes(bytes: &[u8]) -> Result<&Self, Error> {
Self::validate(bytes)?;
Ok(unsafe { Self::from_bytes_unchecked(bytes) })
}
fn from_mut_bytes(bytes: &mut [u8]) -> Result<&mut Self, Error> {
Self::validate(bytes)?;
Ok(unsafe { Self::from_mut_bytes_unchecked(bytes) })
}
}
pub unsafe trait Flat: FlatBase + FlatUnsized + FlatValidate {}
pub unsafe trait FlatSized: FlatUnsized + Sized {
const SIZE: usize = size_of::<Self>();
}
unsafe impl<T: Flat> FlatSized for T {}
unsafe impl<T: FlatSized> FlatBase for T {
const ALIGN: usize = align_of::<Self>();
const MIN_SIZE: usize = Self::SIZE;
fn size(&self) -> usize {
Self::SIZE
}
}
unsafe impl<T: FlatSized> FlatUnsized for T {
type AlignAs = T;
unsafe fn ptr_from_bytes(bytes: *mut [u8]) -> *mut Self {
bytes as *mut Self
}
unsafe fn ptr_to_bytes(this: *mut Self) -> *mut [u8] {
ptr::slice_from_raw_parts_mut(this as *mut u8, Self::SIZE)
}
}
pub trait FlatDefault: Flat {
type DefaultEmplacer: Emplacer<Self>;
fn default_emplacer() -> Self::DefaultEmplacer;
fn default_in_place(bytes: &mut [u8]) -> Result<&mut Self, Error> {
Self::new_in_place(bytes, Self::default_emplacer())
}
}
impl<T: Flat + Default> FlatDefault for T {
type DefaultEmplacer = Self;
fn default_emplacer() -> Self::DefaultEmplacer {
Self::default()
}
}