1macro_rules! any_impl {
4 ($dyn_any:ty) => {
5 const _: () = {
6 #[derive(Debug)]
7 pub struct __Vtable {
8 __drop_in_place: Option<unsafe fn(core::ptr::NonNull<()>)>,
9 __layout: core::alloc::Layout,
10 type_id: core::any::TypeId,
11 }
12
13 impl crate::object::DynTrait for $dyn_any {
14 type Vtable = __Vtable;
15 fn drop_in_place_fn(
16 vtable: &Self::Vtable,
17 ) -> Option<unsafe fn(core::ptr::NonNull<()>)> {
18 vtable.__drop_in_place
19 }
20 fn layout(vtable: &Self::Vtable) -> core::alloc::Layout {
21 vtable.__layout
22 }
23 }
24
25 unsafe impl<__Dyn: core::any::Any> crate::object::Vtable<__Dyn> for $dyn_any {
27 fn vtable<__Storage: crate::storage::Storage>() -> &'static Self::Vtable {
28 &const {
29 __Vtable {
30 __drop_in_place:
31 <Self as crate::object::Vtable<__Dyn>>::DROP_IN_PLACE_FN,
32 __layout: core::alloc::Layout::new::<__Dyn>(),
33 type_id: core::any::TypeId::of::<__Dyn>(),
34 }
35 }
36 }
37 }
38
39 impl<__Storage: crate::storage::Storage> crate::DynObject<$dyn_any, __Storage> {
40 pub fn type_id(&self) -> core::any::TypeId {
42 self.vtable().type_id
43 }
44
45 pub fn is<T: Any>(&self) -> bool {
47 self.type_id() == core::any::TypeId::of::<T>()
48 }
49
50 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
53 self.is::<T>().then(|| unsafe { self.storage().as_ref() })
55 }
56
57 pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
60 self.is::<T>()
61 .then(|| unsafe { self.storage_mut().as_mut() })
63 }
64
65 #[cfg_attr(coverage_nightly, coverage(off))]
68 pub fn downcast<T: Any>(self) -> Result<T, Self> {
69 if self.is::<T>() {
70 let mut this = core::mem::ManuallyDrop::new(self);
71 let storage = this.storage_mut();
72 let obj = unsafe { storage.ptr_mut().cast().read() };
74 unsafe {
77 __Storage::drop_in_place(storage, core::alloc::Layout::new::<T>())
78 };
79 Ok(obj)
80 } else {
81 Err(self)
82 }
83 }
84 }
85 };
86 };
87}
88pub(crate) use any_impl;
89
90#[cfg(test)]
91macro_rules! any_test {
92 ($test:ident, $dyn_any:ty) => {
93 #[test]
94 fn $test() {
95 struct Droppable;
96 impl Drop for Droppable {
97 fn drop(&mut self) {}
98 }
99 let mut any = crate::DynObject::<dyn Any>::new(false);
100 assert_eq!(any.downcast_ref::<()>(), None);
101 assert_eq!(any.downcast_ref::<bool>(), Some(&false));
102 assert_eq!(any.downcast_mut::<()>(), None);
103 *any.downcast_mut::<bool>().unwrap() = true;
104 let storage = any.downcast::<()>().unwrap_err();
105 assert!(storage.downcast::<bool>().unwrap());
106 drop(crate::DynObject::<dyn Any>::new(()));
107 drop(crate::DynObject::<dyn Any>::new(Droppable));
108 #[cfg(feature = "alloc")]
109 let _ = crate::DynObject::<dyn Any, crate::storage::Box>::new(false).downcast::<bool>();
110 }
111 };
112}
113#[cfg(test)]
114pub(crate) use any_test;
115
116const _: () = {
117 #[derive(Debug)]
118 pub struct __Vtable {
119 __drop_in_place: Option<unsafe fn(::core::ptr::NonNull<()>)>,
120 __layout: ::core::alloc::Layout,
121 poll: unsafe fn(),
122 }
123 impl<'__lt, __TypeOutput> crate::object::DynTrait for dyn Future<Output = __TypeOutput> + '__lt {
124 type Vtable = __Vtable;
125 fn drop_in_place_fn(vtable: &Self::Vtable) -> Option<unsafe fn(core::ptr::NonNull<()>)> {
126 vtable.__drop_in_place
127 }
128 fn layout(vtable: &Self::Vtable) -> core::alloc::Layout {
129 vtable.__layout
130 }
131 }
132 unsafe impl<'__lt, __TypeOutput, __Dyn: Future<Output = __TypeOutput> + '__lt>
134 crate::object::Vtable<__Dyn> for dyn Future<Output = __TypeOutput> + '__lt
135 {
136 fn vtable<__Storage: crate::storage::Storage>() -> &'static Self::Vtable {
137 &const {
138 __Vtable {
139 __drop_in_place: <Self as crate::object::Vtable<__Dyn>>::DROP_IN_PLACE_FN,
140 __layout: core::alloc::Layout::new::<__Dyn>(),
141 #[allow(
142 clippy::missing_transmute_annotations,
143 clippy::useless_transmute
144 )]
145 poll: unsafe {
148 ::core::mem::transmute::<
149 fn(
150 ::core::pin::Pin<&mut __Storage>,
151 &mut core::task::Context<'_>,
152 ) -> core::task::Poll<__Dyn::Output>,
153 unsafe fn(),
154 >(|__self, cx| {
155 ::core::mem::transmute(__Dyn::poll(
156 __self.as_pinned_mut(),
157 ::core::mem::transmute(cx),
158 ))
159 })
160 },
161 }
162 }
163 }
164 }
165 impl<'__lt, __TypeOutput, __Storage: crate::storage::Storage> Future
166 for crate::DynObject<dyn Future<Output = __TypeOutput> + '__lt, __Storage>
167 {
168 type Output = __TypeOutput;
169 fn poll(
170 self: core::pin::Pin<&mut Self>,
171 cx: &mut core::task::Context<'_>,
172 ) -> core::task::Poll<Self::Output> {
173 unsafe {
175 ::core::mem::transmute::<
176 unsafe fn(),
177 fn(
178 ::core::pin::Pin<&mut __Storage>,
179 &mut core::task::Context<'_>,
180 ) -> core::task::Poll<Self::Output>,
181 >(self.vtable().poll)(self.storage_pinned_mut(), cx)
182 }
183 }
184 }
185};
186const _: () = {
187 #[derive(Debug)]
188 pub struct __Vtable {
189 __drop_in_place: Option<unsafe fn(::core::ptr::NonNull<()>)>,
190 __layout: ::core::alloc::Layout,
191 poll: unsafe fn(),
192 }
193 impl<'__lt, __TypeOutput> crate::object::DynTrait
194 for dyn Future<Output = __TypeOutput> + '__lt + Send
195 {
196 type Vtable = __Vtable;
197 fn drop_in_place_fn(vtable: &Self::Vtable) -> Option<unsafe fn(core::ptr::NonNull<()>)> {
198 vtable.__drop_in_place
199 }
200 fn layout(vtable: &Self::Vtable) -> core::alloc::Layout {
201 vtable.__layout
202 }
203 }
204 unsafe impl<'__lt, __TypeOutput, __Dyn: Future<Output = __TypeOutput> + '__lt + Send>
206 crate::object::Vtable<__Dyn> for dyn Future<Output = __TypeOutput> + '__lt + Send
207 {
208 fn vtable<__Storage: crate::storage::Storage>() -> &'static Self::Vtable {
209 &const {
210 __Vtable {
211 __drop_in_place: <Self as crate::object::Vtable<__Dyn>>::DROP_IN_PLACE_FN,
212 __layout: core::alloc::Layout::new::<__Dyn>(),
213 #[allow(
214 clippy::missing_transmute_annotations,
215 clippy::useless_transmute
216 )]
217 poll: unsafe {
220 ::core::mem::transmute::<
221 fn(
222 ::core::pin::Pin<&mut __Storage>,
223 &mut core::task::Context<'_>,
224 ) -> core::task::Poll<__Dyn::Output>,
225 unsafe fn(),
226 >(|__self, cx| {
227 ::core::mem::transmute(__Dyn::poll(
228 __self.as_pinned_mut(),
229 ::core::mem::transmute(cx),
230 ))
231 })
232 },
233 }
234 }
235 }
236 }
237 impl<'__lt, __TypeOutput, __Storage: crate::storage::Storage> Future
238 for crate::DynObject<dyn Future<Output = __TypeOutput> + '__lt + Send, __Storage>
239 {
240 type Output = __TypeOutput;
241 fn poll(
242 self: core::pin::Pin<&mut Self>,
243 cx: &mut core::task::Context<'_>,
244 ) -> core::task::Poll<Self::Output> {
245 unsafe {
247 ::core::mem::transmute::<
248 unsafe fn(),
249 fn(
250 ::core::pin::Pin<&mut __Storage>,
251 &mut core::task::Context<'_>,
252 ) -> core::task::Poll<Self::Output>,
253 >(self.vtable().poll)(self.storage_pinned_mut(), cx)
254 }
255 }
256 }
257};
258
259const _: () = {
260 #[derive(Debug)]
261 pub struct __Vtable {
262 __drop_in_place: Option<unsafe fn(::core::ptr::NonNull<()>)>,
263 __layout: ::core::alloc::Layout,
264 next: unsafe fn(),
265 size_hint: unsafe fn(),
266 nth: unsafe fn(),
267 }
268 impl<'__lt, __TypeItem> crate::object::DynTrait for dyn Iterator<Item = __TypeItem> + '__lt {
269 type Vtable = __Vtable;
270 fn drop_in_place_fn(vtable: &Self::Vtable) -> Option<unsafe fn(core::ptr::NonNull<()>)> {
271 vtable.__drop_in_place
272 }
273 fn layout(vtable: &Self::Vtable) -> core::alloc::Layout {
274 vtable.__layout
275 }
276 }
277 unsafe impl<'__lt, __TypeItem, __Dyn: Iterator<Item = __TypeItem> + '__lt>
279 crate::object::Vtable<__Dyn> for dyn Iterator<Item = __TypeItem> + '__lt
280 {
281 fn vtable<__Storage: crate::storage::Storage>() -> &'static Self::Vtable {
282 &const {
283 __Vtable {
284 __drop_in_place: <Self as crate::object::Vtable<__Dyn>>::DROP_IN_PLACE_FN,
285 __layout: core::alloc::Layout::new::<__Dyn>(),
286 #[allow(
287 clippy::missing_transmute_annotations,
288 clippy::useless_transmute
289 )]
290 next: unsafe {
293 ::core::mem::transmute::<
294 fn(&mut __Storage) -> Option<__Dyn::Item>,
295 unsafe fn(),
296 >(|__self| {
297 ::core::mem::transmute(__Dyn::next(__self.as_mut()))
298 })
299 },
300 #[allow(
301 clippy::missing_transmute_annotations,
302 clippy::useless_transmute
303 )]
304 size_hint: unsafe {
307 ::core::mem::transmute::<
308 fn(&__Storage) -> (usize, Option<usize>),
309 unsafe fn(),
310 >(|__self| {
311 ::core::mem::transmute(__Dyn::size_hint(__self.as_ref()))
312 })
313 },
314 #[allow(
315 clippy::missing_transmute_annotations,
316 clippy::useless_transmute
317 )]
318 nth: unsafe {
321 ::core::mem::transmute::<
322 fn(&mut __Storage, usize) -> Option<__Dyn::Item>,
323 unsafe fn(),
324 >(|__self, n| {
325 ::core::mem::transmute(__Dyn::nth(
326 __self.as_mut(),
327 ::core::mem::transmute(n),
328 ))
329 })
330 },
331 }
332 }
333 }
334 }
335 impl<'__lt, __TypeItem, __Storage: crate::storage::Storage> Iterator
336 for crate::DynObject<dyn Iterator<Item = __TypeItem> + '__lt, __Storage>
337 {
338 type Item = __TypeItem;
339 fn next(&mut self) -> Option<Self::Item> {
340 unsafe {
342 ::core::mem::transmute::<unsafe fn(), fn(&mut __Storage) -> Option<Self::Item>>(
343 self.vtable().next,
344 )(self.storage_mut())
345 }
346 }
347 fn size_hint(&self) -> (usize, Option<usize>) {
348 unsafe {
350 ::core::mem::transmute::<unsafe fn(), fn(&__Storage) -> (usize, Option<usize>)>(
351 self.vtable().size_hint,
352 )(self.storage())
353 }
354 }
355 fn nth(&mut self, n: usize) -> Option<Self::Item> {
356 unsafe {
358 ::core::mem::transmute::<unsafe fn(), fn(&mut __Storage, usize) -> Option<Self::Item>>(
359 self.vtable().nth,
360 )(self.storage_mut(), n)
361 }
362 }
363 }
364};
365
366#[cfg_attr(coverage_nightly, coverage(off))]
367#[cfg(test)]
368mod tests {
369 use futures::FutureExt;
370
371 use crate::DynObject;
372
373 fn assert_send<T: Send>(_: &T) {}
374
375 #[test]
376 fn dyn_future() {
377 let n = 42;
378 let future = DynObject::<dyn Future<Output = usize>>::new(async { n });
379 assert_eq!(future.now_or_never(), Some(42));
380 }
381
382 #[test]
383 fn dyn_future_send() {
384 let n = 42;
385 let future = DynObject::<dyn Future<Output = usize> + Send>::new(async { n });
386 assert_send(&future);
387 assert_eq!(future.now_or_never(), Some(42));
388 }
389
390 #[test]
391 fn dyn_iterator() {
392 let mut iter = DynObject::<dyn Iterator<Item = usize>>::new([0, 1, 2, 3].into_iter());
393 assert_eq!(iter.size_hint(), (4, Some(4)));
394 assert_eq!(iter.nth(2), Some(2));
395 assert_eq!(iter.next(), Some(3));
396 }
397}