fp_library/types/arc_ptr.rs
1use crate::{
2 brands::ArcBrand,
3 classes::{
4 pointer::Pointer, ref_counted_pointer::RefCountedPointer,
5 send_ref_counted_pointer::SendRefCountedPointer,
6 send_unsized_coercible::SendUnsizedCoercible, unsized_coercible::UnsizedCoercible,
7 },
8};
9use std::sync::Arc;
10
11impl Pointer for ArcBrand {
12 type Of<T: ?Sized> = Arc<T>;
13
14 /// Wraps a sized value in an `Arc`.
15 ///
16 /// ### Type Signature
17 ///
18 /// `forall a. a -> Arc a`
19 ///
20 /// ### Type Parameters
21 ///
22 /// * `T`: The type of the value to wrap.
23 ///
24 /// ### Parameters
25 ///
26 /// * `value`: The value to wrap.
27 ///
28 /// ### Returns
29 ///
30 /// The value wrapped in an `Arc`.
31 ///
32 /// ### Examples
33 ///
34 /// ```
35 /// use fp_library::{brands::*, functions::*};
36 ///
37 /// let ptr = pointer_new::<ArcBrand, _>(42);
38 /// assert_eq!(*ptr, 42);
39 /// ```
40 fn new<T>(value: T) -> Arc<T> {
41 Arc::new(value)
42 }
43}
44
45impl RefCountedPointer for ArcBrand {
46 type CloneableOf<T: ?Sized> = Arc<T>;
47
48 /// Wraps a sized value in an `Arc`.
49 ///
50 /// ### Type Signature
51 ///
52 /// `forall a. a -> Arc a`
53 ///
54 /// ### Type Parameters
55 ///
56 /// * `T`: The type of the value to wrap.
57 ///
58 /// ### Parameters
59 ///
60 /// * `value`: The value to wrap.
61 ///
62 /// ### Returns
63 ///
64 /// The value wrapped in an `Arc`.
65 ///
66 /// ### Examples
67 ///
68 /// ```
69 /// use fp_library::{brands::*, functions::*};
70 ///
71 /// let ptr = ref_counted_pointer_new::<ArcBrand, _>(42);
72 /// assert_eq!(*ptr, 42);
73 /// ```
74 fn cloneable_new<T>(value: T) -> Arc<T> {
75 Arc::new(value)
76 }
77
78 /// Attempts to unwrap the inner value if this is the sole reference.
79 ///
80 /// ### Type Signature
81 ///
82 /// `forall a. Arc a -> Result a (Arc a)`
83 ///
84 /// ### Type Parameters
85 ///
86 /// * `T`: The type of the wrapped value.
87 ///
88 /// ### Parameters
89 ///
90 /// * `ptr`: The pointer to attempt to unwrap.
91 ///
92 /// ### Returns
93 ///
94 /// `Ok(value)` if this is the sole reference, otherwise `Err(ptr)`.
95 ///
96 /// ### Examples
97 ///
98 /// ```
99 /// use fp_library::{brands::*, functions::*};
100 ///
101 /// let ptr = ref_counted_pointer_new::<ArcBrand, _>(42);
102 /// assert_eq!(try_unwrap::<ArcBrand, _>(ptr), Ok(42));
103 /// ```
104 fn try_unwrap<T>(ptr: Arc<T>) -> Result<T, Arc<T>> {
105 Arc::try_unwrap(ptr)
106 }
107}
108
109impl SendRefCountedPointer for ArcBrand {
110 type SendOf<T: ?Sized + Send + Sync> = Arc<T>;
111
112 /// Wraps a sized value in an `Arc`.
113 ///
114 /// ### Type Signature
115 ///
116 /// `forall a. (Send a, Sync a) => a -> Arc a`
117 ///
118 /// ### Type Parameters
119 ///
120 /// * `T`: The type of the value to wrap.
121 ///
122 /// ### Parameters
123 ///
124 /// * `value`: The value to wrap.
125 ///
126 /// ### Returns
127 ///
128 /// The value wrapped in an `Arc`.
129 ///
130 /// ### Examples
131 ///
132 /// ```
133 /// use fp_library::{brands::*, functions::*};
134 ///
135 /// let ptr = send_ref_counted_pointer_new::<ArcBrand, _>(42);
136 /// assert_eq!(*ptr, 42);
137 /// ```
138 fn send_new<T: Send + Sync>(value: T) -> Arc<T> {
139 Arc::new(value)
140 }
141}
142
143impl UnsizedCoercible for ArcBrand {
144 /// Coerces a sized closure to a `dyn Fn` wrapped in an `Arc`.
145 ///
146 /// ### Type Signature
147 ///
148 /// `forall a b. (a -> b) -> Arc (dyn Fn a -> b)`
149 ///
150 /// ### Type Parameters
151 ///
152 /// * `A`: The input type of the function.
153 /// * `B`: The output type of the function.
154 ///
155 /// ### Parameters
156 ///
157 /// * `f`: The closure to coerce.
158 ///
159 /// ### Returns
160 ///
161 /// The closure wrapped in an `Arc` as a trait object.
162 ///
163 /// ### Examples
164 ///
165 /// ```
166 /// use fp_library::{brands::*, functions::*};
167 ///
168 /// let f = coerce_fn::<ArcBrand, _, _, _>(|x: i32| x + 1);
169 /// assert_eq!(f(1), 2);
170 /// ```
171 fn coerce_fn<'a, A, B>(f: impl 'a + Fn(A) -> B) -> Arc<dyn 'a + Fn(A) -> B> {
172 Arc::new(f)
173 }
174}
175
176impl SendUnsizedCoercible for ArcBrand {
177 /// Coerces a sized Send+Sync closure to a `dyn Fn + Send + Sync` wrapped in an `Arc`.
178 ///
179 /// ### Type Signature
180 ///
181 /// `forall a b. (Send (a -> b), Sync (a -> b)) => (a -> b) -> Arc (dyn Fn a -> b + Send + Sync)`
182 ///
183 /// ### Type Parameters
184 ///
185 /// * `A`: The input type of the function.
186 /// * `B`: The output type of the function.
187 ///
188 /// ### Parameters
189 ///
190 /// * `f`: The closure to coerce.
191 ///
192 /// ### Returns
193 ///
194 /// The closure wrapped in an `Arc` as a thread-safe trait object.
195 ///
196 /// ### Examples
197 ///
198 /// ```
199 /// use fp_library::{brands::*, functions::*};
200 ///
201 /// let f = coerce_send_fn::<ArcBrand, _, _, _>(|x: i32| x + 1);
202 /// assert_eq!(f(1), 2);
203 /// ```
204 fn coerce_send_fn<'a, A, B>(
205 f: impl 'a + Fn(A) -> B + Send + Sync
206 ) -> Arc<dyn 'a + Fn(A) -> B + Send + Sync> {
207 Arc::new(f)
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214 use crate::classes::{
215 pointer::new, ref_counted_pointer::cloneable_new, send_ref_counted_pointer::send_new,
216 };
217
218 /// Tests that `pointer_new` correctly creates an `Arc` wrapping the value.
219 #[test]
220 fn test_arc_new() {
221 let ptr = new::<ArcBrand, _>(42);
222 assert_eq!(*ptr, 42);
223 }
224
225 /// Tests that `ref_counted_pointer_new` correctly creates an `Arc` wrapping the value.
226 #[test]
227 fn test_arc_cloneable_new() {
228 let ptr = cloneable_new::<ArcBrand, _>(42);
229 assert_eq!(*ptr, 42);
230 }
231
232 /// Tests that `send_ref_counted_pointer_new` correctly creates an `Arc` wrapping the value.
233 #[test]
234 fn test_arc_send_new() {
235 let ptr = send_new::<ArcBrand, _>(42);
236 assert_eq!(*ptr, 42);
237 }
238
239 /// Tests that cloning the pointer works as expected (shared ownership).
240 #[test]
241 fn test_arc_clone() {
242 let ptr = cloneable_new::<ArcBrand, _>(42);
243 let clone = ptr.clone();
244 assert_eq!(*clone, 42);
245 }
246
247 /// Tests `try_unwrap` behavior:
248 /// - Returns `Ok(value)` when there is only one reference.
249 /// - Returns `Err(ptr)` when there are multiple references.
250 #[test]
251 fn test_arc_try_unwrap() {
252 let ptr = cloneable_new::<ArcBrand, _>(42);
253 assert_eq!(ArcBrand::try_unwrap(ptr), Ok(42));
254
255 let ptr = cloneable_new::<ArcBrand, _>(42);
256 let _clone = ptr.clone();
257 assert!(ArcBrand::try_unwrap(ptr).is_err());
258 }
259}