arc-ext 0.1.0

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

pub struct ArcProjectOption<'top, 'inner, T, U>
where
    'top: 'inner,
    T: ?Sized + Unpin,
    U: ?Sized,
{
    opt: Option<*const U>,
    inner: Pin<Arc<T>>,
    _lifetime: PhantomData<&'top &'inner ()>,
}

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

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

impl<'top, 'inner, T, U> ArcProjectOption<'top, 'inner, T, U>
where
    T: ?Sized + Unpin + 'top,
    U: ?Sized + 'inner,
{
    pub fn new<F: Fn(&'top Pin<Arc<T>>) -> Option<&'inner U>>(inner: Arc<T>, deref_fn: F) -> Self {
        let mut out = Self {
            opt: None,
            inner: Pin::new(inner),
            _lifetime: PhantomData,
        };

        out.opt = deref_fn(unsafe { std::mem::transmute(&out.inner) }).map(|x| x as _);
        out
    }

    pub fn as_option(&'top self) -> Option<&'inner U> {
        self.opt.map(|x| unsafe { &*x })
    }
}