Skip to main content

fbl/
recyclable.rs

1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7use core::ffi::c_void;
8use core::ptr::NonNull;
9use kalloc::AllocError;
10
11/// Trait for types that can be recycled (deallocated).
12///
13/// # Safety
14///
15/// Implementing this trait is unsafe because the implementer must ensure that:
16/// - `allocate`, if overridden, returns a valid pointer that can be safely deallocated by
17///   `recycle`.
18/// - `recycle` correctly deallocates the pointer and does not cause double-free or use-after-free.
19pub unsafe trait Recyclable: Sized {
20    /// Allocates a new instance of `Self`.
21    ///
22    /// The default implementation returns `Err(AllocError)`, which is appropriate for types
23    /// that cannot be allocated from Rust (e.g., C++ ref-counted objects).
24    fn allocate(_value: Self) -> Result<NonNull<Self>, AllocError> {
25        Err(AllocError)
26    }
27
28    /// Recycles the object.
29    ///
30    /// # Safety
31    ///
32    /// - The caller must ensure that `ptr` points to a valid, fully-initialized
33    ///   instance of `Self` that has no other references.
34    /// - The caller must not use the pointer or any references derived from it
35    ///   after this call.
36    unsafe fn recycle(ptr: NonNull<Self>);
37
38    /// Helper for FFI functions to call `recycle`.
39    ///
40    /// # Safety
41    ///
42    /// - The caller must ensure that `ptr` is valid and points to a valid object
43    ///   of type `Self` that has no other references.
44    /// - The caller must not use the pointer or any references derived from it
45    ///   after this call.
46    unsafe fn recycle_ffi(ptr: *mut c_void) {
47        // SAFETY: The caller of `recycle_ffi` must ensure that `ptr` is non-null
48        // and points to a valid `Self` that can be safely recycled.
49        unsafe {
50            Self::recycle(NonNull::new_unchecked(ptr as *mut Self));
51        }
52    }
53}
54
55/// Trait for types that can be allocated in an uninitialized state.
56///
57/// # Safety
58///
59/// Implementing this trait is unsafe because the implementer must ensure that:
60/// - `allocate_uninit` returns a valid pointer to uninitialized memory that can
61///   be safely deallocated by `recycle_uninit`.
62/// - `recycle_uninit` correctly deallocates the pointer without dropping the content
63///   (as it is uninitialized) and does not cause double-free or use-after-free.
64pub unsafe trait UninitRecyclable: Recyclable {
65    /// Allocates a new uninitialized instance of `Self`.
66    fn allocate_uninit() -> Result<NonNull<core::mem::MaybeUninit<Self>>, AllocError>;
67
68    /// Recycles an uninitialized object.
69    ///
70    /// # Safety
71    ///
72    /// - The caller must ensure that `ptr` points to a valid (but possibly uninitialized)
73    ///   instance of `Self` that has no other references.
74    /// - The caller must not use the pointer or any references derived from it
75    ///   after this call.
76    unsafe fn recycle_uninit(ptr: NonNull<core::mem::MaybeUninit<Self>>);
77}