Skip to main content

sdd/
raw_ptr.rs

1use std::marker::PhantomData;
2use std::panic::UnwindSafe;
3use std::ptr;
4
5use super::ref_counted::RefCounted;
6use super::{Ptr, Tag};
7
8/// [`RawPtr`] is a raw pointer where the lifetime of the pointed-to instance is not managed.
9///
10/// [`RawPtr`] cannot dereference the pointed-to instance unless it is converted into [`Ptr`]
11/// through [`RawPtr::into_ptr`].
12#[derive(Debug)]
13pub struct RawPtr<'g, T> {
14    ptr: *const RefCounted<T>,
15    _phantom: PhantomData<&'g T>,
16}
17
18impl<'g, T> RawPtr<'g, T> {
19    /// Creates a null [`RawPtr`].
20    ///
21    /// # Examples
22    ///
23    /// ```
24    /// use sdd::RawPtr;
25    ///
26    /// let ptr: RawPtr<usize> = RawPtr::null();
27    /// ```
28    #[inline]
29    #[must_use]
30    pub const fn null() -> Self {
31        Self {
32            ptr: ptr::null(),
33            _phantom: PhantomData,
34        }
35    }
36
37    /// Returns `true` if the [`RawPtr`] is null.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use sdd::RawPtr;
43    ///
44    /// let ptr: RawPtr<usize> = RawPtr::null();
45    /// assert!(ptr.is_null());
46    /// ```
47    #[inline]
48    #[must_use]
49    pub fn is_null(&self) -> bool {
50        Tag::unset_tag(self.ptr).is_null()
51    }
52
53    /// Returns its [`Tag`].
54    ///
55    /// # Examples
56    ///
57    /// ```
58    /// use sdd::{RawPtr, Tag};
59    ///
60    /// let ptr: RawPtr<usize> = RawPtr::null();
61    /// assert_eq!(ptr.tag(), Tag::None);
62    /// ```
63    #[inline]
64    #[must_use]
65    pub fn tag(&self) -> Tag {
66        Tag::into_tag(self.ptr)
67    }
68
69    /// Sets a [`Tag`], overwriting its existing [`Tag`].
70    ///
71    /// Returns the previous tag value.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use sdd::{RawPtr, Tag};
77    ///
78    /// let mut ptr: RawPtr<usize> = RawPtr::null();
79    /// assert_eq!(ptr.set_tag(Tag::Both), Tag::None);
80    /// assert_eq!(ptr.tag(), Tag::Both);
81    /// ```
82    #[inline]
83    pub fn set_tag(&mut self, tag: Tag) -> Tag {
84        let old_tag = Tag::into_tag(self.ptr);
85        self.ptr = Tag::update_tag(self.ptr, tag);
86        old_tag
87    }
88
89    /// Clears its [`Tag`].
90    ///
91    /// Returns the previous tag value.
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// use sdd::{RawPtr, Tag};
97    ///
98    /// let mut ptr: RawPtr<usize> = RawPtr::null().with_tag(Tag::Both);
99    /// assert_eq!(ptr.unset_tag(), Tag::Both);
100    /// ```
101    #[inline]
102    pub fn unset_tag(&mut self) -> Tag {
103        let old_tag = Tag::into_tag(self.ptr);
104        self.ptr = Tag::unset_tag(self.ptr);
105        old_tag
106    }
107
108    /// Returns a copy of `self` with a [`Tag`] set.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// use sdd::{RawPtr, Tag};
114    ///
115    /// let mut ptr: RawPtr<usize> = RawPtr::null();
116    /// assert_eq!(ptr.tag(), Tag::None);
117    ///
118    /// let ptr_with_tag = ptr.with_tag(Tag::First);
119    /// assert_eq!(ptr_with_tag.tag(), Tag::First);
120    /// ```
121    #[inline]
122    #[must_use]
123    pub fn with_tag(self, tag: Tag) -> Self {
124        Self::from(Tag::update_tag(self.ptr, tag))
125    }
126
127    /// Returns a copy of `self` with its [`Tag`] erased.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use sdd::{Ptr, RawPtr, Tag};
133    ///
134    /// let mut ptr: RawPtr<usize> = RawPtr::null();
135    /// ptr.set_tag(Tag::Second);
136    /// assert_eq!(ptr.tag(), Tag::Second);
137    ///
138    /// let ptr_without_tag = ptr.without_tag();
139    /// assert_eq!(ptr_without_tag.tag(), Tag::None);
140    /// ```
141    #[inline]
142    #[must_use]
143    pub fn without_tag(self) -> Self {
144        Self::from(Tag::unset_tag(self.ptr))
145    }
146
147    /// Converts itself into a [`Ptr`] to dereference the instance.
148    ///
149    /// # Safety
150    ///
151    /// The pointed-to instance must be valid for the lifetime `'g`.
152    ///
153    /// # Examples
154    ///
155    /// ```
156    /// use sdd::Owned;
157    ///
158    /// let owned: Owned<usize> = Owned::new(83);
159    /// let ptr = owned.into_raw();
160    /// assert_eq!(unsafe { ptr.into_ptr().as_ref() }, Some(&83));
161    /// drop(unsafe { Owned::from_raw(ptr) });
162    /// ```
163    #[inline]
164    #[must_use]
165    pub const unsafe fn into_ptr(self) -> Ptr<'g, T> {
166        Ptr::from(self.ptr)
167    }
168
169    /// Creates a new [`RawPtr`] from a [`RefCounted`] pointer.
170    #[inline]
171    pub(super) const fn from(ptr: *const RefCounted<T>) -> Self {
172        Self {
173            ptr,
174            _phantom: PhantomData,
175        }
176    }
177
178    /// Returns a pointer to the [`RefCounted`], including tag bits.
179    #[inline]
180    pub(super) const fn underlying_ptr(self) -> *const RefCounted<T> {
181        self.ptr
182    }
183}
184
185impl<T> Clone for RawPtr<'_, T> {
186    #[inline]
187    fn clone(&self) -> Self {
188        *self
189    }
190}
191
192impl<T> Copy for RawPtr<'_, T> {}
193
194impl<T> Default for RawPtr<'_, T> {
195    #[inline]
196    fn default() -> Self {
197        Self::null()
198    }
199}
200
201impl<T> Eq for RawPtr<'_, T> {}
202
203impl<T> PartialEq for RawPtr<'_, T> {
204    #[inline]
205    fn eq(&self, other: &Self) -> bool {
206        self.ptr == other.ptr
207    }
208}
209
210impl<T: UnwindSafe> UnwindSafe for RawPtr<'_, T> {}