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}