intrusive_collections/
unsafe_ref.rs

1// Copyright 2016 Amanieu d'Antras
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8#[cfg(feature = "alloc")]
9use crate::alloc::boxed::Box;
10use core::borrow::Borrow;
11use core::fmt;
12use core::ops::Deref;
13use core::ptr::NonNull;
14
15/// Unchecked shared pointer
16///
17/// This type acts like a `Rc` or `Arc` except that no reference count is
18/// maintained. Instead, the user is responsible for freeing the managed object
19/// once it is no longer in use.
20///
21/// You must guarantee that an object managed by an `UnsafeRef` is not
22/// moved, dropped or accessed through a mutable reference as long as at least
23/// one `UnsafeRef` is pointing to it.
24pub struct UnsafeRef<T: ?Sized> {
25    ptr: NonNull<T>,
26}
27
28impl<T: ?Sized> UnsafeRef<T> {
29    /// Creates an `UnsafeRef` from a raw pointer
30    ///
31    /// # Safety
32    ///
33    /// You must ensure that the `UnsafeRef` guarantees are upheld.
34    #[inline]
35    pub unsafe fn from_raw(val: *const T) -> UnsafeRef<T> {
36        UnsafeRef {
37            ptr: NonNull::new_unchecked(val as *mut _),
38        }
39    }
40
41    /// Converts an `UnsafeRef` into a raw pointer
42    #[inline]
43    pub fn into_raw(ptr: Self) -> *mut T {
44        ptr.ptr.as_ptr()
45    }
46}
47
48#[cfg(feature = "alloc")]
49impl<T: ?Sized> UnsafeRef<T> {
50    /// Creates an `UnsafeRef` from a `Box`
51    #[inline]
52    pub fn from_box(val: Box<T>) -> UnsafeRef<T> {
53        unsafe { UnsafeRef::from_raw(Box::into_raw(val)) }
54    }
55
56    /// Converts an `UnsafeRef` into a `Box`
57    ///
58    /// # Safety
59    ///
60    /// You must ensure that this is the only `UnsafeRef` managing this
61    /// object and that it is not currently a member of any intrusive
62    /// collections. This operation is only valid if the `UnsafeRef` was
63    /// created using `UnsafeRef::from_box`.
64    #[inline]
65    pub unsafe fn into_box(ptr: Self) -> Box<T> {
66        Box::from_raw(UnsafeRef::into_raw(ptr))
67    }
68}
69
70impl<T: ?Sized> Clone for UnsafeRef<T> {
71    #[inline]
72    fn clone(&self) -> UnsafeRef<T> {
73        UnsafeRef { ptr: self.ptr }
74    }
75}
76
77impl<T: ?Sized> Deref for UnsafeRef<T> {
78    type Target = T;
79
80    #[inline]
81    fn deref(&self) -> &T {
82        self.as_ref()
83    }
84}
85
86impl<T: ?Sized> AsRef<T> for UnsafeRef<T> {
87    #[inline]
88    fn as_ref(&self) -> &T {
89        unsafe { self.ptr.as_ref() }
90    }
91}
92
93impl<T: ?Sized> Borrow<T> for UnsafeRef<T> {
94    #[inline]
95    fn borrow(&self) -> &T {
96        self.as_ref()
97    }
98}
99
100impl<T: fmt::Debug + ?Sized> fmt::Debug for UnsafeRef<T> {
101    #[inline]
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        fmt::Debug::fmt(self.as_ref(), f)
104    }
105}
106
107unsafe impl<T: ?Sized + Send + Sync> Send for UnsafeRef<T> {}
108
109unsafe impl<T: ?Sized + Sync> Sync for UnsafeRef<T> {}