fp_library/types/once_cell.rs
1//! OnceCell wrapper.
2//!
3//! This module defines the [`OnceCellBrand`] struct, which provides implementations for [`OnceCell`].
4//! It implements [`Once`].
5
6use crate::{Apply, brands::OnceCellBrand, classes::once::Once, impl_kind, kinds::*};
7use std::cell::OnceCell;
8
9impl_kind! {
10 for OnceCellBrand {
11 type Of<A> = OnceCell<A>;
12 }
13}
14
15impl Once for OnceCellBrand {
16 type Of<A> = Apply!(brand: Self, signature: (A));
17
18 /// Creates a new, uninitialized `Once` container.
19 ///
20 /// This method creates a new instance of the `OnceCell` that is initially empty.
21 ///
22 /// ### Type Signature
23 ///
24 /// `forall a. Once OnceCellBrand => () -> OnceCell a`
25 ///
26 /// ### Type Parameters
27 ///
28 /// * `A`: The type of the value to be stored in the container.
29 ///
30 /// ### Returns
31 ///
32 /// A new, empty `OnceCell`.
33 ///
34 /// ### Examples
35 ///
36 /// ```
37 /// use fp_library::classes::once::Once;
38 /// use fp_library::brands::OnceCellBrand;
39 ///
40 /// let cell = <OnceCellBrand as Once>::new::<i32>();
41 /// assert_eq!(<OnceCellBrand as Once>::get(&cell), None);
42 /// ```
43 fn new<A>() -> Apply!(brand: Self, kind: Once, lifetimes: (), types: (A)) {
44 OnceCell::new()
45 }
46
47 /// Gets a reference to the value if it has been initialized.
48 ///
49 /// This method returns a reference to the value stored in the `OnceCell` if it has been initialized, otherwise it returns `None`.
50 ///
51 /// ### Type Signature
52 ///
53 /// `forall a. Once OnceCellBrand => OnceCell a -> Option a`
54 ///
55 /// ### Type Parameters
56 ///
57 /// * `A`: The type of the value stored in the container.
58 ///
59 /// ### Parameters
60 ///
61 /// * `a`: The `OnceCell`.
62 ///
63 /// ### Returns
64 ///
65 /// A reference to the value, or `None` if uninitialized.
66 ///
67 /// ### Examples
68 ///
69 /// ```
70 /// use fp_library::classes::once::Once;
71 /// use fp_library::brands::OnceCellBrand;
72 ///
73 /// let cell = <OnceCellBrand as Once>::new::<i32>();
74 /// assert_eq!(<OnceCellBrand as Once>::get(&cell), None);
75 /// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
76 /// assert_eq!(<OnceCellBrand as Once>::get(&cell), Some(&42));
77 /// ```
78 fn get<A>(a: &Apply!(brand: Self, kind: Once, lifetimes: (), types: (A))) -> Option<&A> {
79 OnceCell::get(a)
80 }
81
82 /// Gets a mutable reference to the value if it has been initialized.
83 ///
84 /// This method returns a mutable reference to the value stored in the `OnceCell` if it has been initialized, otherwise it returns `None`.
85 ///
86 /// ### Type Signature
87 ///
88 /// `forall a. Once OnceCellBrand => OnceCell a -> Option a`
89 ///
90 /// ### Type Parameters
91 ///
92 /// * `A`: The type of the value stored in the container.
93 ///
94 /// ### Parameters
95 ///
96 /// * `a`: The `OnceCell`.
97 ///
98 /// ### Returns
99 ///
100 /// A mutable reference to the value, or `None` if uninitialized.
101 ///
102 /// ### Examples
103 ///
104 /// ```
105 /// use fp_library::classes::once::Once;
106 /// use fp_library::brands::OnceCellBrand;
107 ///
108 /// let mut cell = <OnceCellBrand as Once>::new::<i32>();
109 /// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
110 /// if let Some(val) = <OnceCellBrand as Once>::get_mut(&mut cell) {
111 /// *val += 1;
112 /// }
113 /// assert_eq!(<OnceCellBrand as Once>::get_mut(&mut cell), Some(&mut 43));
114 /// ```
115 fn get_mut<A>(
116 a: &mut Apply!(brand: Self, kind: Once, lifetimes: (), types: (A))
117 ) -> Option<&mut A> {
118 OnceCell::get_mut(a)
119 }
120
121 /// Sets the value of the container.
122 ///
123 /// This method attempts to set the value of the `OnceCell`. If the `OnceCell` is already initialized, it returns the value in the `Err` variant.
124 ///
125 /// ### Type Signature
126 ///
127 /// `forall a. Once OnceCellBrand => (OnceCell a, a) -> Result<(), a>`
128 ///
129 /// ### Type Parameters
130 ///
131 /// * `A`: The type of the value to set.
132 ///
133 /// ### Parameters
134 ///
135 /// * `a`: The `OnceCell`.
136 /// * `value`: The value to set.
137 ///
138 /// ### Returns
139 ///
140 /// `Ok(())` on success, or `Err(value)` if already initialized.
141 ///
142 /// ### Examples
143 ///
144 /// ```
145 /// use fp_library::classes::once::Once;
146 /// use fp_library::brands::OnceCellBrand;
147 ///
148 /// let cell = <OnceCellBrand as Once>::new::<i32>();
149 /// assert!(<OnceCellBrand as Once>::set(&cell, 42).is_ok());
150 /// assert!(<OnceCellBrand as Once>::set(&cell, 10).is_err());
151 /// ```
152 fn set<A>(
153 a: &Apply!(brand: Self, kind: Once, lifetimes: (), types: (A)),
154 value: A,
155 ) -> Result<(), A> {
156 OnceCell::set(a, value)
157 }
158
159 /// Gets the value, initializing it with the closure `f` if it is not already initialized.
160 ///
161 /// This method returns a reference to the value stored in the `OnceCell`. If the `OnceCell` is not initialized, it initializes it using the provided closure `f` and then returns a reference to the value.
162 ///
163 /// ### Type Signature
164 ///
165 /// `forall a. Once OnceCellBrand => (OnceCell a, () -> a) -> a`
166 ///
167 /// ### Type Parameters
168 ///
169 /// * `A`: The type of the value stored in the container.
170 /// * `B`: The type of the initialization function.
171 ///
172 /// ### Parameters
173 ///
174 /// * `a`: The `OnceCell`.
175 /// * `f`: The initialization function.
176 ///
177 /// ### Returns
178 ///
179 /// A reference to the value.
180 ///
181 /// ### Examples
182 ///
183 /// ```
184 /// use fp_library::classes::once::Once;
185 /// use fp_library::brands::OnceCellBrand;
186 ///
187 /// let cell = <OnceCellBrand as Once>::new::<i32>();
188 /// assert_eq!(*<OnceCellBrand as Once>::get_or_init(&cell, || 42), 42);
189 /// assert_eq!(*<OnceCellBrand as Once>::get_or_init(&cell, || 10), 42);
190 /// ```
191 fn get_or_init<A, B: FnOnce() -> A>(
192 a: &Apply!(brand: Self, kind: Once, lifetimes: (), types: (A)),
193 f: B,
194 ) -> &A {
195 OnceCell::get_or_init(a, f)
196 }
197
198 /// Consumes the container and returns the value if it has been initialized.
199 ///
200 /// This method consumes the `OnceCell` and returns the value stored in it if it has been initialized, otherwise it returns `None`.
201 ///
202 /// ### Type Signature
203 ///
204 /// `forall a. Once OnceCellBrand => OnceCell a -> Option a`
205 ///
206 /// ### Type Parameters
207 ///
208 /// * `A`: The type of the value stored in the container.
209 ///
210 /// ### Parameters
211 ///
212 /// * `a`: The `OnceCell`.
213 ///
214 /// ### Returns
215 ///
216 /// The value, or `None` if uninitialized.
217 ///
218 /// ### Examples
219 ///
220 /// ```
221 /// use fp_library::classes::once::Once;
222 /// use fp_library::brands::OnceCellBrand;
223 ///
224 /// let cell = <OnceCellBrand as Once>::new::<i32>();
225 /// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
226 /// assert_eq!(<OnceCellBrand as Once>::into_inner(cell), Some(42));
227 /// ```
228 fn into_inner<A>(a: Apply!(brand: Self, kind: Once, lifetimes: (), types: (A))) -> Option<A> {
229 OnceCell::into_inner(a)
230 }
231
232 /// Takes the value out of the container, leaving it uninitialized.
233 ///
234 /// This method takes the value out of the `OnceCell`, leaving the `OnceCell` in an uninitialized state. It returns the value if it was initialized, otherwise it returns `None`.
235 ///
236 /// ### Type Signature
237 ///
238 /// `forall a. Once OnceCellBrand => OnceCell a -> Option a`
239 ///
240 /// ### Type Parameters
241 ///
242 /// * `A`: The type of the value stored in the container.
243 ///
244 /// ### Parameters
245 ///
246 /// * `a`: The `OnceCell`.
247 ///
248 /// ### Returns
249 ///
250 /// The value, or `None` if uninitialized.
251 ///
252 /// ### Examples
253 ///
254 /// ```
255 /// use fp_library::classes::once::Once;
256 /// use fp_library::brands::OnceCellBrand;
257 ///
258 /// let mut cell = <OnceCellBrand as Once>::new::<i32>();
259 /// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
260 /// assert_eq!(<OnceCellBrand as Once>::take(&mut cell), Some(42));
261 /// assert_eq!(<OnceCellBrand as Once>::take(&mut cell), None);
262 /// ```
263 fn take<A>(a: &mut Apply!(brand: Self, kind: Once, lifetimes: (), types: (A))) -> Option<A> {
264 OnceCell::take(a)
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271 use crate::classes::once::Once;
272
273 /// Tests the `Once` trait implementation for `OnceCell`.
274 #[test]
275 fn test_once_cell() {
276 let mut cell = <OnceCellBrand as Once>::new::<i32>();
277 assert_eq!(<OnceCellBrand as Once>::get(&cell), None);
278
279 assert_eq!(<OnceCellBrand as Once>::set(&cell, 42), Ok(()));
280 assert_eq!(<OnceCellBrand as Once>::get(&cell), Some(&42));
281 assert_eq!(<OnceCellBrand as Once>::set(&cell, 100), Err(100));
282 assert_eq!(<OnceCellBrand as Once>::get(&cell), Some(&42));
283
284 let val = <OnceCellBrand as Once>::get_or_init(&cell, || 99);
285 assert_eq!(val, &42);
286
287 let cell2 = <OnceCellBrand as Once>::new::<i32>();
288 let val2 = <OnceCellBrand as Once>::get_or_init(&cell2, || 99);
289 assert_eq!(val2, &99);
290 assert_eq!(<OnceCellBrand as Once>::get(&cell2), Some(&99));
291
292 assert_eq!(<OnceCellBrand as Once>::take(&mut cell), Some(42));
293 assert_eq!(<OnceCellBrand as Once>::get(&cell), None);
294
295 assert_eq!(<OnceCellBrand as Once>::into_inner(cell2), Some(99));
296 }
297}