share/
lib.rs

1
2use std::{borrow::Borrow, ops::Deref};
3
4/// Simple trait that can be implemented for any type via `shareable!` trait.
5pub trait Shareable<'a> {
6    /// Either `&'a Self` or `Self` when `Self` is `Copy`.
7    #[doc(hidden)]
8    type Shared: Copy + Borrow<Self> + 'a;
9
10    /// Share reference.
11    #[doc(hidden)]
12    fn share(&'a self) -> Self::Shared;
13}
14
15/// Shared value reference.
16/// It can store either reference or copy of the value.
17pub struct Share<'a, T: ?Sized + Shareable<'a>> {
18    shared: T::Shared,
19}
20
21impl<'a, T> Share<'a, T>
22where
23    T: ?Sized + Shareable<'a>,
24{
25    /// Construct new `Share` from reference.
26    pub fn new(reference: &'a T) -> Self {
27        Share {
28            shared: reference.share(),
29        }
30    }
31}
32
33impl<'a, T> Deref for Share<'a, T>
34where
35    T: ?Sized + Shareable<'a>,
36{
37    type Target = T;
38
39    fn deref(&self) -> &T {
40        self.shared.borrow()
41    }
42}
43
44/// References are share-by-copy.
45impl<'a, T> Shareable<'a> for &'a T
46where
47    T: 'a,
48{
49    type Shared = &'a T;
50    fn share(&'a self) -> &'a T {
51        *self
52    }
53}
54
55#[macro_export]
56macro_rules! shareable {
57    ($t:ty) => {
58        impl<'a> Shareable<'a> for $t {
59            type Shared = &'a $t;
60            fn share(&'a self) -> &'a $t {
61                self
62            }
63        }
64    };
65    ($t:ty: Copy) => {
66        impl<'a> Shareable<'a> for $t {
67            type Shared = $t;
68            fn share(&self) -> $t {
69                *self
70            }
71        }
72    };
73}
74
75
76
77#[test]
78fn copy() {
79    #[derive(Copy, Clone)]
80    struct Foo;
81    shareable!(Foo: Copy);
82
83    // Copy.
84    let _: Foo = Share::new(&Foo).shared;
85}
86
87
88#[test]
89fn reference() {
90    #[derive(Clone)]
91    struct Foo;
92    shareable!(Foo);
93
94    // Ref.
95    let _: &Foo = Share::new(&Foo).shared;
96}