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