use core::{
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
};
#[repr(transparent)]
pub struct DropMut<'a, T: ?Sized>(
&'a mut T
);
impl<'a, T: ?Sized> DropMut<'a, T> {
pub unsafe fn new(value: &'a mut T) -> Self {
Self(value)
}
pub fn at_uninit(at: &'a mut MaybeUninit<T>, value: T) -> Self
where
T: Sized,
{
Self(at.write(value))
}
pub fn take(self) -> T
where
T: Sized,
{
let value = unsafe { core::ptr::read(&raw const *self.0) };
_ = ManuallyDrop::new(self);
value
}
pub fn take_ref(self) -> &'a mut T
where
T: Sized,
{
let mut value = ManuallyDrop::new(self);
unsafe { &mut *&raw mut *value.0 }
}
}
impl<'a, T: ?Sized> Deref for DropMut<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl<'a, T: ?Sized> DerefMut for DropMut<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
impl<'a, T: ?Sized> Drop for DropMut<'a, T> {
fn drop(&mut self) {
unsafe { core::ptr::drop_in_place(&raw mut *self.0) };
}
}