arc_ext/
lib.rs

1use std::{pin::Pin, sync::Arc};
2
3mod arc;
4mod option;
5
6#[cfg(feature = "async-graphql")]
7pub mod graphql;
8
9pub use arc::ArcProject;
10pub use option::ArcProjectOption;
11
12pub trait ArcExt<T: ?Sized>: Unpin
13where
14    T: Unpin,
15{
16    fn project<'a, 'b, U, F>(self, deref_fn: F) -> ArcProject<'a, 'b, T, U>
17    where
18        'a: 'b,
19        T: 'a,
20        U: 'b,
21        F: Fn(&'a Pin<Arc<T>>) -> &'b U;
22
23    fn project_option<'a, 'b, U, F>(self, deref_fn: F) -> ArcProjectOption<'a, 'b, T, U>
24    where
25        'a: 'b,
26        T: 'a,
27        U: 'b,
28        F: Fn(&'a Pin<Arc<T>>) -> Option<&'b U>;
29}
30
31impl<T: ?Sized + Unpin> ArcExt<T> for Arc<T> {
32    fn project<'a, 'b, U, F>(self, deref_fn: F) -> ArcProject<'a, 'b, T, U>
33    where
34        'a: 'b,
35        T: 'a,
36        U: 'b,
37        F: Fn(&'a Pin<Arc<T>>) -> &'b U,
38    {
39        ArcProject::new(self, deref_fn)
40    }
41
42    fn project_option<'a, 'b, U, F>(self, deref_fn: F) -> ArcProjectOption<'a, 'b, T, U>
43    where
44        'a: 'b,
45        T: 'a,
46        U: 'b,
47        F: Fn(&'a Pin<Arc<T>>) -> Option<&'b U>,
48    {
49        ArcProjectOption::new(self, deref_fn)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[derive(Debug, PartialEq, Eq)]
58    struct Top {
59        nested: Nested,
60        string: String,
61    }
62
63    #[derive(Debug, PartialEq, Eq)]
64    struct Nested {
65        a: u32,
66        b: Box<[u8]>,
67        c: Option<Arc<Top>>,
68    }
69
70    #[test]
71    fn test() {
72        let top = Arc::new(Top {
73            nested: Nested {
74                a: 32,
75                b: vec![1, 2, 3, 4].into_boxed_slice(),
76                c: Some(Arc::new(Top {
77                    nested: Nested {
78                        a: 12,
79                        b: vec![99].into_boxed_slice(),
80                        c: None,
81                    },
82                    string: "nested".to_string(),
83                })),
84            },
85            string: "owned str".to_string(),
86        });
87
88        let project = top.clone().project(|x| &x.nested.b);
89        assert_eq!(&[1, 2, 3, 4], &**project);
90        drop(project);
91
92        let project = top.clone().project_option(|x| x.nested.c.as_ref());
93        let opt = project.as_option().unwrap();
94
95        assert_eq!(top.nested.c.as_ref().unwrap(), opt);
96    }
97}