Skip to main content

arctic/sequential/
value.rs

1use core::ops::Deref;
2use std::rc::Rc;
3
4/// Values that can be safely stored in a [`SequentialMap`][crate::sequential::Map].
5///
6/// # Safety
7///
8/// Implementer must guarantee that `Self` has the same memory layout as a `u64`.
9pub unsafe trait Value: Sized {
10    /// Erase the type of this value, returning a u64.
11    fn into_raw(self) -> u64;
12
13    /// # Safety
14    ///
15    /// Caller must guarantee that:
16    /// - `raw` was created by a previous [`Value::into_raw`] call.
17    /// - `from_raw` is called at most once for each [`Value::into_raw`] call.
18    /// - There are no live borrows when [`Value::from_raw_unchecked`] is called.
19    unsafe fn from_raw_unchecked(raw: u64) -> Self;
20}
21
22// NOTE: `Sized` is required so that &T is not a fat pointer and fits in 8 bytes
23unsafe impl<'v, T: 'v + Sized> Value for &'v T {
24    #[inline]
25    fn into_raw(self) -> u64 {
26        const {
27            assert!(core::mem::size_of::<Self>() == core::mem::size_of::<u64>());
28            assert!(core::mem::align_of::<Self>() == core::mem::align_of::<u64>());
29        }
30
31        (self as *const T).expose_provenance() as u64
32    }
33
34    #[inline]
35    unsafe fn from_raw_unchecked(raw: u64) -> Self {
36        let borrow = unsafe { core::ptr::with_exposed_provenance::<T>(raw as usize).as_ref() };
37        if_validate!(borrow.unwrap(), unsafe { borrow.unwrap_unchecked() })
38    }
39}
40
41// NOTE: `Sized` is required so that Box<T> is not a fat pointer and fits in 8 bytes
42unsafe impl<T: Sized> Value for Box<T> {
43    #[inline]
44    fn into_raw(self) -> u64 {
45        const {
46            assert!(core::mem::size_of::<Self>() == core::mem::size_of::<u64>());
47            assert!(core::mem::align_of::<Self>() == core::mem::align_of::<u64>());
48        }
49
50        Box::into_raw(self).expose_provenance() as u64
51    }
52
53    #[inline]
54    unsafe fn from_raw_unchecked(raw: u64) -> Self {
55        unsafe { Box::from_raw(core::ptr::with_exposed_provenance_mut::<T>(raw as usize)) }
56    }
57}
58
59// NOTE: `Sized` is required so that Arc<T> is not a fat pointer and fits in 8 bytes
60unsafe impl<T: Sized> Value for Arc<T> {
61    #[inline]
62    fn into_raw(self) -> u64 {
63        const {
64            assert!(core::mem::size_of::<Self>() == core::mem::size_of::<u64>());
65            assert!(core::mem::align_of::<Self>() == core::mem::align_of::<u64>());
66        }
67
68        crate::sync::Arc::into_raw(self.0).expose_provenance() as u64
69    }
70
71    #[inline]
72    unsafe fn from_raw_unchecked(raw: u64) -> Self {
73        Self(unsafe {
74            crate::sync::Arc::from_raw(core::ptr::with_exposed_provenance(raw as usize))
75        })
76    }
77}
78
79// NOTE: `Sized` is required so that Rc<T> is not a fat pointer and fits in 8 bytes
80unsafe impl<T: Sized> Value for Rc<T> {
81    #[inline]
82    fn into_raw(self) -> u64 {
83        const {
84            assert!(core::mem::size_of::<Self>() == core::mem::size_of::<u64>());
85            assert!(core::mem::align_of::<Self>() == core::mem::align_of::<u64>());
86        }
87
88        Rc::into_raw(self).expose_provenance() as u64
89    }
90
91    #[inline]
92    unsafe fn from_raw_unchecked(raw: u64) -> Self {
93        unsafe { Rc::from_raw(core::ptr::with_exposed_provenance(raw as usize)) }
94    }
95}
96
97/// Transparent wrapper for [`Arc<T>`][crate::sync::Arc<T>] smart pointer
98/// that can be borrowed as an [`ArcRef<T>`][crate::concurrent::value::ArcRef].
99#[repr(transparent)]
100#[derive(Debug)]
101pub struct Arc<T>(pub(crate) crate::sync::Arc<T>);
102
103impl<T> From<crate::sync::Arc<T>> for Arc<T> {
104    #[inline]
105    fn from(arc: crate::sync::Arc<T>) -> Self {
106        Self(arc)
107    }
108}
109
110impl<T> From<Arc<T>> for crate::sync::Arc<T> {
111    #[inline]
112    fn from(Arc(arc): Arc<T>) -> Self {
113        arc
114    }
115}
116
117impl<T> Deref for Arc<T> {
118    type Target = crate::sync::Arc<T>;
119    #[inline]
120    fn deref(&self) -> &Self::Target {
121        &self.0
122    }
123}
124
125macro_rules! impl_integer {
126    ($($ty:ty),*) => {
127        $(
128            unsafe impl Value for $ty {
129                #[inline]
130                fn into_raw(self) -> u64 {
131                    self as u64
132                }
133
134                #[inline]
135                unsafe fn from_raw_unchecked(raw: u64) -> Self {
136                    raw as $ty
137                }
138
139            }
140        )*
141    };
142}
143
144impl_integer!(u64, i64);