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}