1use std::{marker::PhantomData, pin::Pin, sync::Arc};
2
3pub struct ArcProjectOption<'top, 'inner, T, U>
4where
5 'top: 'inner,
6 T: ?Sized + Unpin,
7 U: ?Sized,
8{
9 opt: Option<*const U>,
10 inner: Pin<Arc<T>>,
11 _lifetime: PhantomData<&'top &'inner ()>,
12}
13
14unsafe impl<T, U> Send for ArcProjectOption<'_, '_, T, U>
15where
16 T: ?Sized + Unpin,
17 U: ?Sized,
18{
19}
20
21unsafe impl<T, U> Sync for ArcProjectOption<'_, '_, T, U>
22where
23 T: ?Sized + Unpin,
24 U: ?Sized,
25{
26}
27
28impl<'top, 'inner, T, U> ArcProjectOption<'top, 'inner, T, U>
29where
30 T: ?Sized + Unpin + 'top,
31 U: ?Sized + 'inner,
32{
33 pub fn new<F: Fn(&'top Pin<Arc<T>>) -> Option<&'inner U>>(inner: Arc<T>, deref_fn: F) -> Self {
34 let mut out = Self {
35 opt: None,
36 inner: Pin::new(inner),
37 _lifetime: PhantomData,
38 };
39
40 out.opt = deref_fn(unsafe { std::mem::transmute(&out.inner) }).map(|x| x as _);
41 out
42 }
43
44 pub fn as_option(&'top self) -> Option<&'inner U> {
45 self.opt.map(|x| unsafe { &*x })
46 }
47}