use core::{
mem::ManuallyDrop,
ptr::{self, NonNull},
};
pub const fn man_drop_ref<T>(man: &ManuallyDrop<T>) -> &T {
unsafe { &*ptr::from_ref(man).cast() }
}
pub const fn man_drop_mut<T>(man: &mut ManuallyDrop<T>) -> &mut T {
unsafe { &mut *ptr::from_mut(man).cast() }
}
pub const fn nonnull_from<T: ?Sized>(src: impl hidden::Reference<Referee = T>) -> NonNull<T> {
const fn doit<T: ?Sized, R: hidden::Reference<Referee = T>>(src: R) -> NonNull<R::Referee> {
let ptr: *mut T = {
let src = ManuallyDrop::new(src);
if R::MUTABLE {
let ptr: &mut T = unsafe { core::mem::transmute_copy(&src) };
ptr
} else {
let ptr: &T = unsafe { core::mem::transmute_copy(&src) };
ptr::from_ref(ptr).cast_mut()
}
};
unsafe { NonNull::new_unchecked(ptr) }
}
doit(src)
}
mod hidden {
pub unsafe trait Reference: Into<core::ptr::NonNull<Self::Referee>> {
type Referee: ?Sized;
const MUTABLE: bool;
}
unsafe impl<T: ?Sized> Reference for &T {
type Referee = T;
const MUTABLE: bool = false;
}
unsafe impl<T: ?Sized> Reference for &mut T {
type Referee = T;
const MUTABLE: bool = true;
}
}