use crate::static_assert::static_check_layout;
#[derive(Clone, Copy, core::fmt::Debug, PartialEq, Eq)]
pub struct ReprError;
pub unsafe trait HasRepr: Sized {
type Raw: Clone + Copy + core::fmt::Debug;
fn raw_is_valid(value: &Self::Raw) -> Result<(), ReprError>;
fn try_from_raw(value: Self::Raw) -> Result<Self, ReprError> {
static_check_layout::<Self, Self::Raw>();
Self::raw_is_valid(&value)?;
Ok(unsafe { core::mem::transmute_copy(&value) })
}
fn try_from_repr(value: Repr<Self>) -> Result<Self, ReprError> {
Self::try_from_raw(value.0)
}
fn try_from_ref(value: &Repr<Self>) -> Result<&Self, ReprError> {
static_check_layout::<Self, Self::Raw>();
Self::raw_is_valid(&value.0)?;
Ok(unsafe { &*(value as *const Repr<Self> as *const Self) })
}
fn try_from_mut(value: &mut Repr<Self>) -> Result<&mut Self, ReprError> {
static_check_layout::<Self, Self::Raw>();
Self::raw_is_valid(&value.0)?;
Ok(unsafe { &mut *(value as *mut Repr<Self> as *mut Self) })
}
fn into_repr(self) -> Repr<Self> {
static_check_layout::<Self, Self::Raw>();
unsafe { core::mem::transmute_copy(&self) }
}
}
pub trait RawTryInto<T: HasRepr> {
fn raw_try_into(self) -> Result<T, ReprError>;
}
impl<T: HasRepr> RawTryInto<T> for T::Raw {
fn raw_try_into(self) -> Result<T, ReprError> {
T::try_from_raw(self)
}
}
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct Repr<T: HasRepr>(T::Raw);
impl<T: HasRepr> Repr<T> {
pub fn repr_try_into(self) -> Result<T, ReprError> {
T::try_from_repr(self)
}
pub fn ref_try_into(&self) -> Result<&T, ReprError> {
T::try_from_ref(self)
}
pub fn from_raw(v: T::Raw) -> Self {
Self(v)
}
}