arc_ext/
option.rs

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}