arc-ext 0.1.0

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

mod arc;
mod option;

#[cfg(feature = "async-graphql")]
pub mod graphql;

pub use arc::ArcProject;
pub use option::ArcProjectOption;

pub trait ArcExt<T: ?Sized>: Unpin
where
    T: Unpin,
{
    fn project<'a, 'b, U, F>(self, deref_fn: F) -> ArcProject<'a, 'b, T, U>
    where
        'a: 'b,
        T: 'a,
        U: 'b,
        F: Fn(&'a Pin<Arc<T>>) -> &'b U;

    fn project_option<'a, 'b, U, F>(self, deref_fn: F) -> ArcProjectOption<'a, 'b, T, U>
    where
        'a: 'b,
        T: 'a,
        U: 'b,
        F: Fn(&'a Pin<Arc<T>>) -> Option<&'b U>;
}

impl<T: ?Sized + Unpin> ArcExt<T> for Arc<T> {
    fn project<'a, 'b, U, F>(self, deref_fn: F) -> ArcProject<'a, 'b, T, U>
    where
        'a: 'b,
        T: 'a,
        U: 'b,
        F: Fn(&'a Pin<Arc<T>>) -> &'b U,
    {
        ArcProject::new(self, deref_fn)
    }

    fn project_option<'a, 'b, U, F>(self, deref_fn: F) -> ArcProjectOption<'a, 'b, T, U>
    where
        'a: 'b,
        T: 'a,
        U: 'b,
        F: Fn(&'a Pin<Arc<T>>) -> Option<&'b U>,
    {
        ArcProjectOption::new(self, deref_fn)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[derive(Debug, PartialEq, Eq)]
    struct Top {
        nested: Nested,
        string: String,
    }

    #[derive(Debug, PartialEq, Eq)]
    struct Nested {
        a: u32,
        b: Box<[u8]>,
        c: Option<Arc<Top>>,
    }

    #[test]
    fn test() {
        let top = Arc::new(Top {
            nested: Nested {
                a: 32,
                b: vec![1, 2, 3, 4].into_boxed_slice(),
                c: Some(Arc::new(Top {
                    nested: Nested {
                        a: 12,
                        b: vec![99].into_boxed_slice(),
                        c: None,
                    },
                    string: "nested".to_string(),
                })),
            },
            string: "owned str".to_string(),
        });

        let project = top.clone().project(|x| &x.nested.b);
        assert_eq!(&[1, 2, 3, 4], &**project);
        drop(project);

        let project = top.clone().project_option(|x| x.nested.c.as_ref());
        let opt = project.as_option().unwrap();

        assert_eq!(top.nested.c.as_ref().unwrap(), opt);
    }
}