type_handle/
lib.rs

1use std::marker::PhantomData;
2use std::ops::{Deref, DerefMut};
3use std::{mem, ptr};
4
5/// Convert any reference into any other.
6#[inline]
7unsafe fn transmute_ref<FromT, ToT>(from: &FromT) -> &ToT {
8    debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>());
9    &*(from as *const FromT as *const ToT)
10}
11
12/// Convert any mutable reference into any other.
13#[inline]
14pub(crate) unsafe fn transmute_ref_mut<FromT, ToT>(from: &mut FromT) -> &mut ToT {
15    debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>());
16    &mut *(from as *mut FromT as *mut ToT)
17}
18
19pub struct Handle<T>(
20    T,
21    // `*const` is needed to prevent automatic Send and Sync derivation if T implements Send and Sync.
22    PhantomData<*const ()>,
23);
24
25impl<T> AsRef<Handle<T>> for Handle<T> {
26    #[inline]
27    fn as_ref(&self) -> &Self {
28        self
29    }
30}
31
32impl<T> From<T> for Handle<T> {
33    fn from(t: T) -> Self {
34        Self::from_instance(t)
35    }
36}
37
38impl<T> Handle<T> {
39    /// Wrap a struct instance into a handle.
40    #[inline]
41    #[must_use]
42    pub fn from_instance(t: T) -> Self {
43        Handle(t, PhantomData)
44    }
45
46    /// Wrap a struct reference into a handle.
47    #[inline]
48    #[must_use]
49    pub fn from_ref(t: &T) -> &Self {
50        unsafe { transmute_ref(t) }
51    }
52
53    /// Wrap a mutable struct reference into a mutable handle.
54    #[inline]
55    #[must_use]
56    pub fn from_ref_mut(t: &mut T) -> &mut Self {
57        unsafe { transmute_ref_mut(t) }
58    }
59
60    /// Wrap a const pointer into a const handle pointer.
61    #[inline]
62    #[must_use]
63    pub fn from_ptr(tp: *const T) -> *const Self {
64        tp as _
65    }
66
67    /// Wrap a mut pointer into a mut handle pointer.
68    #[inline]
69    #[must_use]
70    pub fn from_ptr_mut(tp: *mut T) -> *mut Self {
71        tp as _
72    }
73
74    /// Replaces the instance with the one from this Handle, and returns the replaced one
75    /// wrapped in a Handle without dropping either one.
76    #[inline]
77    #[must_use]
78    pub fn replace(mut self, t: &mut T) -> Self {
79        mem::swap(&mut self.0, t);
80        self
81    }
82
83    /// Consumes the wrapper and returns the wrapped type.
84    #[inline]
85    #[must_use]
86    pub fn into_instance(mut self) -> T {
87        let r = mem::replace(&mut self.0, unsafe { mem::zeroed() });
88        mem::forget(self);
89        r
90    }
91
92    /// Returns a reference to the wrapped type.
93    #[inline]
94    #[must_use]
95    pub fn instance(&self) -> &T {
96        &self.0
97    }
98
99    /// Returns a mutable reference to the wrapped type.
100    #[inline]
101    #[must_use]
102    pub fn instance_mut(&mut self) -> &mut T {
103        &mut self.0
104    }
105}
106
107impl<T: Clone> Clone for Handle<T> {
108    fn clone(&self) -> Self {
109        Self::from_instance(self.0.clone())
110    }
111}
112
113impl<T: PartialEq> PartialEq for Handle<T> {
114    fn eq(&self, other: &Self) -> bool {
115        self.instance().eq(other.instance())
116    }
117}
118
119impl<T> Deref for Handle<T> {
120    type Target = T;
121
122    #[inline]
123    fn deref(&self) -> &Self::Target {
124        self.instance()
125    }
126}
127
128impl<T> DerefMut for Handle<T> {
129    #[inline]
130    fn deref_mut(&mut self) -> &mut Self::Target {
131        self.instance_mut()
132    }
133}
134
135#[cfg(feature = "send_sync")]
136unsafe impl<T> Send for Handle<T> {}
137
138#[cfg(feature = "send_sync")]
139unsafe impl<T> Sync for Handle<T> {}
140
141/// A wrapper type represented by a reference counted pointer to the wrapped type.
142#[repr(transparent)]
143pub struct RCHandle<T>(ptr::NonNull<T>);
144
145impl<T> From<&RCHandle<T>> for RCHandle<T> {
146    fn from(rch: &RCHandle<T>) -> Self {
147        rch.clone().into()
148    }
149}
150
151impl<T> AsRef<RCHandle<T>> for RCHandle<T> {
152    fn as_ref(&self) -> &RCHandle<T> {
153        self
154    }
155}
156
157impl<T> RCHandle<T> {
158    /// Create a reference counted handle from a pointer.
159    ///
160    /// Takes ownership of the object the pointer points to, does not increase the reference count.
161    ///
162    /// Returns [`None`] if the pointer is `null`.
163    #[inline]
164    pub fn from_ptr(ptr: *mut T) -> Option<Self> {
165        ptr::NonNull::new(ptr).map(Self)
166    }
167
168    /// Create a reference counted handle from a pointer.
169    ///
170    /// Shares ownership with the object the pointer points to, therefore increases the reference count.
171    ///
172    /// Returns [`None`] if the pointer is `null`.
173    #[inline]
174    pub fn from_unshared_ptr(ptr: *mut T) -> Option<Self> {
175        ptr::NonNull::new(ptr).map(|ptr| {
176            unsafe {
177                let _ = ptr.as_ref();
178            }
179            Self(ptr)
180        })
181    }
182
183    /// Create a reference to the wrapper from a reference to a pointer that points to the wrapped type.
184    #[inline]
185    pub fn from_unshared_ptr_ref(t: &*mut T) -> &Option<Self> {
186        unsafe { transmute_ref(t) }
187    }
188
189    /// Create a reference counted handle from a mutable reference.
190    ///
191    /// Takes ownership of the referenced object.
192    #[inline]
193    pub fn from_ref(t: &mut T) -> Self {
194        // references cannot be null, so it's safe to call unwrap_unchecked() here
195        unsafe { Self::from_ptr(t).unwrap_unchecked() }
196    }
197
198    /// Returns the pointer to the handle.
199    #[inline]
200    pub fn as_ptr(&self) -> &ptr::NonNull<T> {
201        &self.0
202    }
203
204    /// Returns a reference to the wrapped type.
205    #[inline]
206    pub fn as_ref(&self) -> &T {
207        unsafe { self.0.as_ref() }
208    }
209
210    /// Returns a mutable reference to the wrapped type.
211    #[inline]
212    pub fn as_mut(&mut self) -> &mut T {
213        unsafe { self.0.as_mut() }
214    }
215
216    /// Consumes the wrapper and returns a pointer to the wrapped type.
217    #[inline]
218    pub fn into_ptr(self) -> *mut T {
219        let ptr = self.0.as_ptr();
220        mem::forget(self);
221        ptr
222    }
223}
224
225impl<T> Clone for RCHandle<T> {
226    fn clone(&self) -> Self {
227        let ptr = self.0;
228        unsafe {
229            let _ = ptr.as_ref();
230        }
231        Self(ptr)
232    }
233}
234
235impl<T: PartialEq> PartialEq for RCHandle<T> {
236    fn eq(&self, other: &Self) -> bool {
237        self.as_ref().eq(other.as_ref())
238    }
239}
240
241impl<T> Deref for RCHandle<T> {
242    type Target = T;
243
244    #[inline]
245    fn deref(&self) -> &Self::Target {
246        self.as_ref()
247    }
248}
249
250impl<T> DerefMut for RCHandle<T> {
251    #[inline]
252    fn deref_mut(&mut self) -> &mut Self::Target {
253        self.as_mut()
254    }
255}
256
257#[cfg(feature = "send_sync")]
258unsafe impl<T> Send for RCHandle<T> {}
259
260#[cfg(feature = "send_sync")]
261unsafe impl<T> Sync for RCHandle<T> {}
262
263#[cfg(test)]
264mod tests {
265    use super::*;
266
267    struct Thing {
268        number: i32,
269    }
270
271    #[test]
272    fn test_handle() {
273        for num in 0..128 {
274            let thing = Thing { number: num };
275            let handle = Handle::from_instance(thing);
276            assert!(handle.number == num && handle.instance().number == num);
277        }
278    }
279
280    #[test]
281    fn test_handle_mut() {
282        for num in 0..128 {
283            let thing = Thing { number: num };
284            let mut handle = Handle::from_instance(thing);
285            assert!(
286                handle.number == num
287                    && handle.instance().number == num
288                    && handle.instance_mut().number == num
289            );
290            let new_num = num * 5;
291            handle.number = new_num;
292            assert!(handle.number == new_num);
293        }
294    }
295
296    #[test]
297    fn test_rchandle() {
298        for num in 0..128 {
299            let mut thing = Thing { number: num };
300            let mut rch = RCHandle::from_ptr(&mut thing).unwrap();
301            assert!(rch.number == num && rch.as_ref().number == num && rch.as_mut().number == num);
302            let new_num = num * 6;
303            rch.number = new_num;
304            assert!(rch.number == new_num);
305
306            let mut rch = RCHandle::from_ref(&mut thing);
307            rch.number = 11;
308            assert!(rch.number == 11);
309        }
310    }
311}