Skip to main content

atomic_tagged_ptr/
ptr.rs

1use core::fmt;
2use core::ptr::NonNull;
3
4/// A transparent wrapper around `Option<NonNull<T>>` returned by `AtomicTaggedPtr` operations.
5///
6/// It provides convenient helper methods to convert into raw const/mutable pointers,
7/// access the underlying `Option<NonNull<T>>`, and supports direct comparisons.
8#[repr(transparent)]
9pub struct Ptr<T> {
10    inner: Option<NonNull<T>>,
11}
12
13impl<T> Default for Ptr<T> {
14    #[inline]
15    fn default() -> Self {
16        Self { inner: None }
17    }
18}
19
20impl<T> Copy for Ptr<T> {}
21
22impl<T> Clone for Ptr<T> {
23    #[inline]
24    fn clone(&self) -> Self {
25        *self
26    }
27}
28
29impl<T> fmt::Debug for Ptr<T> {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        fmt::Debug::fmt(&self.inner, f)
32    }
33}
34
35impl<T> Ptr<T> {
36    /// Creates a new `Ptr` wrapper from an `Option<NonNull<T>>`.
37    #[inline]
38    pub const fn new(ptr: Option<NonNull<T>>) -> Self {
39        Self { inner: ptr }
40    }
41    /// Converts the pointer into a raw mutable pointer `*mut T`.
42    /// Returns a null pointer if the underlying value is `None`.
43    #[inline]
44    pub fn as_mut_ptr(self) -> *mut T {
45        self.inner
46            .map(|p| p.as_ptr())
47            .unwrap_or(core::ptr::null_mut())
48    }
49
50    /// Converts the pointer into a raw const pointer `*const T`.
51    /// Returns a null pointer if the underlying value is `None`.
52    #[inline]
53    pub fn as_ptr(self) -> *const T {
54        self.inner
55            .map(|p| p.as_ptr() as *const T)
56            .unwrap_or(core::ptr::null())
57    }
58
59    /// Obtains the underlying `Option<NonNull<T>>`.
60    #[inline]
61    pub const fn option(self) -> Option<NonNull<T>> {
62        self.inner
63    }
64
65    /// Obtains the underlying `Option<NonNull<T>>`.
66    #[inline]
67    pub const fn as_option(self) -> Option<NonNull<T>> {
68        self.inner
69    }
70
71    /// Returns `true` if the pointer is null.
72    #[inline]
73    pub fn is_null(self) -> bool {
74        self.inner.is_none()
75    }
76
77    /// Returns `true` if the pointer is not null (is some).
78    #[inline]
79    pub fn is_some(self) -> bool {
80        self.inner.is_some()
81    }
82
83    /// Returns `true` if the pointer is null (is none).
84    #[inline]
85    pub fn is_none(self) -> bool {
86        self.inner.is_none()
87    }
88
89    /// Returns a shared reference to the value if the pointer is not null.
90    ///
91    /// # Safety
92    ///
93    /// The caller must ensure that the pointer is valid, aligned, points to a valid initialized value,
94    /// and respects the aliasing rules of Rust references.
95    #[inline]
96    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
97        self.inner.map(|p| unsafe { p.as_ref() })
98    }
99
100    /// Returns a mutable reference to the value if the pointer is not null.
101    ///
102    /// # Safety
103    ///
104    /// The caller must ensure that the pointer is valid, aligned, points to a valid initialized value,
105    /// and respects the aliasing rules of Rust references.
106    #[inline]
107    pub unsafe fn as_mut<'a>(mut self) -> Option<&'a mut T> {
108        self.inner.as_mut().map(|p| unsafe { p.as_mut() })
109    }
110
111    /// Unwraps the inner `NonNull<T>`, panicking with the given message if it is `None`.
112    #[inline]
113    pub fn expect(self, msg: &str) -> NonNull<T> {
114        self.inner.expect(msg)
115    }
116
117    /// Unwraps the inner `NonNull<T>`, panicking if it is `None`.
118    #[inline]
119    pub fn unwrap(self) -> NonNull<T> {
120        self.inner
121            .expect("called `Ptr::unwrap()` on a null pointer")
122    }
123
124    /// Returns the contained `NonNull<T>` or a default.
125    #[inline]
126    pub fn unwrap_or(self, default: NonNull<T>) -> NonNull<T> {
127        self.inner.unwrap_or(default)
128    }
129
130    /// Maps the inner `NonNull<T>` pointer to a new pointer of another type.
131    #[inline]
132    pub fn map<U, F>(self, f: F) -> Ptr<U>
133    where
134        F: FnOnce(NonNull<T>) -> NonNull<U>,
135    {
136        Ptr::new(self.inner.map(f))
137    }
138
139    /// Maps the inner `NonNull<T>` pointer to a value, or returns a default value.
140    #[inline]
141    pub fn map_or<U, F>(self, default: U, f: F) -> U
142    where
143        F: FnOnce(NonNull<T>) -> U,
144    {
145        self.inner.map_or(default, f)
146    }
147
148    /// Maps the inner `NonNull<T>` pointer to a value, or evaluates a default closure.
149    #[inline]
150    pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
151    where
152        D: FnOnce() -> U,
153        F: FnOnce(NonNull<T>) -> U,
154    {
155        self.inner.map_or_else(default, f)
156    }
157}
158
159impl<T> fmt::Pointer for Ptr<T> {
160    #[inline]
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        fmt::Pointer::fmt(&self.as_ptr(), f)
163    }
164}
165
166impl<T> PartialOrd for Ptr<T> {
167    #[inline]
168    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
169        Some(self.cmp(other))
170    }
171}
172
173impl<T> Ord for Ptr<T> {
174    #[inline]
175    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
176        self.as_ptr().cmp(&other.as_ptr())
177    }
178}
179
180impl<T> From<Ptr<T>> for *const T {
181    #[inline]
182    fn from(ptr: Ptr<T>) -> Self {
183        ptr.as_ptr()
184    }
185}
186
187impl<T> From<Ptr<T>> for *mut T {
188    #[inline]
189    fn from(ptr: Ptr<T>) -> Self {
190        ptr.as_mut_ptr()
191    }
192}
193
194impl<T> From<Ptr<T>> for Option<*const T> {
195    #[inline]
196    fn from(ptr: Ptr<T>) -> Self {
197        ptr.inner.map(|p| p.as_ptr() as *const T)
198    }
199}
200
201impl<T> From<Ptr<T>> for Option<*mut T> {
202    #[inline]
203    fn from(ptr: Ptr<T>) -> Self {
204        ptr.inner.map(|p| p.as_ptr())
205    }
206}
207
208// --- PartialEq implementations to ensure seamless forward compatibility ---
209
210impl<T> PartialEq for Ptr<T> {
211    #[inline]
212    fn eq(&self, other: &Self) -> bool {
213        self.inner == other.inner
214    }
215}
216
217impl<T> Eq for Ptr<T> {}
218
219impl<T> core::hash::Hash for Ptr<T> {
220    #[inline]
221    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
222        self.inner.hash(state);
223    }
224}
225
226impl<T> PartialEq<Option<NonNull<T>>> for Ptr<T> {
227    #[inline]
228    fn eq(&self, other: &Option<NonNull<T>>) -> bool {
229        self.inner == *other
230    }
231}
232
233impl<T> PartialEq<NonNull<T>> for Ptr<T> {
234    #[inline]
235    fn eq(&self, other: &NonNull<T>) -> bool {
236        self.inner == Some(*other)
237    }
238}
239
240impl<T> PartialEq<*const T> for Ptr<T> {
241    #[inline]
242    fn eq(&self, other: &*const T) -> bool {
243        self.as_ptr() == *other
244    }
245}
246
247impl<T> PartialEq<*mut T> for Ptr<T> {
248    #[inline]
249    fn eq(&self, other: &*mut T) -> bool {
250        self.as_mut_ptr() == *other
251    }
252}
253
254// --- From / Into conversion implementations for Ptr<T> ---
255
256impl<T> From<Option<NonNull<T>>> for Ptr<T> {
257    #[inline]
258    fn from(ptr: Option<NonNull<T>>) -> Self {
259        Self { inner: ptr }
260    }
261}
262
263impl<T> From<NonNull<T>> for Ptr<T> {
264    #[inline]
265    fn from(ptr: NonNull<T>) -> Self {
266        Self { inner: Some(ptr) }
267    }
268}
269
270impl<T> From<*const T> for Ptr<T> {
271    #[inline]
272    fn from(ptr: *const T) -> Self {
273        Self {
274            inner: NonNull::new(ptr as *mut T),
275        }
276    }
277}
278
279impl<T> From<*mut T> for Ptr<T> {
280    #[inline]
281    fn from(ptr: *mut T) -> Self {
282        Self {
283            inner: NonNull::new(ptr),
284        }
285    }
286}
287
288impl<T> From<TaggedPtr<T>> for Ptr<T> {
289    #[inline]
290    fn from(tagged: TaggedPtr<T>) -> Self {
291        tagged.ptr
292    }
293}
294
295impl<T> From<Ptr<T>> for Option<NonNull<T>> {
296    #[inline]
297    fn from(ptr: Ptr<T>) -> Self {
298        ptr.inner
299    }
300}
301
302impl<T> From<TaggedPtr<T>> for Option<NonNull<T>> {
303    #[inline]
304    fn from(tagged: TaggedPtr<T>) -> Self {
305        tagged.ptr.inner
306    }
307}
308
309/// A packaged representation of a pointer and a generation tag.
310/// Used for atomic operations with `AtomicTaggedPtr`.
311pub struct TaggedPtr<T> {
312    /// The physical pointer wrapper.
313    pub ptr: Ptr<T>,
314    /// The generation tag for ABA protection.
315    pub tag: crate::Tag,
316}
317
318impl<T> Copy for TaggedPtr<T> {}
319
320impl<T> Clone for TaggedPtr<T> {
321    #[inline]
322    fn clone(&self) -> Self {
323        *self
324    }
325}
326
327impl<T> PartialEq for TaggedPtr<T> {
328    #[inline]
329    fn eq(&self, other: &Self) -> bool {
330        self.ptr == other.ptr && self.tag == other.tag
331    }
332}
333
334impl<T> Eq for TaggedPtr<T> {}
335
336impl<T> core::hash::Hash for TaggedPtr<T> {
337    #[inline]
338    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
339        self.ptr.hash(state);
340        self.tag.hash(state);
341    }
342}
343
344impl<T> Default for TaggedPtr<T> {
345    #[inline]
346    fn default() -> Self {
347        Self {
348            ptr: Ptr::default(),
349            tag: crate::Tag::default(),
350        }
351    }
352}
353
354impl<T> TaggedPtr<T> {
355    /// Creates a new `TaggedPtr` from a pointer and a tag.
356    #[inline]
357    pub fn new<P>(ptr: P, tag: crate::Tag) -> Self
358    where
359        P: Into<Ptr<T>>,
360    {
361        Self {
362            ptr: ptr.into(),
363            tag,
364        }
365    }
366
367    /// Deconstructs the `TaggedPtr` into a tuple of `(Ptr<T>, Tag)`.
368    #[inline]
369    pub fn decompose(self) -> (Ptr<T>, crate::Tag) {
370        (self.ptr, self.tag)
371    }
372
373    /// Converts the pointer into a raw const pointer `*const T`.
374    /// Returns a null pointer if the underlying value is `None`.
375    #[inline]
376    pub fn as_ptr(self) -> *const T {
377        self.ptr.as_ptr()
378    }
379
380    /// Converts the pointer into a raw mutable pointer `*mut T`.
381    /// Returns a null pointer if the underlying value is `None`.
382    #[inline]
383    pub fn as_mut_ptr(self) -> *mut T {
384        self.ptr.as_mut_ptr()
385    }
386
387    /// Returns `true` if the pointer is null.
388    #[inline]
389    pub fn is_null(self) -> bool {
390        self.ptr.is_null()
391    }
392
393    /// Returns `true` if the pointer is not null (is some).
394    #[inline]
395    pub fn is_some(self) -> bool {
396        self.ptr.is_some()
397    }
398
399    /// Returns `true` if the pointer is null (is none).
400    #[inline]
401    pub fn is_none(self) -> bool {
402        self.ptr.is_none()
403    }
404
405    /// Returns a shared reference to the value if the pointer is not null.
406    ///
407    /// # Safety
408    ///
409    /// The caller must ensure that the pointer is valid, aligned, points to a valid initialized value,
410    /// and respects the aliasing rules of Rust references.
411    #[inline]
412    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
413        unsafe { self.ptr.as_ref() }
414    }
415
416    /// Returns a mutable reference to the value if the pointer is not null.
417    ///
418    /// # Safety
419    ///
420    /// The caller must ensure that the pointer is valid, aligned, points to a valid initialized value,
421    /// and respects the aliasing rules of Rust references.
422    #[inline]
423    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
424        unsafe { self.ptr.as_mut() }
425    }
426
427    /// Returns a new `TaggedPtr` with a different pointer but the same tag.
428    #[inline]
429    pub fn with_ptr<U>(self, ptr: impl Into<Ptr<U>>) -> TaggedPtr<U> {
430        TaggedPtr {
431            ptr: ptr.into(),
432            tag: self.tag,
433        }
434    }
435
436    /// Returns a new `TaggedPtr` with a different tag but the same pointer.
437    #[inline]
438    pub fn with_tag(self, tag: crate::Tag) -> Self {
439        Self { ptr: self.ptr, tag }
440    }
441
442    /// Maps the pointer part of the `TaggedPtr` using the given closure.
443    #[inline]
444    pub fn map_ptr<U, F>(self, f: F) -> TaggedPtr<U>
445    where
446        F: FnOnce(Ptr<T>) -> Ptr<U>,
447    {
448        TaggedPtr {
449            ptr: f(self.ptr),
450            tag: self.tag,
451        }
452    }
453}
454
455impl<T> fmt::Pointer for TaggedPtr<T> {
456    #[inline]
457    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
458        fmt::Pointer::fmt(&self.ptr, f)
459    }
460}
461
462impl<T> PartialOrd for TaggedPtr<T> {
463    #[inline]
464    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
465        Some(self.cmp(other))
466    }
467}
468
469impl<T> Ord for TaggedPtr<T> {
470    #[inline]
471    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
472        match self.ptr.cmp(&other.ptr) {
473            core::cmp::Ordering::Equal => self.tag.cmp(&other.tag),
474            ord => ord,
475        }
476    }
477}
478
479impl<T> From<TaggedPtr<T>> for *const T {
480    #[inline]
481    fn from(tagged: TaggedPtr<T>) -> Self {
482        tagged.as_ptr()
483    }
484}
485
486impl<T> From<TaggedPtr<T>> for *mut T {
487    #[inline]
488    fn from(tagged: TaggedPtr<T>) -> Self {
489        tagged.as_mut_ptr()
490    }
491}
492
493impl<T> fmt::Debug for TaggedPtr<T> {
494    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
495        f.debug_struct("TaggedPtr")
496            .field("ptr", &self.ptr)
497            .field("tag", &self.tag)
498            .finish()
499    }
500}
501
502impl<T> From<(Ptr<T>, crate::Tag)> for TaggedPtr<T> {
503    #[inline]
504    fn from(tuple: (Ptr<T>, crate::Tag)) -> Self {
505        Self {
506            ptr: tuple.0,
507            tag: tuple.1,
508        }
509    }
510}
511
512impl<T> From<(Option<NonNull<T>>, crate::Tag)> for TaggedPtr<T> {
513    #[inline]
514    fn from(tuple: (Option<NonNull<T>>, crate::Tag)) -> Self {
515        Self {
516            ptr: Ptr::new(tuple.0),
517            tag: tuple.1,
518        }
519    }
520}
521
522impl<T> From<(NonNull<T>, crate::Tag)> for TaggedPtr<T> {
523    #[inline]
524    fn from(tuple: (NonNull<T>, crate::Tag)) -> Self {
525        Self {
526            ptr: Ptr::from(tuple.0),
527            tag: tuple.1,
528        }
529    }
530}
531
532impl<T> From<(*const T, crate::Tag)> for TaggedPtr<T> {
533    #[inline]
534    fn from(tuple: (*const T, crate::Tag)) -> Self {
535        Self {
536            ptr: Ptr::from(tuple.0),
537            tag: tuple.1,
538        }
539    }
540}
541
542impl<T> From<(*mut T, crate::Tag)> for TaggedPtr<T> {
543    #[inline]
544    fn from(tuple: (*mut T, crate::Tag)) -> Self {
545        Self {
546            ptr: Ptr::from(tuple.0),
547            tag: tuple.1,
548        }
549    }
550}
551
552impl<T> From<TaggedPtr<T>> for (Ptr<T>, crate::Tag) {
553    #[inline]
554    fn from(tagged: TaggedPtr<T>) -> Self {
555        (tagged.ptr, tagged.tag)
556    }
557}