anchored_pool/
pooled_resource.rs

1#![expect(unsafe_code, reason = "let unsafe code in Pools rely on PooledResource Drop impl")]
2
3use std::mem::ManuallyDrop;
4use std::{
5    borrow::{Borrow, BorrowMut},
6    fmt::{Debug, Formatter, Result as FmtResult},
7    ops::{Deref, DerefMut},
8};
9
10
11pub(crate) trait SealedPool<Resource> {
12    type Returner;
13
14    /// Used by [`PooledResource`] to return a `Resource` to a pool.
15    ///
16    /// # Safety
17    /// Must be called at most once in the `Drop` impl of a `PooledResource` constructed
18    /// via `PooledResource::new`, where `*returner` must be the `returner` value passed to
19    /// `PooledResource::new`.
20    unsafe fn return_resource(returner: &Self::Returner, resource: Resource);
21}
22
23pub(crate) trait SealedBufferPool {
24    type InnerPool: SealedPool<Vec<u8>>;
25}
26
27/// A handle to `Resource` in a pool, which returns the `Resource` back to the pool when dropped.
28#[expect(private_bounds, reason = "sealed")]
29#[derive(Debug)]
30pub struct PooledResource<Pool: SealedPool<Resource>, Resource> {
31    /// Must not be mutated after construction
32    returner:   Pool::Returner,
33    resource:   ManuallyDrop<Resource>,
34}
35
36#[expect(private_bounds, reason = "sealed")]
37impl<Pool: SealedPool<Resource>, Resource> PooledResource<Pool, Resource> {
38    /// Create a new `PooledResource` that provides mutable access to a `Resource`, and returns
39    /// that `Resource` to a `Pool` once dropped.
40    ///
41    /// # Safety
42    /// It must be safe to call `pool.return_resource(pool_slot, any_resource)` one time in the
43    /// `Drop` impl of this `PooledResource` struct, where `pool` and `pool_slot` are the values
44    /// passed here, and `any_resource` is any `Resource` value.
45    #[expect(clippy::missing_const_for_fn, reason = "no reason to promise const-ness")]
46    #[inline]
47    #[must_use]
48    pub(crate) unsafe fn new(returner: Pool::Returner, resource: Resource) -> Self {
49        Self {
50            returner,
51            resource: ManuallyDrop::new(resource),
52        }
53    }
54}
55
56impl<Pool: SealedPool<Resource>, Resource> Drop for PooledResource<Pool, Resource> {
57    fn drop(&mut self) {
58        // SAFETY:
59        // We must never again use the `ManuallyDrop` value. This is the destructor of the type,
60        // and the pool has no reference to the internal data of the `PooledResource`, so nothing
61        // can touch `self.resource` after this line.
62        let resource = unsafe { ManuallyDrop::take(&mut self.resource) };
63        // SAFETY:
64        // We call the method at most once in the way described by `Self::new`, which is the only
65        // way to construct this type. By the safety contract of `Self::new`, this is safe.
66        unsafe { Pool::return_resource(&self.returner, resource); }
67    }
68}
69
70impl<Pool: SealedPool<Resource>, Resource> Deref for PooledResource<Pool, Resource> {
71    type Target = Resource;
72
73    #[inline]
74    fn deref(&self) -> &Self::Target {
75        &self.resource
76    }
77}
78
79impl<Pool: SealedPool<Resource>, Resource> DerefMut for PooledResource<Pool, Resource> {
80    #[inline]
81    fn deref_mut(&mut self) -> &mut Self::Target {
82        &mut self.resource
83    }
84}
85
86impl<Pool: SealedPool<Resource>, Resource> Borrow<Resource> for PooledResource<Pool, Resource> {
87    #[inline]
88    fn borrow(&self) -> &Resource {
89        self
90    }
91}
92
93impl<Pool: SealedPool<Resource>, Resource> BorrowMut<Resource> for PooledResource<Pool, Resource> {
94    #[inline]
95    fn borrow_mut(&mut self) -> &mut Resource {
96        self
97    }
98}
99
100impl<Pool: SealedPool<Resource>, Resource> AsRef<Resource> for PooledResource<Pool, Resource> {
101    #[inline]
102    fn as_ref(&self) -> &Resource {
103        self
104    }
105}
106
107impl<Pool: SealedPool<Resource>, Resource> AsMut<Resource> for PooledResource<Pool, Resource> {
108    #[inline]
109    fn as_mut(&mut self) -> &mut Resource {
110        self
111    }
112}
113
114/// A handle to a buffer in a pool, which returns the buffer back to the pool when dropped.
115#[expect(private_bounds, reason = "sealed")]
116pub struct PooledBuffer<Pool: SealedBufferPool>(PooledResource<Pool::InnerPool, Vec<u8>>);
117
118#[expect(private_bounds, reason = "sealed")]
119impl<Pool: SealedBufferPool> PooledBuffer<Pool> {
120    #[inline]
121    #[must_use]
122    pub(crate) const fn new(inner: PooledResource<Pool::InnerPool, Vec<u8>>) -> Self {
123        Self(inner)
124    }
125}
126
127impl<Pool: SealedBufferPool> Debug for PooledBuffer<Pool> {
128    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
129        f.debug_tuple("PooledBuffer")
130            .field(&format!("<buffer of length {} and capacity {}>", self.len(), self.capacity()))
131            .finish()
132    }
133}
134
135impl<Pool: SealedBufferPool> Deref for PooledBuffer<Pool> {
136    type Target = Vec<u8>;
137
138    #[inline]
139    fn deref(&self) -> &Self::Target {
140        &self.0
141    }
142}
143
144impl<Pool: SealedBufferPool> DerefMut for PooledBuffer<Pool> {
145    #[inline]
146    fn deref_mut(&mut self) -> &mut Self::Target {
147        &mut self.0
148    }
149}
150
151impl<Pool: SealedBufferPool> Borrow<Vec<u8>> for PooledBuffer<Pool> {
152    #[inline]
153    fn borrow(&self) -> &Vec<u8> {
154        self
155    }
156}
157
158impl<Pool: SealedBufferPool> BorrowMut<Vec<u8>> for PooledBuffer<Pool> {
159    #[inline]
160    fn borrow_mut(&mut self) -> &mut Vec<u8> {
161        self
162    }
163}
164
165impl<Pool: SealedBufferPool> AsRef<Vec<u8>> for PooledBuffer<Pool> {
166    #[inline]
167    fn as_ref(&self) -> &Vec<u8> {
168        self
169    }
170}
171
172impl<Pool: SealedBufferPool> AsMut<Vec<u8>> for PooledBuffer<Pool> {
173    #[inline]
174    fn as_mut(&mut self) -> &mut Vec<u8> {
175        self
176    }
177}