1use std::sync::Arc;
2
3pub trait AsArc<T> {
4 #[allow(clippy::wrong_self_convention)]
5 fn as_arc(self) -> Arc<T>;
6}
7
8impl<T> AsArc<T> for Arc<T> {
9 fn as_arc(self) -> Arc<T> {
10 self
11 }
12}
13
14impl<T> AsArc<T> for &Arc<T> {
15 fn as_arc(self) -> Arc<T> {
16 self.clone()
17 }
18}
19
20impl<T> AsArc<T> for T {
21 fn as_arc(self) -> Arc<T> {
22 Arc::new(self)
23 }
24}
25
26impl<T: Clone> AsArc<T> for &T {
27 fn as_arc(self) -> Arc<T> {
28 Arc::new(self.clone())
29 }
30}
31
32impl<T> AsArc<T> for Box<T> {
33 fn as_arc(self) -> Arc<T> {
34 Arc::new(*self)
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[derive(Debug, PartialEq, Default)]
43 struct MyStruct(usize);
44
45 impl Clone for MyStruct {
46 fn clone(&self) -> Self {
47 Self(self.0 + 1)
48 }
49 }
50
51 #[test]
52 fn as_arc_should_only_clone_a_ref_of_arc() {
53 let before = Arc::new(MyStruct::default());
54
55 fn takes_impl(arg: impl AsArc<MyStruct>) -> Arc<MyStruct> {
56 arg.as_arc()
57 }
58
59 assert_eq!(
60 Arc::strong_count(&before),
61 1,
62 "Arc ref count should be 1 before passing value to takes_impl"
63 );
64 assert_eq!(
65 before.0, 0,
66 "Clone count should be 0 before passing value to takes_impl"
67 );
68
69 let referenced = takes_impl(&before);
70
71 assert_eq!(
72 Arc::strong_count(&referenced),
73 2,
74 "Arc ref count should be 2 after passing reference to takes_impl"
75 );
76 assert_eq!(
77 Arc::strong_count(&before),
78 2,
79 "Arc ref count should be 2 after passing reference to takes_impl"
80 );
81 assert_eq!(
82 referenced.0, 0,
83 "Clone count should be 0 after passing reference to takes_impl"
84 );
85 assert_eq!(
86 before.0, 0,
87 "Clone count should be 0 after passing reference to takes_impl"
88 );
89
90 let moved = takes_impl(before);
91
92 assert_eq!(
93 Arc::strong_count(&referenced),
94 2,
95 "Arc ref count should be 2 after moving value to takes_impl"
96 );
97 assert_eq!(
98 Arc::strong_count(&moved),
99 2,
100 "Arc ref count should be 2 after moving value to takes_impl"
101 );
102 assert_eq!(
103 referenced.0, 0,
104 "Clone count should be 0 after moving value to takes_impl"
105 );
106 assert_eq!(
107 moved.0, 0,
108 "Clone count should be 0 after moving value to takes_impl"
109 );
110 }
111
112 #[test]
113 fn as_arc_should_only_clone_a_ref_of_inner() {
114 let before = MyStruct::default();
115
116 fn takes_impl(arg: impl AsArc<MyStruct>) -> Arc<MyStruct> {
117 arg.as_arc()
118 }
119
120 assert_eq!(
121 before.0, 0,
122 "Clone count should be 0 before passing value to takes_impl"
123 );
124
125 let arc_from_ref = takes_impl(&before);
126
127 assert_eq!(
128 arc_from_ref.0, 1,
129 "Inner clone count of arc_from_ref should be 1 after passing reference to takes_impl"
130 );
131 assert_eq!(
132 before.0, 0,
133 "Clone count of before should still be 0 after passing reference to takes_impl"
134 );
135
136 let arc_from_moved = takes_impl(before);
137
138 assert_eq!(
139 arc_from_ref.0, 1,
140 "Inner clone count of arc_from_ref should still be 1 after moving original to takes_impl"
141 );
142 assert_eq!(
143 arc_from_moved.0, 0,
144 "Inner clone count of arc_from_moved should still be 0 after moving original to takes_impl"
145 );
146 }
147}