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!(<Self as Kind!( type Of<T>; )>::Of<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 OnceCell => () -> 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::functions::*;
38 /// use fp_library::brands::OnceCellBrand;
39 ///
40 /// let cell = once_new::<OnceCellBrand, i32>();
41 /// assert_eq!(once_get::<OnceCellBrand, _>(&cell), None);
42 /// ```
43 fn new<A>() -> <Self as Once>::Of<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 OnceCell => 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::functions::*;
71 /// use fp_library::brands::OnceCellBrand;
72 ///
73 /// let cell = once_new::<OnceCellBrand, i32>();
74 /// assert_eq!(once_get::<OnceCellBrand, _>(&cell), None);
75 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
76 /// assert_eq!(once_get::<OnceCellBrand, _>(&cell), Some(&42));
77 /// ```
78 fn get<A>(a: &<Self as Once>::Of<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 OnceCell => 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::functions::*;
106 /// use fp_library::brands::OnceCellBrand;
107 ///
108 /// let mut cell = once_new::<OnceCellBrand, i32>();
109 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
110 /// if let Some(val) = once_get_mut::<OnceCellBrand, _>(&mut cell) {
111 /// *val += 1;
112 /// }
113 /// assert_eq!(once_get_mut::<OnceCellBrand, _>(&mut cell), Some(&mut 43));
114 /// ```
115 fn get_mut<A>(a: &mut <Self as Once>::Of<A>) -> Option<&mut A> {
116 OnceCell::get_mut(a)
117 }
118
119 /// Sets the value of the container.
120 ///
121 /// This method attempts to set the value of the `OnceCell`. If the `OnceCell` is already initialized, it returns the value in the `Err` variant.
122 ///
123 /// ### Type Signature
124 ///
125 /// `forall a. Once OnceCell => (OnceCell a, a) -> Result<(), a>`
126 ///
127 /// ### Type Parameters
128 ///
129 /// * `A`: The type of the value to set.
130 ///
131 /// ### Parameters
132 ///
133 /// * `a`: The `OnceCell`.
134 /// * `value`: The value to set.
135 ///
136 /// ### Returns
137 ///
138 /// `Ok(())` on success, or `Err(value)` if already initialized.
139 ///
140 /// ### Examples
141 ///
142 /// ```
143 /// use fp_library::functions::*;
144 /// use fp_library::brands::OnceCellBrand;
145 ///
146 /// let cell = once_new::<OnceCellBrand, i32>();
147 /// assert!(once_set::<OnceCellBrand, _>(&cell, 42).is_ok());
148 /// assert!(once_set::<OnceCellBrand, _>(&cell, 10).is_err());
149 /// ```
150 fn set<A>(
151 a: &<Self as Once>::Of<A>,
152 value: A,
153 ) -> Result<(), A> {
154 OnceCell::set(a, value)
155 }
156
157 /// Gets the value, initializing it with the closure `f` if it is not already initialized.
158 ///
159 /// 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.
160 ///
161 /// ### Type Signature
162 ///
163 /// `forall a. Once OnceCell => (OnceCell a, () -> a) -> a`
164 ///
165 /// ### Type Parameters
166 ///
167 /// * `A`: The type of the value stored in the container.
168 /// * `B`: The type of the initialization function.
169 ///
170 /// ### Parameters
171 ///
172 /// * `a`: The `OnceCell`.
173 /// * `f`: The initialization function.
174 ///
175 /// ### Returns
176 ///
177 /// A reference to the value.
178 ///
179 /// ### Examples
180 ///
181 /// ```
182 /// use fp_library::functions::*;
183 /// use fp_library::brands::OnceCellBrand;
184 ///
185 /// let cell = once_new::<OnceCellBrand, i32>();
186 /// assert_eq!(*once_get_or_init::<OnceCellBrand, _, _>(&cell, || 42), 42);
187 /// assert_eq!(*once_get_or_init::<OnceCellBrand, _, _>(&cell, || 10), 42);
188 /// ```
189 fn get_or_init<A, B: FnOnce() -> A>(
190 a: &<Self as Once>::Of<A>,
191 f: B,
192 ) -> &A {
193 OnceCell::get_or_init(a, f)
194 }
195
196 /// Consumes the container and returns the value if it has been initialized.
197 ///
198 /// This method consumes the `OnceCell` and returns the value stored in it if it has been initialized, otherwise it returns `None`.
199 ///
200 /// ### Type Signature
201 ///
202 /// `forall a. Once OnceCell => OnceCell a -> Option a`
203 ///
204 /// ### Type Parameters
205 ///
206 /// * `A`: The type of the value stored in the container.
207 ///
208 /// ### Parameters
209 ///
210 /// * `a`: The `OnceCell`.
211 ///
212 /// ### Returns
213 ///
214 /// The value, or `None` if uninitialized.
215 ///
216 /// ### Examples
217 ///
218 /// ```
219 /// use fp_library::functions::*;
220 /// use fp_library::brands::OnceCellBrand;
221 ///
222 /// let cell = once_new::<OnceCellBrand, i32>();
223 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
224 /// assert_eq!(once_into_inner::<OnceCellBrand, _>(cell), Some(42));
225 /// ```
226 fn into_inner<A>(a: <Self as Once>::Of<A>) -> Option<A> {
227 OnceCell::into_inner(a)
228 }
229
230 /// Takes the value out of the container, leaving it uninitialized.
231 ///
232 /// 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`.
233 ///
234 /// ### Type Signature
235 ///
236 /// `forall a. Once OnceCell => OnceCell a -> Option a`
237 ///
238 /// ### Type Parameters
239 ///
240 /// * `A`: The type of the value stored in the container.
241 ///
242 /// ### Parameters
243 ///
244 /// * `a`: The `OnceCell`.
245 ///
246 /// ### Returns
247 ///
248 /// The value, or `None` if uninitialized.
249 ///
250 /// ### Examples
251 ///
252 /// ```
253 /// use fp_library::functions::*;
254 /// use fp_library::brands::OnceCellBrand;
255 ///
256 /// let mut cell = once_new::<OnceCellBrand, i32>();
257 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
258 /// assert_eq!(once_take::<OnceCellBrand, _>(&mut cell), Some(42));
259 /// assert_eq!(once_take::<OnceCellBrand, _>(&mut cell), None);
260 /// ```
261 fn take<A>(a: &mut <Self as Once>::Of<A>) -> Option<A> {
262 OnceCell::take(a)
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269 use crate::classes::once::Once;
270
271 /// Tests the `Once` trait implementation for `OnceCell`.
272 #[test]
273 fn test_once_cell() {
274 let mut cell = <OnceCellBrand as Once>::new::<i32>();
275 assert_eq!(<OnceCellBrand as Once>::get(&cell), None);
276
277 assert_eq!(<OnceCellBrand as Once>::set(&cell, 42), Ok(()));
278 assert_eq!(<OnceCellBrand as Once>::get(&cell), Some(&42));
279 assert_eq!(<OnceCellBrand as Once>::set(&cell, 100), Err(100));
280 assert_eq!(<OnceCellBrand as Once>::get(&cell), Some(&42));
281
282 let val = <OnceCellBrand as Once>::get_or_init(&cell, || 99);
283 assert_eq!(val, &42);
284
285 let cell2 = <OnceCellBrand as Once>::new::<i32>();
286 let val2 = <OnceCellBrand as Once>::get_or_init(&cell2, || 99);
287 assert_eq!(val2, &99);
288 assert_eq!(<OnceCellBrand as Once>::get(&cell2), Some(&99));
289
290 assert_eq!(<OnceCellBrand as Once>::take(&mut cell), Some(42));
291 assert_eq!(<OnceCellBrand as Once>::get(&cell), None);
292
293 assert_eq!(<OnceCellBrand as Once>::into_inner(cell2), Some(99));
294 }
295}