scope_lock/
ref_once.rs

1use core::borrow::{Borrow, BorrowMut};
2use core::mem;
3use core::ops::{Deref, DerefMut};
4use core::ptr;
5
6#[repr(transparent)]
7pub(crate) struct Once<T: ?Sized>(mem::ManuallyDrop<T>);
8
9// TODO: split into separate crate
10pub struct RefOnce<'a, T: ?Sized> {
11    slot: &'a mut Once<T>,
12}
13
14impl<'a, T> RefOnce<'a, T> {
15    pub fn new(value: T, slot: &'a mut mem::MaybeUninit<T>) -> Self {
16        slot.write(value);
17        RefOnce {
18            slot: unsafe { mem::transmute::<&'a mut mem::MaybeUninit<T>, &'a mut Once<T>>(slot) },
19        }
20    }
21
22    pub fn into_inner(this: Self) -> T {
23        let mut this = mem::ManuallyDrop::new(this);
24        unsafe { mem::ManuallyDrop::take(&mut this.slot.0) }
25    }
26}
27
28impl<'a, T: ?Sized> RefOnce<'a, T> {
29    /// Essentially leaks object as a pointer until the original
30    /// [`RefOnce`] is restored via [`Self::from_raw`].
31    pub fn into_raw(this: Self) -> *mut T {
32        let this = mem::ManuallyDrop::new(this);
33        (unsafe { ptr::addr_of!(this.slot).read() } as *mut Once<T>) as *mut T
34    }
35
36    /// Convert pointer returned from [`Self::into_raw`] back into
37    /// [`RefOnce`].
38    ///
39    /// # Safety
40    ///
41    /// `ptr` must have been returned from [`Self::into_raw`]. New
42    /// lifetime argument `'a` of [`RefOnce`] should not outlive old
43    /// lifetime not to cause any undefined behaviour.
44    pub unsafe fn from_raw(ptr: *mut T) -> Self {
45        RefOnce {
46            slot: unsafe { &mut *(ptr as *mut Once<T>) },
47        }
48    }
49}
50
51impl<T: ?Sized> Deref for RefOnce<'_, T> {
52    type Target = T;
53
54    fn deref(&self) -> &Self::Target {
55        &self.slot.0
56    }
57}
58
59impl<T: ?Sized> DerefMut for RefOnce<'_, T> {
60    fn deref_mut(&mut self) -> &mut Self::Target {
61        &mut self.slot.0
62    }
63}
64
65impl<T: ?Sized> Borrow<T> for RefOnce<'_, T> {
66    fn borrow(&self) -> &T {
67        &self.slot.0
68    }
69}
70
71impl<T: ?Sized> BorrowMut<T> for RefOnce<'_, T> {
72    fn borrow_mut(&mut self) -> &mut T {
73        &mut self.slot.0
74    }
75}
76
77impl<T: ?Sized> Drop for RefOnce<'_, T> {
78    fn drop(&mut self) {
79        unsafe { mem::ManuallyDrop::drop(&mut self.slot.0) }
80    }
81}