Skip to main content

atomic_tagged_ptr/ptr/
tagged.rs

1mod atomic;
2
3pub use atomic::{AtomicTaggedPtr, TAG_MASK};
4
5use core::fmt;
6use core::ptr::NonNull;
7
8use super::Ptr;
9
10/// A packaged representation of a pointer and a generation tag.
11/// Used for atomic operations with `AtomicTaggedPtr`.
12pub struct TaggedPtr<T> {
13    /// The physical pointer wrapper.
14    pub ptr: Ptr<T>,
15    /// The generation tag for ABA protection.
16    pub tag: crate::Tag,
17}
18
19impl<T> Copy for TaggedPtr<T> {}
20
21impl<T> Clone for TaggedPtr<T> {
22    #[inline]
23    fn clone(&self) -> Self {
24        *self
25    }
26}
27
28impl<T> PartialEq for TaggedPtr<T> {
29    #[inline]
30    fn eq(&self, other: &Self) -> bool {
31        self.ptr == other.ptr && self.tag == other.tag
32    }
33}
34
35impl<T> Eq for TaggedPtr<T> {}
36
37impl<T> core::hash::Hash for TaggedPtr<T> {
38    #[inline]
39    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
40        self.ptr.hash(state);
41        self.tag.hash(state);
42    }
43}
44
45impl<T> Default for TaggedPtr<T> {
46    #[inline]
47    fn default() -> Self {
48        Self {
49            ptr: Ptr::default(),
50            tag: crate::Tag::default(),
51        }
52    }
53}
54
55impl<T> TaggedPtr<T> {
56    /// Creates a new `TaggedPtr` from a pointer and a tag.
57    ///
58    /// # Examples
59    ///
60    /// ```rust
61    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
62    /// use std::ptr::NonNull;
63    ///
64    /// let val = 42;
65    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
66    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
67    /// assert_eq!(tagged.ptr.option(), ptr);
68    /// assert_eq!(tagged.tag.value(), 123);
69    /// ```
70    #[inline]
71    pub fn new<P>(ptr: P, tag: crate::Tag) -> Self
72    where
73        P: Into<Ptr<T>>,
74    {
75        Self {
76            ptr: ptr.into(),
77            tag,
78        }
79    }
80
81    /// Creates a new `TaggedPtr` with a null pointer and the default tag.
82    ///
83    /// # Examples
84    ///
85    /// ```rust
86    /// use atomic_tagged_ptr::TaggedPtr;
87    ///
88    /// let p: TaggedPtr<i32> = TaggedPtr::null();
89    /// assert!(p.is_null());
90    /// assert_eq!(p.tag.value(), 0);
91    /// ```
92    #[inline]
93    pub const fn null() -> Self {
94        Self {
95            ptr: Ptr::null(),
96            tag: crate::Tag::new(0),
97        }
98    }
99
100    /// Casts the pointer part to a pointer of another type, keeping the tag unchanged.
101    ///
102    /// # Examples
103    ///
104    /// ```rust
105    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
106    /// use std::ptr::NonNull;
107    ///
108    /// let val = 42u8;
109    /// let tagged = TaggedPtr::new(NonNull::new(&val as *const u8 as *mut u8), Tag::new(123));
110    /// let casted: TaggedPtr<i8> = tagged.cast();
111    /// assert_eq!(casted.tag.value(), 123);
112    /// ```
113    #[inline]
114    pub fn cast<U>(self) -> TaggedPtr<U> {
115        TaggedPtr {
116            ptr: self.ptr.cast(),
117            tag: self.tag,
118        }
119    }
120
121    /// Deconstructs the `TaggedPtr` into a tuple of `(Ptr<T>, Tag)`.
122    ///
123    /// # Examples
124    ///
125    /// ```rust
126    /// use atomic_tagged_ptr::{TaggedPtr, Tag, Ptr};
127    /// use std::ptr::NonNull;
128    ///
129    /// let val = 42;
130    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
131    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
132    /// let (p, t) = tagged.decompose();
133    /// assert_eq!(p.option(), ptr);
134    /// assert_eq!(t.value(), 123);
135    /// ```
136    #[inline]
137    pub fn decompose(self) -> (Ptr<T>, crate::Tag) {
138        (self.ptr, self.tag)
139    }
140
141    /// Converts the pointer part into a raw const pointer `*const T`.
142    /// Returns a null pointer if the underlying pointer is null.
143    ///
144    /// # Examples
145    ///
146    /// ```rust
147    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
148    /// use std::ptr::NonNull;
149    ///
150    /// let val = 42;
151    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
152    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
153    /// assert_eq!(unsafe { *tagged.as_ptr() }, 42);
154    ///
155    /// let null_tagged: TaggedPtr<i32> = TaggedPtr::null();
156    /// assert!(null_tagged.as_ptr().is_null());
157    /// ```
158    #[inline]
159    pub fn as_ptr(self) -> *const T {
160        self.ptr.as_ptr()
161    }
162
163    /// Converts the pointer part into a raw mutable pointer `*mut T`.
164    /// Returns a null pointer if the underlying pointer is null.
165    ///
166    /// # Examples
167    ///
168    /// ```rust
169    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
170    /// use std::ptr::NonNull;
171    ///
172    /// let mut val = 42;
173    /// let ptr = NonNull::new(&mut val as *mut i32);
174    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
175    /// assert_eq!(unsafe { *tagged.as_mut_ptr() }, 42);
176    ///
177    /// let null_tagged: TaggedPtr<i32> = TaggedPtr::null();
178    /// assert!(null_tagged.as_mut_ptr().is_null());
179    /// ```
180    #[inline]
181    pub fn as_mut_ptr(self) -> *mut T {
182        self.ptr.as_mut_ptr()
183    }
184
185    /// Returns `true` if the pointer part is null.
186    ///
187    /// # Examples
188    ///
189    /// ```rust
190    /// use atomic_tagged_ptr::TaggedPtr;
191    ///
192    /// let p: TaggedPtr<i32> = TaggedPtr::null();
193    /// assert!(p.is_null());
194    /// ```
195    #[inline]
196    pub fn is_null(self) -> bool {
197        self.ptr.is_null()
198    }
199
200    /// Returns `true` if the pointer part is not null (is some).
201    ///
202    /// # Examples
203    ///
204    /// ```rust
205    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
206    /// use std::ptr::NonNull;
207    ///
208    /// let val = 42;
209    /// let p = TaggedPtr::new(NonNull::new(&val as *const i32 as *mut i32), Tag::new(10));
210    /// assert!(p.is_some());
211    /// ```
212    #[inline]
213    pub fn is_some(self) -> bool {
214        self.ptr.is_some()
215    }
216
217    /// Returns `true` if the pointer part is null (is none).
218    ///
219    /// # Examples
220    ///
221    /// ```rust
222    /// use atomic_tagged_ptr::TaggedPtr;
223    ///
224    /// let p: TaggedPtr<i32> = TaggedPtr::null();
225    /// assert!(p.is_none());
226    /// ```
227    #[inline]
228    pub fn is_none(self) -> bool {
229        self.ptr.is_none()
230    }
231
232    /// Returns a shared reference to the value if the pointer part is not null.
233    ///
234    /// # Safety
235    ///
236    /// The caller must ensure that:
237    /// * The pointer is valid (aligned, points to a valid initialized value of type `T`).
238    /// * The memory is not mutated while the reference is active.
239    /// * The reference lifetime `'a` is correctly bounded.
240    ///
241    /// # Examples
242    ///
243    /// ```rust
244    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
245    /// use std::ptr::NonNull;
246    ///
247    /// let val = 42;
248    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
249    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
250    /// unsafe {
251    ///     assert_eq!(tagged.as_ref(), Some(&42));
252    /// }
253    /// ```
254    #[inline]
255    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
256        unsafe { self.ptr.as_ref() }
257    }
258
259    /// Returns a mutable reference to the value if the pointer part is not null.
260    ///
261    /// # Safety
262    ///
263    /// The caller must ensure that:
264    /// * The pointer is valid (aligned, points to a valid initialized value of type `T`).
265    /// * No other references (shared or mutable) to the same memory are active.
266    /// * The reference lifetime `'a` is correctly bounded.
267    ///
268    /// # Examples
269    ///
270    /// ```rust
271    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
272    /// use std::ptr::NonNull;
273    ///
274    /// let mut val = 42;
275    /// let ptr = NonNull::new(&mut val as *mut i32);
276    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
277    /// unsafe {
278    ///     let r = tagged.as_mut();
279    ///     assert_eq!(r, Some(&mut 42));
280    ///     *r.unwrap() = 100;
281    /// }
282    /// assert_eq!(val, 100);
283    /// ```
284    #[inline]
285    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
286        unsafe { self.ptr.as_mut() }
287    }
288
289    /// Returns a new `TaggedPtr` with a different pointer but the same tag.
290    ///
291    /// # Examples
292    ///
293    /// ```rust
294    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
295    /// use std::ptr::NonNull;
296    ///
297    /// let val1 = 10;
298    /// let val2 = 20;
299    /// let ptr1 = NonNull::new(&val1 as *const i32 as *mut i32);
300    /// let ptr2 = NonNull::new(&val2 as *const i32 as *mut i32);
301    ///
302    /// let tagged = TaggedPtr::new(ptr1, Tag::new(100));
303    /// let new_tagged = tagged.with_ptr(ptr2);
304    /// assert_eq!(new_tagged.ptr.option(), ptr2);
305    /// assert_eq!(new_tagged.tag.value(), 100);
306    /// ```
307    #[inline]
308    pub fn with_ptr<U>(self, ptr: impl Into<Ptr<U>>) -> TaggedPtr<U> {
309        TaggedPtr {
310            ptr: ptr.into(),
311            tag: self.tag,
312        }
313    }
314
315    /// Returns a new `TaggedPtr` with a different tag but the same pointer.
316    ///
317    /// # Examples
318    ///
319    /// ```rust
320    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
321    /// use std::ptr::NonNull;
322    ///
323    /// let val = 42;
324    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
325    ///
326    /// let tagged = TaggedPtr::new(ptr, Tag::new(100));
327    /// let new_tagged = tagged.with_tag(Tag::new(200));
328    /// assert_eq!(new_tagged.ptr.option(), ptr);
329    /// assert_eq!(new_tagged.tag.value(), 200);
330    /// ```
331    #[inline]
332    pub fn with_tag(self, tag: crate::Tag) -> Self {
333        Self { ptr: self.ptr, tag }
334    }
335
336    /// Maps the pointer part of the `TaggedPtr` using the given closure.
337    ///
338    /// # Examples
339    ///
340    /// ```rust
341    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
342    /// use std::ptr::NonNull;
343    ///
344    /// let val = 42u8;
345    /// let ptr = NonNull::new(&val as *const u8 as *mut u8);
346    /// let tagged = TaggedPtr::new(ptr, Tag::new(100));
347    /// let mapped = tagged.map_ptr(|p| p.cast::<i8>());
348    /// assert_eq!(unsafe { *mapped.as_ptr() }, 42);
349    /// assert_eq!(mapped.tag.value(), 100);
350    /// ```
351    #[inline]
352    pub fn map_ptr<U, F>(self, f: F) -> TaggedPtr<U>
353    where
354        F: FnOnce(Ptr<T>) -> Ptr<U>,
355    {
356        TaggedPtr {
357            ptr: f(self.ptr),
358            tag: self.tag,
359        }
360    }
361
362    /// Reads the value from the pointer part without moving it. This leaves the memory unchanged.
363    ///
364    /// # Safety
365    ///
366    /// * The pointer must be non-null.
367    /// * The pointer must be valid for reads (correctly aligned, points to an initialized instance of `T`, etc.).
368    /// * The memory must not be mutated by another thread while being read.
369    ///
370    /// # Examples
371    ///
372    /// ```rust
373    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
374    /// use std::ptr::NonNull;
375    ///
376    /// let val = 42;
377    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
378    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
379    /// unsafe {
380    ///     assert_eq!(tagged.read(), 42);
381    /// }
382    /// ```
383    #[inline]
384    pub unsafe fn read(self) -> T {
385        // Safety: The caller guarantees the pointer is valid.
386        unsafe { self.ptr.read() }
387    }
388
389    /// Performs a volatile read of the value from the pointer part without moving it.
390    ///
391    /// # Safety
392    ///
393    /// * The pointer must be non-null.
394    /// * The pointer must be valid for reads.
395    /// * The memory must not be mutated by another thread while being read.
396    ///
397    /// # Examples
398    ///
399    /// ```rust
400    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
401    /// use std::ptr::NonNull;
402    ///
403    /// let val = 42;
404    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
405    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
406    /// unsafe {
407    ///     assert_eq!(tagged.read_volatile(), 42);
408    /// }
409    /// ```
410    #[inline]
411    pub unsafe fn read_volatile(self) -> T {
412        // Safety: The caller guarantees the pointer is valid.
413        unsafe { self.ptr.read_volatile() }
414    }
415
416    /// Reads the value from the pointer part without moving it, without requiring alignment.
417    ///
418    /// # Safety
419    ///
420    /// * The pointer must be non-null.
421    /// * The pointer must be valid for reads.
422    /// * The memory must not be mutated by another thread while being read.
423    ///
424    /// # Examples
425    ///
426    /// ```rust
427    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
428    /// use std::ptr::NonNull;
429    ///
430    /// let val = 42;
431    /// let ptr = NonNull::new(&val as *const i32 as *mut i32);
432    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
433    /// unsafe {
434    ///     assert_eq!(tagged.read_unaligned(), 42);
435    /// }
436    /// ```
437    #[inline]
438    pub unsafe fn read_unaligned(self) -> T {
439        // Safety: The caller guarantees the pointer is valid.
440        unsafe { self.ptr.read_unaligned() }
441    }
442
443    /// Overwrites the memory location at the pointer part with the given value.
444    ///
445    /// # Safety
446    ///
447    /// * The pointer must be non-null.
448    /// * The pointer must be valid for writes (correctly aligned, etc.).
449    ///
450    /// # Examples
451    ///
452    /// ```rust
453    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
454    /// use std::ptr::NonNull;
455    ///
456    /// let mut val = 0;
457    /// let ptr = NonNull::new(&mut val as *mut i32);
458    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
459    /// unsafe {
460    ///     tagged.write(42);
461    /// }
462    /// assert_eq!(val, 42);
463    /// ```
464    #[inline]
465    pub unsafe fn write(self, val: T) {
466        // Safety: The caller guarantees the pointer is valid.
467        unsafe { self.ptr.write(val) }
468    }
469
470    /// Performs a volatile write to the memory location at the pointer part.
471    ///
472    /// # Safety
473    ///
474    /// * The pointer must be non-null.
475    /// * The pointer must be valid for writes.
476    ///
477    /// # Examples
478    ///
479    /// ```rust
480    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
481    /// use std::ptr::NonNull;
482    ///
483    /// let mut val = 0;
484    /// let ptr = NonNull::new(&mut val as *mut i32);
485    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
486    /// unsafe {
487    ///     tagged.write_volatile(42);
488    /// }
489    /// assert_eq!(val, 42);
490    /// ```
491    #[inline]
492    pub unsafe fn write_volatile(self, val: T) {
493        // Safety: The caller guarantees the pointer is valid.
494        unsafe { self.ptr.write_volatile(val) }
495    }
496
497    /// Overwrites the memory location at the pointer part without requiring alignment.
498    ///
499    /// # Safety
500    ///
501    /// * The pointer must be non-null.
502    /// * The pointer must be valid for writes.
503    ///
504    /// # Examples
505    ///
506    /// ```rust
507    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
508    /// use std::ptr::NonNull;
509    ///
510    /// let mut val = 0;
511    /// let ptr = NonNull::new(&mut val as *mut i32);
512    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
513    /// unsafe {
514    ///     tagged.write_unaligned(42);
515    /// }
516    /// assert_eq!(val, 42);
517    /// ```
518    #[inline]
519    pub unsafe fn write_unaligned(self, val: T) {
520        // Safety: The caller guarantees the pointer is valid.
521        unsafe { self.ptr.write_unaligned(val) }
522    }
523
524    /// Replaces the value at the pointer part with `val`, returning the old value.
525    ///
526    /// # Safety
527    ///
528    /// * The pointer must be non-null.
529    /// * The pointer must be valid for reads and writes.
530    ///
531    /// # Examples
532    ///
533    /// ```rust
534    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
535    /// use std::ptr::NonNull;
536    ///
537    /// let mut val = 10;
538    /// let ptr = NonNull::new(&mut val as *mut i32);
539    /// let tagged = TaggedPtr::new(ptr, Tag::new(1));
540    /// unsafe {
541    ///     let old = tagged.replace(20);
542    ///     assert_eq!(old, 10);
543    /// }
544    /// assert_eq!(val, 20);
545    /// ```
546    #[inline]
547    pub unsafe fn replace(self, val: T) -> T {
548        // Safety: The caller guarantees the pointer is valid.
549        unsafe { self.ptr.replace(val) }
550    }
551
552    /// Swaps the values at the pointer part of `self` and `with`.
553    ///
554    /// # Safety
555    ///
556    /// * Both pointers must be non-null.
557    /// * Both pointers must be valid for reads and writes.
558    /// * Both pointers must be properly aligned.
559    ///
560    /// # Examples
561    ///
562    /// ```rust
563    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
564    /// use std::ptr::NonNull;
565    ///
566    /// let mut val1 = 10;
567    /// let mut val2 = 20;
568    /// let ptr1 = NonNull::new(&mut val1 as *mut i32);
569    /// let ptr2 = NonNull::new(&mut val2 as *mut i32);
570    /// let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
571    /// let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
572    /// unsafe {
573    ///     tagged1.swap(tagged2);
574    /// }
575    /// assert_eq!(val1, 20);
576    /// assert_eq!(val2, 10);
577    /// ```
578    #[inline]
579    pub unsafe fn swap(self, with: TaggedPtr<T>) {
580        // Safety: The caller guarantees both pointers are valid.
581        unsafe { self.ptr.swap(with.ptr) }
582    }
583
584    /// Copies `count` items from the pointer part of `self` to `dest`. The regions may overlap.
585    ///
586    /// # Safety
587    ///
588    /// * Both pointers must be non-null.
589    /// * Both pointers must be valid for reads and writes.
590    /// * Both pointers must be properly aligned.
591    ///
592    /// # Examples
593    ///
594    /// ```rust
595    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
596    /// use std::ptr::NonNull;
597    ///
598    /// let mut arr = [1, 2, 3];
599    /// let ptr1 = NonNull::new(&mut arr[0] as *mut i32);
600    /// let ptr2 = NonNull::new(&mut arr[1] as *mut i32);
601    /// let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
602    /// let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
603    /// unsafe {
604    ///     tagged1.copy_to(tagged2, 2);
605    /// }
606    /// assert_eq!(arr, [1, 1, 2]);
607    /// ```
608    #[inline]
609    pub unsafe fn copy_to(self, dest: TaggedPtr<T>, count: usize) {
610        // Safety: The caller guarantees the pointers are valid.
611        unsafe { self.ptr.copy_to(dest.ptr, count) }
612    }
613
614    /// Copies `count` items from the pointer part of `self` to `dest`. The regions must not overlap.
615    ///
616    /// # Safety
617    ///
618    /// * Both pointers must be non-null.
619    /// * Both pointers must be valid for reads and writes.
620    /// * Both pointers must be properly aligned.
621    /// * The memory regions must not overlap.
622    ///
623    /// # Examples
624    ///
625    /// ```rust
626    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
627    /// use std::ptr::NonNull;
628    ///
629    /// let mut arr1 = [1, 2, 3];
630    /// let mut arr2 = [0, 0, 0];
631    /// let ptr1 = NonNull::new(&mut arr1[0] as *mut i32);
632    /// let ptr2 = NonNull::new(&mut arr2[0] as *mut i32);
633    /// let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
634    /// let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
635    /// unsafe {
636    ///     tagged1.copy_to_nonoverlapping(tagged2, 3);
637    /// }
638    /// assert_eq!(arr2, [1, 2, 3]);
639    /// ```
640    #[inline]
641    pub unsafe fn copy_to_nonoverlapping(self, dest: TaggedPtr<T>, count: usize) {
642        // Safety: The caller guarantees the pointers are valid.
643        unsafe { self.ptr.copy_to_nonoverlapping(dest.ptr, count) }
644    }
645
646    /// Copies `count` items from `src` to the pointer part of `self`. The regions may overlap.
647    ///
648    /// # Safety
649    ///
650    /// * Both pointers must be non-null.
651    /// * Both pointers must be valid for reads and writes.
652    /// * Both pointers must be properly aligned.
653    ///
654    /// # Examples
655    ///
656    /// ```rust
657    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
658    /// use std::ptr::NonNull;
659    ///
660    /// let mut arr = [1, 2, 3];
661    /// let ptr1 = NonNull::new(&mut arr[1] as *mut i32);
662    /// let ptr2 = NonNull::new(&mut arr[0] as *mut i32);
663    /// let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
664    /// let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
665    /// unsafe {
666    ///     tagged1.copy_from(tagged2, 2);
667    /// }
668    /// assert_eq!(arr, [1, 1, 2]);
669    /// ```
670    #[inline]
671    pub unsafe fn copy_from(self, src: TaggedPtr<T>, count: usize) {
672        // Safety: The caller guarantees the pointers are valid.
673        unsafe { self.ptr.copy_from(src.ptr, count) }
674    }
675
676    /// Copies `count` items from `src` to the pointer part of `self`. The regions must not overlap.
677    ///
678    /// # Safety
679    ///
680    /// * Both pointers must be non-null.
681    /// * Both pointers must be valid for reads and writes.
682    /// * Both pointers must be properly aligned.
683    /// * The memory regions must not overlap.
684    ///
685    /// # Examples
686    ///
687    /// ```rust
688    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
689    /// use std::ptr::NonNull;
690    ///
691    /// let mut arr1 = [1, 2, 3];
692    /// let mut arr2 = [0, 0, 0];
693    /// let ptr1 = NonNull::new(&mut arr2[0] as *mut i32);
694    /// let ptr2 = NonNull::new(&mut arr1[0] as *mut i32);
695    /// let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
696    /// let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
697    /// unsafe {
698    ///     tagged1.copy_from_nonoverlapping(tagged2, 3);
699    /// }
700    /// assert_eq!(arr2, [1, 2, 3]);
701    /// ```
702    #[inline]
703    pub unsafe fn copy_from_nonoverlapping(self, src: TaggedPtr<T>, count: usize) {
704        // Safety: The caller guarantees the pointers are valid.
705        unsafe { self.ptr.copy_from_nonoverlapping(src.ptr, count) }
706    }
707
708    /// Calculates the offset from the pointer part, returning a new `TaggedPtr` with the same tag.
709    ///
710    /// # Safety
711    ///
712    /// Both the starting and resulting pointer must be either in bounds or one byte past the end of the same allocated object.
713    ///
714    /// # Examples
715    ///
716    /// ```rust
717    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
718    /// use std::ptr::NonNull;
719    ///
720    /// let mut arr = [10, 20, 30];
721    /// let ptr = NonNull::new(&mut arr[0] as *mut i32);
722    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
723    /// unsafe {
724    ///     let offset_tagged = tagged.offset(1);
725    ///     assert_eq!(offset_tagged.read(), 20);
726    ///     assert_eq!(offset_tagged.tag.value(), 123);
727    /// }
728    /// ```
729    #[inline]
730    pub unsafe fn offset(self, count: isize) -> Self {
731        Self {
732            ptr: unsafe { self.ptr.offset(count) },
733            tag: self.tag,
734        }
735    }
736
737    /// Calculates the positive offset from the pointer part, returning a new `TaggedPtr` with the same tag.
738    ///
739    /// # Safety
740    ///
741    /// Both the starting and resulting pointer must be either in bounds or one byte past the end of the same allocated object.
742    ///
743    /// # Examples
744    ///
745    /// ```rust
746    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
747    /// use std::ptr::NonNull;
748    ///
749    /// let mut arr = [10, 20, 30];
750    /// let ptr = NonNull::new(&mut arr[0] as *mut i32);
751    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
752    /// unsafe {
753    ///     let offset_tagged = tagged.add(2);
754    ///     assert_eq!(offset_tagged.read(), 30);
755    ///     assert_eq!(offset_tagged.tag.value(), 123);
756    /// }
757    /// ```
758    #[inline]
759    pub unsafe fn add(self, count: usize) -> Self {
760        Self {
761            ptr: unsafe { self.ptr.add(count) },
762            tag: self.tag,
763        }
764    }
765
766    /// Calculates the negative offset from the pointer part, returning a new `TaggedPtr` with the same tag.
767    ///
768    /// # Safety
769    ///
770    /// Both the starting and resulting pointer must be either in bounds or one byte past the end of the same allocated object.
771    ///
772    /// # Examples
773    ///
774    /// ```rust
775    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
776    /// use std::ptr::NonNull;
777    ///
778    /// let mut arr = [10, 20, 30];
779    /// let ptr = NonNull::new(&mut arr[2] as *mut i32);
780    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
781    /// unsafe {
782    ///     let offset_tagged = tagged.sub(1);
783    ///     assert_eq!(offset_tagged.read(), 20);
784    ///     assert_eq!(offset_tagged.tag.value(), 123);
785    /// }
786    /// ```
787    #[inline]
788    pub unsafe fn sub(self, count: usize) -> Self {
789        Self {
790            ptr: unsafe { self.ptr.sub(count) },
791            tag: self.tag,
792        }
793    }
794
795    /// Calculates the wrapping offset from the pointer part, returning a new `TaggedPtr` with the same tag.
796    ///
797    /// # Examples
798    ///
799    /// ```rust
800    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
801    /// use std::ptr::NonNull;
802    ///
803    /// let mut arr = [10, 20, 30];
804    /// let ptr = NonNull::new(&mut arr[0] as *mut i32);
805    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
806    /// let offset_tagged = tagged.wrapping_offset(1);
807    /// assert_eq!(unsafe { offset_tagged.read() }, 20);
808    /// assert_eq!(offset_tagged.tag.value(), 123);
809    /// ```
810    #[inline]
811    pub fn wrapping_offset(self, count: isize) -> Self {
812        Self {
813            ptr: self.ptr.wrapping_offset(count),
814            tag: self.tag,
815        }
816    }
817
818    /// Calculates the positive wrapping offset from the pointer part, returning a new `TaggedPtr` with the same tag.
819    ///
820    /// # Examples
821    ///
822    /// ```rust
823    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
824    /// use std::ptr::NonNull;
825    ///
826    /// let mut arr = [10, 20, 30];
827    /// let ptr = NonNull::new(&mut arr[0] as *mut i32);
828    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
829    /// let offset_tagged = tagged.wrapping_add(2);
830    /// assert_eq!(unsafe { offset_tagged.read() }, 30);
831    /// assert_eq!(offset_tagged.tag.value(), 123);
832    /// ```
833    #[inline]
834    pub fn wrapping_add(self, count: usize) -> Self {
835        Self {
836            ptr: self.ptr.wrapping_add(count),
837            tag: self.tag,
838        }
839    }
840
841    /// Calculates the negative wrapping offset from the pointer part, returning a new `TaggedPtr` with the same tag.
842    ///
843    /// # Examples
844    ///
845    /// ```rust
846    /// use atomic_tagged_ptr::{TaggedPtr, Tag};
847    /// use std::ptr::NonNull;
848    ///
849    /// let mut arr = [10, 20, 30];
850    /// let ptr = NonNull::new(&mut arr[2] as *mut i32);
851    /// let tagged = TaggedPtr::new(ptr, Tag::new(123));
852    /// let offset_tagged = tagged.wrapping_sub(1);
853    /// assert_eq!(unsafe { offset_tagged.read() }, 20);
854    /// assert_eq!(offset_tagged.tag.value(), 123);
855    /// ```
856    #[inline]
857    pub fn wrapping_sub(self, count: usize) -> Self {
858        Self {
859            ptr: self.ptr.wrapping_sub(count),
860            tag: self.tag,
861        }
862    }
863}
864
865impl<T> fmt::Pointer for TaggedPtr<T> {
866    #[inline]
867    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
868        fmt::Pointer::fmt(&self.ptr, f)
869    }
870}
871
872impl<T> PartialOrd for TaggedPtr<T> {
873    #[inline]
874    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
875        Some(self.cmp(other))
876    }
877}
878
879impl<T> Ord for TaggedPtr<T> {
880    #[inline]
881    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
882        match self.ptr.cmp(&other.ptr) {
883            core::cmp::Ordering::Equal => self.tag.cmp(&other.tag),
884            ord => ord,
885        }
886    }
887}
888
889impl<T> From<TaggedPtr<T>> for *const T {
890    #[inline]
891    fn from(tagged: TaggedPtr<T>) -> Self {
892        tagged.as_ptr()
893    }
894}
895
896impl<T> From<TaggedPtr<T>> for *mut T {
897    #[inline]
898    fn from(tagged: TaggedPtr<T>) -> Self {
899        tagged.as_mut_ptr()
900    }
901}
902
903impl<T> fmt::Debug for TaggedPtr<T> {
904    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
905        f.debug_struct("TaggedPtr")
906            .field("ptr", &self.ptr)
907            .field("tag", &self.tag)
908            .finish()
909    }
910}
911
912impl<T> From<(Ptr<T>, crate::Tag)> for TaggedPtr<T> {
913    #[inline]
914    fn from(tuple: (Ptr<T>, crate::Tag)) -> Self {
915        Self {
916            ptr: tuple.0,
917            tag: tuple.1,
918        }
919    }
920}
921
922impl<T> From<(Option<NonNull<T>>, crate::Tag)> for TaggedPtr<T> {
923    #[inline]
924    fn from(tuple: (Option<NonNull<T>>, crate::Tag)) -> Self {
925        Self {
926            ptr: Ptr::new(tuple.0),
927            tag: tuple.1,
928        }
929    }
930}
931
932impl<T> From<(NonNull<T>, crate::Tag)> for TaggedPtr<T> {
933    #[inline]
934    fn from(tuple: (NonNull<T>, crate::Tag)) -> Self {
935        Self {
936            ptr: Ptr::from(tuple.0),
937            tag: tuple.1,
938        }
939    }
940}
941
942impl<T> From<(*const T, crate::Tag)> for TaggedPtr<T> {
943    #[inline]
944    fn from(tuple: (*const T, crate::Tag)) -> Self {
945        Self {
946            ptr: Ptr::from(tuple.0),
947            tag: tuple.1,
948        }
949    }
950}
951
952impl<T> From<(*mut T, crate::Tag)> for TaggedPtr<T> {
953    #[inline]
954    fn from(tuple: (*mut T, crate::Tag)) -> Self {
955        Self {
956            ptr: Ptr::from(tuple.0),
957            tag: tuple.1,
958        }
959    }
960}
961
962impl<T> From<TaggedPtr<T>> for (Ptr<T>, crate::Tag) {
963    #[inline]
964    fn from(tagged: TaggedPtr<T>) -> Self {
965        (tagged.ptr, tagged.tag)
966    }
967}
968
969impl<T> From<TaggedPtr<T>> for Option<NonNull<T>> {
970    #[inline]
971    fn from(tagged: TaggedPtr<T>) -> Self {
972        tagged.ptr.inner
973    }
974}
975
976impl<T> AsRef<Option<NonNull<T>>> for Ptr<T> {
977    #[inline]
978    fn as_ref(&self) -> &Option<NonNull<T>> {
979        &self.inner
980    }
981}
982
983impl<T> AsRef<Ptr<T>> for TaggedPtr<T> {
984    #[inline]
985    fn as_ref(&self) -> &Ptr<T> {
986        &self.ptr
987    }
988}
989
990impl<T> AsRef<crate::Tag> for TaggedPtr<T> {
991    #[inline]
992    fn as_ref(&self) -> &crate::Tag {
993        &self.tag
994    }
995}