use core::borrow::{Borrow, BorrowMut};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr;
#[repr(transparent)]
pub(crate) struct Once<T: ?Sized>(mem::ManuallyDrop<T>);
pub struct RefOnce<'a, T: ?Sized> {
slot: &'a mut Once<T>,
}
impl<'a, T> RefOnce<'a, T> {
pub fn new(value: T, slot: &'a mut mem::MaybeUninit<T>) -> Self {
slot.write(value);
RefOnce {
slot: unsafe { mem::transmute::<&'a mut mem::MaybeUninit<T>, &'a mut Once<T>>(slot) },
}
}
pub fn into_inner(this: Self) -> T {
let mut this = mem::ManuallyDrop::new(this);
unsafe { mem::ManuallyDrop::take(&mut this.slot.0) }
}
}
impl<'a, T: ?Sized> RefOnce<'a, T> {
pub fn into_raw(this: Self) -> *mut T {
let this = mem::ManuallyDrop::new(this);
(unsafe { ptr::addr_of!(this.slot).read() } as *mut Once<T>) as *mut T
}
pub unsafe fn from_raw(ptr: *mut T) -> Self {
RefOnce {
slot: unsafe { &mut *(ptr as *mut Once<T>) },
}
}
}
impl<T: ?Sized> Deref for RefOnce<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.slot.0
}
}
impl<T: ?Sized> DerefMut for RefOnce<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.slot.0
}
}
impl<T: ?Sized> Borrow<T> for RefOnce<'_, T> {
fn borrow(&self) -> &T {
&self.slot.0
}
}
impl<T: ?Sized> BorrowMut<T> for RefOnce<'_, T> {
fn borrow_mut(&mut self) -> &mut T {
&mut self.slot.0
}
}
impl<T: ?Sized> Drop for RefOnce<'_, T> {
fn drop(&mut self) {
unsafe { mem::ManuallyDrop::drop(&mut self.slot.0) }
}
}