infinity_pool/handles/
blind_local.rs1use std::any::type_name;
2use std::borrow::Borrow;
3use std::cell::RefCell;
4use std::fmt;
5use std::ops::Deref;
6use std::pin::Pin;
7use std::ptr::NonNull;
8use std::rc::Rc;
9
10use crate::{LayoutKey, LocalBlindPoolCore, LocalBlindPooledMut, RawPooled, RawPooledMut};
11
12#[doc = include_str!("../../doc/snippets/ref_counted_handle_implications.md")]
14#[doc = include_str!("../../doc/snippets/shared_handle_implications.md")]
15pub struct LocalBlindPooled<T: ?Sized> {
20 inner: RawPooled<T>,
21
22 remover: Rc<Remover>,
27}
28
29impl<T: ?Sized> LocalBlindPooled<T> {
30 #[must_use]
31 pub(crate) fn new(inner: RawPooledMut<T>, key: LayoutKey, core: LocalBlindPoolCore) -> Self {
32 let inner = inner.into_shared();
33
34 let remover = Remover {
35 handle: unsafe { inner.erase_raw() },
37 key,
38 core,
39 };
40
41 Self {
42 inner,
43 remover: Rc::new(remover),
44 }
45 }
46
47 #[doc = include_str!("../../doc/snippets/handle_ptr.md")]
48 #[must_use]
49 #[inline]
50 #[cfg_attr(test, mutants::skip)] pub fn ptr(&self) -> NonNull<T> {
52 self.inner.ptr()
53 }
54
55 #[doc = include_str!("../../doc/snippets/ref_counted_as_pin.md")]
56 #[must_use]
57 #[inline]
58 #[cfg_attr(test, mutants::skip)] pub fn as_pin(&self) -> Pin<&T> {
60 unsafe { Pin::new_unchecked(self) }
62 }
63
64 #[doc(hidden)]
74 #[must_use]
75 #[inline]
76 pub unsafe fn __private_cast_dyn_with_fn<U: ?Sized, F>(self, cast_fn: F) -> LocalBlindPooled<U>
77 where
78 F: FnOnce(&T) -> &U,
79 {
80 let new_inner = unsafe { self.inner.__private_cast_dyn_with_fn(cast_fn) };
84
85 LocalBlindPooled {
86 inner: new_inner,
87 remover: self.remover,
88 }
89 }
90
91 #[must_use]
97 #[inline]
98 #[cfg_attr(test, mutants::skip)] pub fn erase(self) -> LocalBlindPooled<()> {
100 LocalBlindPooled {
101 inner: unsafe { self.inner.erase_raw() },
103 remover: self.remover,
104 }
105 }
106}
107
108#[cfg_attr(coverage_nightly, coverage(off))] impl<T: ?Sized> fmt::Debug for LocalBlindPooled<T> {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 f.debug_struct(type_name::<Self>())
112 .field("inner", &self.inner)
113 .field("remover", &self.remover)
114 .finish()
115 }
116}
117
118impl<T: ?Sized> Deref for LocalBlindPooled<T> {
119 type Target = T;
120
121 #[inline]
122 #[cfg_attr(test, mutants::skip)] fn deref(&self) -> &Self::Target {
124 unsafe { self.ptr().as_ref() }
128 }
129}
130
131impl<T: ?Sized> Borrow<T> for LocalBlindPooled<T> {
132 #[inline]
133 #[cfg_attr(test, mutants::skip)] fn borrow(&self) -> &T {
135 self
136 }
137}
138
139impl<T: ?Sized> AsRef<T> for LocalBlindPooled<T> {
140 #[inline]
141 #[cfg_attr(test, mutants::skip)] fn as_ref(&self) -> &T {
143 self
144 }
145}
146
147impl<T: ?Sized> Clone for LocalBlindPooled<T> {
148 #[inline]
149 fn clone(&self) -> Self {
150 Self {
151 inner: self.inner,
152 remover: Rc::clone(&self.remover),
153 }
154 }
155}
156
157impl<T: ?Sized> From<LocalBlindPooledMut<T>> for LocalBlindPooled<T> {
158 #[inline]
159 fn from(value: LocalBlindPooledMut<T>) -> Self {
160 value.into_shared()
161 }
162}
163
164#[derive(Debug)]
166struct Remover {
167 handle: RawPooled<()>,
168 key: LayoutKey,
169 core: LocalBlindPoolCore,
170}
171
172impl Drop for Remover {
173 fn drop(&mut self) {
174 let mut core = RefCell::borrow_mut(&self.core);
175
176 let pool = core
177 .get_mut(&self.key)
178 .expect("if the handle still exists, the inner pool must still exist");
179
180 unsafe {
184 pool.remove(self.handle);
185 }
186 }
187}
188
189#[cfg(test)]
190#[cfg_attr(coverage_nightly, coverage(off))]
191mod tests {
192 use static_assertions::{assert_impl_all, assert_not_impl_any};
193
194 use super::*;
195 use crate::{NotSendNotSync, NotSendSync, SendAndSync, SendNotSync};
196
197 assert_not_impl_any!(LocalBlindPooled<SendAndSync>: Send, Sync);
198 assert_not_impl_any!(LocalBlindPooled<SendNotSync>: Send, Sync);
199 assert_not_impl_any!(LocalBlindPooled<NotSendNotSync>: Send, Sync);
200 assert_not_impl_any!(LocalBlindPooled<NotSendSync>: Send, Sync);
201
202 assert_impl_all!(LocalBlindPooled<SendAndSync>: Clone);
204
205 assert_not_impl_any!(Remover: Send, Sync);
206
207 assert_impl_all!(Remover: Drop);
209}