use core::alloc::Layout;
use core::mem::MaybeUninit;
use core::marker::PhantomData;
use core::ptr::NonNull;
use alloc::boxed::Box;
use alloc::vec::Vec;
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct SameLayout<A, B>(PhantomData<(A, B)>);
impl<A, B> SameLayout<A, B> {
pub const fn new() -> Option<Self> {
let layout_a = Layout::new::<A>();
let layout_b = Layout::new::<B>();
if layout_a.size() == layout_b.size() && layout_a.align() == layout_b.align() {
Some(SameLayout(PhantomData))
} else {
None
}
}
pub fn forget_vec(self, vec: Vec<A>) -> Vec<B> {
let mut vec = core::mem::ManuallyDrop::new(vec);
let cap = vec.capacity();
let ptr = vec.as_mut_ptr();
unsafe { Vec::from_raw_parts(ptr as *mut B, 0, cap) }
}
pub fn deinit_box(self, boxed: Box<A>) -> (A, Box<MaybeUninit<B>>) {
let ptr = Box::into_raw(boxed);
let a = unsafe { core::ptr::read(ptr) };
(a, unsafe { Box::from_raw(ptr as *mut MaybeUninit<B>) })
}
}
impl<A, B> Clone for SameLayout<A, B> {
fn clone(&self) -> Self {
SameLayout(self.0)
}
}
impl<A, B> Copy for SameLayout<A, B> {}
impl<A, B> SameLayout<A, B> {
pub const fn array<const N: usize>(self) -> SameLayout<[A; N], [B; N]> {
SameLayout(PhantomData)
}
pub const fn chain<C>(self, _: SameLayout<B, C>) -> SameLayout<A, C> {
SameLayout(PhantomData)
}
pub const fn transpose(self) -> SameLayout<B, A> {
SameLayout(PhantomData)
}
}
pub const fn id<A>() -> SameLayout<A, A> {
SameLayout(PhantomData)
}
pub const fn for_ref<'a, A: ?Sized>() -> SameLayout<*const A, &'a A> {
SameLayout(PhantomData)
}
pub fn for_mut<'a, A: ?Sized>() -> SameLayout<*const A, &'a mut A> {
SameLayout(PhantomData)
}
pub const fn for_ref_opt<'a, A: ?Sized>() -> SameLayout<&'a A, Option<&'a A>> {
SameLayout(PhantomData)
}
pub fn for_mut_opt<'a, A: ?Sized>() -> SameLayout<&'a mut A, Option<&'a mut A>> {
SameLayout(PhantomData)
}
pub const fn for_sized_ptr<A, B>() -> SameLayout<*const A, *const B> {
SameLayout(PhantomData)
}
pub const fn for_ptr_mut<A: ?Sized>() -> SameLayout<*const A, *mut A> {
SameLayout(PhantomData)
}
pub const fn for_non_null<A: ?Sized>() -> SameLayout<*const A, NonNull<A>> {
SameLayout(PhantomData)
}
pub const fn for_non_null_opt<A: ?Sized>() -> SameLayout<*const A, Option<NonNull<A>>> {
SameLayout(PhantomData)
}
pub const fn for_box<A: ?Sized>() -> SameLayout<*const A, Box<A>> {
SameLayout(PhantomData)
}
pub const fn for_box_opt<A: ?Sized>() -> SameLayout<*const A, Option<Box<A>>> {
SameLayout(PhantomData)
}