Skip to main content

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