arc-ext 0.1.0

Extensions for Arc<T> such as field projection
Documentation
use std::{marker::PhantomData, ops::Deref, pin::Pin, sync::Arc};

pub struct ArcProject<'a, 'b, T, U>
where
    T: ?Sized + Unpin,
{
    value: *const U,
    inner: Pin<Arc<T>>,
    _lifetime: PhantomData<&'a &'b ()>,
}

unsafe impl<T, U> Send for ArcProject<'_, '_, T, U> where T: ?Sized + Unpin {}

unsafe impl<T, U> Sync for ArcProject<'_, '_, T, U> where T: ?Sized + Unpin {}

impl<'a, 'b, T, U> ArcProject<'a, 'b, T, U>
where
    'a: 'b,
    T: ?Sized + Unpin + 'a,
    U: 'b,
{
    pub fn new<F: Fn(&'a Pin<Arc<T>>) -> &'b U>(inner: Arc<T>, deref_fn: F) -> Self {
        let mut out = Self {
            value: std::ptr::null(),
            inner: Pin::new(inner),
            _lifetime: PhantomData,
        };

        out.value = deref_fn(unsafe { std::mem::transmute(&out.inner) });
        out
    }
}

impl<'a, 'b, T, U> Deref for ArcProject<'a, 'b, T, U>
where
    'a: 'b,
    T: ?Sized + Unpin + 'a,
    U: 'b,
{
    type Target = U;

    fn deref(&self) -> &'b Self::Target {
        unsafe { &*self.value }
    }
}