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