mod test;
use crate::{FromOcts, Immutable, Init, IntoOcts};
use core::mem::ManuallyDrop;
use core::ptr;
#[inline]
#[must_use]
#[track_caller]
pub const fn transmute<T, U>(value: T) -> U
where
T: IntoOcts + Init,
U: FromOcts,
{
const {
assert!(
size_of::<U>() == size_of::<T>(),
"cannot transmute types of different sizes",
);
}
unsafe { transmute_unchecked(value) }
}
#[inline]
#[must_use]
#[track_caller]
pub const fn transmute_ref<T, U>(r: &T) -> &U
where
T: IntoOcts + Init + Immutable,
U: FromOcts + Immutable,
{
const {
assert!(
size_of::<U>() == size_of::<T>(),
"cannot transmute types of different sizes",
);
assert!(
align_of::<U>() <= align_of::<T>(),
"cannot transmute reference to increasing alignement",
);
}
let p = ptr::from_ref(r).cast::<U>();
unsafe { &*p }
}
#[inline]
#[must_use]
#[track_caller]
pub const fn transmute_mut<T, U>(r: &mut T) -> &mut U
where
T: IntoOcts + Init,
U: FromOcts + Init,
{
const {
assert!(
size_of::<U>() == size_of::<T>(),
"cannot transmute types of different sizes",
);
assert!(
align_of::<U>() <= align_of::<T>(),
"cannot transmute reference to increasing alignement",
);
}
let p = ptr::from_mut(r).cast::<U>();
unsafe { &mut *p }
}
#[inline(always)]
#[must_use]
#[track_caller]
pub const unsafe fn transmute_unchecked<T, U>(value: T) -> U {
debug_assert!(
size_of::<U>() == size_of::<T>(),
"cannot transmute types of different sizes",
);
#[repr(C)]
union Transmute<Src, Dst> {
src: ManuallyDrop<Src>,
dst: ManuallyDrop<Dst>,
}
let transmute = Transmute { src: ManuallyDrop::new(value) };
unsafe { ManuallyDrop::into_inner(transmute.dst) }
}