fp_library/classes/ref_counted_pointer.rs
1//! A trait for reference-counted pointers with shared ownership.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::{brands::*, functions::*};
7//!
8//! let ptr = ref_counted_pointer_new::<RcBrand, _>(42);
9//! let clone = ptr.clone();
10//! assert_eq!(*clone, 42);
11//! ```
12
13use super::Pointer;
14use std::ops::Deref;
15
16/// Extension trait for reference-counted pointers with shared ownership.
17///
18/// Adds `CloneableOf` associated type which is Clone + Deref. This follows
19/// the pattern of `SendCloneableFn` adding `SendOf` to `CloneableFn`.
20pub trait RefCountedPointer: Pointer {
21 /// The cloneable pointer type constructor.
22 ///
23 /// For Rc/Arc, this is the same as `Of<T>`.
24 type CloneableOf<T: ?Sized>: Clone + Deref<Target = T>;
25
26 /// Wraps a sized value in a cloneable pointer.
27 ///
28 /// ### Type Signature
29 ///
30 /// `forall a. a -> RefCountedPointer a`
31 ///
32 /// ### Type Parameters
33 ///
34 /// * `T`: The type of the value to wrap.
35 ///
36 /// ### Parameters
37 ///
38 /// * `value`: The value to wrap.
39 ///
40 /// ### Returns
41 ///
42 /// The value wrapped in the cloneable pointer type.
43 ///
44 /// ### Examples
45 ///
46 /// ```
47 /// use fp_library::{brands::*, functions::*};
48 ///
49 /// let ptr = ref_counted_pointer_new::<RcBrand, _>(42);
50 /// assert_eq!(*ptr, 42);
51 /// ```
52 fn cloneable_new<T>(value: T) -> Self::CloneableOf<T>
53 where
54 Self::CloneableOf<T>: Sized;
55
56 /// Attempts to unwrap the inner value if this is the sole reference.
57 ///
58 /// ### Type Signature
59 ///
60 /// `forall a. RefCountedPointer a -> Result a (RefCountedPointer a)`
61 ///
62 /// ### Type Parameters
63 ///
64 /// * `T`: The type of the wrapped value.
65 ///
66 /// ### Parameters
67 ///
68 /// * `ptr`: The pointer to attempt to unwrap.
69 ///
70 /// ### Returns
71 ///
72 /// `Ok(value)` if this is the sole reference, otherwise `Err(ptr)`.
73 ///
74 /// ### Examples
75 ///
76 /// ```
77 /// use fp_library::{brands::*, functions::*};
78 ///
79 /// let ptr = ref_counted_pointer_new::<RcBrand, _>(42);
80 /// assert_eq!(try_unwrap::<RcBrand, _>(ptr), Ok(42));
81 ///
82 /// let ptr1 = ref_counted_pointer_new::<RcBrand, _>(42);
83 /// let ptr2 = ptr1.clone();
84 /// assert!(try_unwrap::<RcBrand, _>(ptr1).is_err());
85 /// ```
86 fn try_unwrap<T>(ptr: Self::CloneableOf<T>) -> Result<T, Self::CloneableOf<T>>;
87}
88
89/// Attempts to unwrap the inner value if this is the sole reference.
90///
91/// Free function version that dispatches to [the type class' associated function][`RefCountedPointer::try_unwrap`].
92///
93/// ### Type Signature
94///
95/// `forall a. RefCountedPointer a -> Result a (RefCountedPointer a)`
96///
97/// ### Type Parameters
98///
99/// * `P`: The pointer brand.
100/// * `T`: The type of the wrapped value.
101///
102/// ### Parameters
103///
104/// * `ptr`: The pointer to attempt to unwrap.
105///
106/// ### Returns
107///
108/// `Ok(value)` if this is the sole reference, otherwise `Err(ptr)`.
109///
110/// ### Examples
111///
112/// ```
113/// use fp_library::{brands::*, functions::*};
114///
115/// let ptr = ref_counted_pointer_new::<RcBrand, _>(42);
116/// assert_eq!(try_unwrap::<RcBrand, _>(ptr), Ok(42));
117///
118/// let ptr1 = ref_counted_pointer_new::<RcBrand, _>(42);
119/// let ptr2 = ptr1.clone();
120/// assert!(try_unwrap::<RcBrand, _>(ptr1).is_err());
121/// ```
122pub fn try_unwrap<P: RefCountedPointer, T>(ptr: P::CloneableOf<T>) -> Result<T, P::CloneableOf<T>> {
123 P::try_unwrap(ptr)
124}
125
126/// Wraps a sized value in a cloneable pointer.
127///
128/// ### Type Signature
129///
130/// `forall p a. RefCountedPointer p => a -> RefCountedPointer a`
131///
132/// ### Type Parameters
133///
134/// * `P`: The pointer brand.
135/// * `T`: The type of the value to wrap.
136///
137/// ### Parameters
138///
139/// * `value`: The value to wrap.
140///
141/// ### Returns
142///
143/// The value wrapped in the cloneable pointer type.
144///
145/// ### Examples
146///
147/// ```
148/// use fp_library::{brands::*, classes::*, functions::*};
149///
150/// let ptr = ref_counted_pointer_new::<RcBrand, _>(42);
151/// let clone = ptr.clone();
152/// assert_eq!(*clone, 42);
153/// ```
154pub fn cloneable_new<P: RefCountedPointer, T>(value: T) -> P::CloneableOf<T>
155where
156 P::CloneableOf<T>: Sized,
157{
158 P::cloneable_new(value)
159}