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> {}