fbl/ptr_traits.rs
1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::recyclable::Recyclable;
6use crate::ref_counted::HasRefCount;
7use crate::ref_ptr::RefPtr;
8use crate::unique_ptr::UniquePtr;
9use core::ops::Deref;
10use core::ptr::NonNull;
11
12/// Trait for pointer types that can be stored in intrusive containers.
13///
14/// # Safety
15///
16/// Implementing this trait is unsafe because the container relies on the correctness of
17/// the implementation to maintain memory safety:
18/// - `into_raw` must return a valid, non-null, and dereferenceable pointer to `Target` that
19/// uniquely identifies the object.
20/// - `from_raw` must correctly reconstruct a valid instance of `Self` from a pointer previously
21/// returned by `into_raw`.
22/// - `from_raw` must reclaim the ownership previously yielded by `into_raw`.
23/// - `get_ref` must return a valid reference to the `Target`.
24pub unsafe trait PtrTraits {
25 /// The type pointed to by this pointer.
26 type Target;
27 /// Whether the pointer type is managed (e.g., `UniquePtr` or `RefPtr`).
28 ///
29 /// If the pointer type is managed, containers can be dropped while they
30 /// are non-empty because the pointers can free the underlying memory. If
31 /// the pointer is not managed, then the containers need to be empty when
32 /// they are dropped to avoid memory leaks.
33 const IS_MANAGED: bool;
34 /// Consumes the pointer and returns a raw pointer to the target.
35 fn into_raw(self) -> *mut Self::Target;
36 /// Creates an instance of `Self` from a raw pointer.
37 ///
38 /// # Safety
39 ///
40 /// The caller must ensure that `raw` was returned by a previous call to
41 /// `into_raw` on an instance of `Self`, and that it has not been used to
42 /// create another instance of `Self`.
43 unsafe fn from_raw(raw: *mut Self::Target) -> Self;
44 /// Returns a reference to the target.
45 fn get_ref(&self) -> &Self::Target;
46}
47
48// SAFETY: `*mut T` behaves as a raw pointer with identity mapped into/from raw conversions.
49// It performs no lifecycle management and get_ref is safe if the pointer is valid.
50unsafe impl<T> PtrTraits for *mut T {
51 type Target = T;
52 const IS_MANAGED: bool = false;
53 fn into_raw(self) -> *mut T {
54 self
55 }
56 unsafe fn from_raw(raw: *mut T) -> Self {
57 raw
58 }
59 fn get_ref(&self) -> &T {
60 // SAFETY: The caller must ensure that `self` (which is `&(*mut T)`) points to a valid T.
61 unsafe { &**self }
62 }
63}
64
65// SAFETY: `NonNull<T>` behaves as a raw pointer with identity mapped into/from raw conversions.
66// It performs no lifecycle management and get_ref is safe if the pointer is valid.
67unsafe impl<T> PtrTraits for NonNull<T> {
68 type Target = T;
69 const IS_MANAGED: bool = false;
70 fn into_raw(self) -> *mut T {
71 self.as_ptr()
72 }
73 unsafe fn from_raw(raw: *mut T) -> Self {
74 // SAFETY: The caller of `from_raw` must ensure that `raw` was returned
75 // by a previous call to `into_raw` on an instance of `Self`. Since `into_raw`
76 // for `NonNull` always returns a non-null pointer, `raw` is guaranteed to be non-null.
77 unsafe { NonNull::new_unchecked(raw) }
78 }
79 fn get_ref(&self) -> &T {
80 // SAFETY: The caller must ensure that `self` points to a valid T.
81 unsafe { self.as_ref() }
82 }
83}
84
85// SAFETY: `UniquePtr<T>` owns the unique reference to `T`. Roundtrip between into_raw
86// and from_raw is guaranteed to preserve unique ownership and lifetimes.
87unsafe impl<T: Recyclable> PtrTraits for UniquePtr<T> {
88 type Target = T;
89 const IS_MANAGED: bool = true;
90 fn into_raw(self) -> *mut T {
91 UniquePtr::into_raw(self)
92 }
93 unsafe fn from_raw(raw: *mut T) -> Self {
94 // SAFETY: The caller of `from_raw` must ensure that `raw` was returned
95 // by a previous call to `into_raw` on an instance of `Self`, and that it
96 // has not been used to create another instance of `Self`.
97 unsafe { UniquePtr::from_raw(raw) }
98 }
99 fn get_ref(&self) -> &T {
100 self.deref()
101 }
102}
103
104// SAFETY: `RefPtr<T>` manages a shared atomic ref-count on `T`. Roundtrip between
105// into_raw and from_raw correctly transfers a single reference.
106unsafe impl<T: HasRefCount + Recyclable> PtrTraits for RefPtr<T> {
107 type Target = T;
108 const IS_MANAGED: bool = true;
109 fn into_raw(self) -> *mut T {
110 RefPtr::into_raw(self) as *mut T
111 }
112 unsafe fn from_raw(raw: *mut T) -> Self {
113 // SAFETY: The caller of `from_raw` must ensure that `raw` was returned
114 // by a previous call to `into_raw` on an instance of `Self`, and that it
115 // has not been used to create another instance of `Self`.
116 unsafe { RefPtr::from_raw(raw) }
117 }
118 fn get_ref(&self) -> &T {
119 self.deref()
120 }
121}
122
123/// Marker trait for managed pointer types (like `UniquePtr` and `RefPtr`).
124///
125/// # Safety
126///
127/// Implementing this trait is unsafe because:
128/// - The implementer must guarantee that the pointer type `P` actually manages the lifetime
129/// of its `Target` (i.e., it holds exclusive or shared ownership of the target).
130/// - Dropping the pointer `P` must correctly release the reference/ownership, causing the
131/// target to be dropped and cleaned up once there are no more owners.
132/// - The target object must be guaranteed to outlive its reference in the list while contained.
133pub unsafe trait ManagedPtr: PtrTraits {}
134
135// SAFETY: `UniquePtr<T>` uniquely manages `T`'s lifetime.
136unsafe impl<T: Recyclable> ManagedPtr for UniquePtr<T> {}
137// SAFETY: `RefPtr<T>` manages `T`'s lifetime via atomic reference counting.
138unsafe impl<T: HasRefCount + Recyclable> ManagedPtr for RefPtr<T> {}