use core::mem::ManuallyDrop;
pub(crate) struct ErasedPtr {
ptr: *const (),
}
impl ErasedPtr {
#[inline(always)]
pub fn new<T>(ptr: *const T) -> ErasedPtr {
ErasedPtr { ptr: ptr.cast::<()>() }
}
#[inline(always)]
pub unsafe fn cast<T>(&self) -> *const T {
self.ptr.cast::<T>()
}
#[inline(always)]
pub unsafe fn map_owned<T, P, R>(
&mut self,
from_raw: unsafe fn(*const T) -> P,
as_ptr: fn(&P) -> *const T,
f: impl FnOnce(&mut P) -> R,
) -> R {
struct WriteBack<'a, T, P> {
slot: &'a mut *const (),
owned: ManuallyDrop<P>,
as_ptr: fn(&P) -> *const T,
}
impl<T, P> Drop for WriteBack<'_, T, P> {
#[inline(always)]
fn drop(&mut self) {
*self.slot = (self.as_ptr)(&self.owned).cast::<()>();
}
}
let owned: P = unsafe { from_raw(self.ptr.cast::<T>()) };
let mut guard =
WriteBack::<T, P> { slot: &mut self.ptr, owned: ManuallyDrop::new(owned), as_ptr };
f(&mut guard.owned)
}
}