fp_library/types/
once_lock.rs

1//! Implementations for [`OnceLock`]
2
3use crate::{
4	brands::OnceLockBrand,
5	classes::once::{ApplyOnce, Once},
6	hkt::{Apply0L1T, Kind0L1T},
7};
8use std::sync::OnceLock;
9
10impl Kind0L1T for OnceLockBrand {
11	type Output<A> = OnceLock<A>;
12}
13
14impl Once for OnceLockBrand {
15	type Output<A> = Apply0L1T<Self, A>;
16
17	/// Creates a new, uninitialized `OnceLock`.
18	///
19	/// # Type Signature
20	///
21	/// `forall a. Once OnceLockBrand => () -> OnceLock a`
22	///
23	/// # Returns
24	///
25	/// A new, empty `OnceLock`.
26	///
27	/// # Examples
28	///
29	/// ```
30	/// use fp_library::classes::once::Once;
31	/// use fp_library::brands::OnceLockBrand;
32	///
33	/// let cell = <OnceLockBrand as Once>::new::<i32>();
34	/// assert_eq!(<OnceLockBrand as Once>::get(&cell), None);
35	/// ```
36	fn new<A>() -> ApplyOnce<Self, A> {
37		OnceLock::new()
38	}
39
40	/// Gets a reference to the value if it has been initialized.
41	///
42	/// # Type Signature
43	///
44	/// `forall a. Once OnceLockBrand => OnceLock a -> Option a`
45	///
46	/// # Parameters
47	///
48	/// * `a`: The `OnceLock`.
49	///
50	/// # Returns
51	///
52	/// A reference to the value, or `None` if uninitialized.
53	fn get<A>(a: &ApplyOnce<Self, A>) -> Option<&A> {
54		OnceLock::get(a)
55	}
56
57	/// Gets a mutable reference to the value if it has been initialized.
58	///
59	/// # Type Signature
60	///
61	/// `forall a. Once OnceLockBrand => OnceLock a -> Option a`
62	///
63	/// # Parameters
64	///
65	/// * `a`: The `OnceLock`.
66	///
67	/// # Returns
68	///
69	/// A mutable reference to the value, or `None` if uninitialized.
70	fn get_mut<A>(a: &mut ApplyOnce<Self, A>) -> Option<&mut A> {
71		OnceLock::get_mut(a)
72	}
73
74	/// Sets the value of the `OnceLock`.
75	///
76	/// Returns `Ok(())` if the value was set, or `Err(value)` if the cell was already initialized.
77	///
78	/// # Type Signature
79	///
80	/// `forall a. Once OnceLockBrand => (OnceLock a, a) -> Result<(), a>`
81	///
82	/// # Parameters
83	///
84	/// * `a`: The `OnceLock`.
85	/// * `value`: The value to set.
86	///
87	/// # Returns
88	///
89	/// `Ok(())` on success, or `Err(value)` if already initialized.
90	fn set<A>(
91		a: &ApplyOnce<Self, A>,
92		value: A,
93	) -> Result<(), A> {
94		OnceLock::set(a, value)
95	}
96
97	/// Gets the value, initializing it with the closure `f` if it is not already initialized.
98	///
99	/// # Type Signature
100	///
101	/// `forall a. Once OnceLockBrand => (OnceLock a, () -> a) -> a`
102	///
103	/// # Parameters
104	///
105	/// * `a`: The `OnceLock`.
106	/// * `f`: The initialization function.
107	///
108	/// # Returns
109	///
110	/// A reference to the value.
111	fn get_or_init<A, B: FnOnce() -> A>(
112		a: &ApplyOnce<Self, A>,
113		f: B,
114	) -> &A {
115		OnceLock::get_or_init(a, f)
116	}
117
118	/// Consumes the `OnceLock` and returns the value if it has been initialized.
119	///
120	/// # Type Signature
121	///
122	/// `forall a. Once OnceLockBrand => OnceLock a -> Option a`
123	///
124	/// # Parameters
125	///
126	/// * `a`: The `OnceLock`.
127	///
128	/// # Returns
129	///
130	/// The value, or `None` if uninitialized.
131	fn into_inner<A>(a: ApplyOnce<Self, A>) -> Option<A> {
132		OnceLock::into_inner(a)
133	}
134
135	/// Takes the value out of the `OnceLock`, leaving it uninitialized.
136	///
137	/// # Type Signature
138	///
139	/// `forall a. Once OnceLockBrand => OnceLock a -> Option a`
140	///
141	/// # Parameters
142	///
143	/// * `a`: The `OnceLock`.
144	///
145	/// # Returns
146	///
147	/// The value, or `None` if uninitialized.
148	fn take<A>(a: &mut ApplyOnce<Self, A>) -> Option<A> {
149		OnceLock::take(a)
150	}
151}
152
153#[cfg(test)]
154mod tests {
155	use super::*;
156	use crate::classes::once::Once;
157
158	/// Tests the `Once` trait implementation for `OnceLock`.
159	#[test]
160	fn test_once_lock() {
161		let mut cell = <OnceLockBrand as Once>::new::<i32>();
162		assert_eq!(<OnceLockBrand as Once>::get(&cell), None);
163
164		assert_eq!(<OnceLockBrand as Once>::set(&cell, 42), Ok(()));
165		assert_eq!(<OnceLockBrand as Once>::get(&cell), Some(&42));
166		assert_eq!(<OnceLockBrand as Once>::set(&cell, 100), Err(100));
167		assert_eq!(<OnceLockBrand as Once>::get(&cell), Some(&42));
168
169		let val = <OnceLockBrand as Once>::get_or_init(&cell, || 99);
170		assert_eq!(val, &42);
171
172		let cell2 = <OnceLockBrand as Once>::new::<i32>();
173		let val2 = <OnceLockBrand as Once>::get_or_init(&cell2, || 99);
174		assert_eq!(val2, &99);
175		assert_eq!(<OnceLockBrand as Once>::get(&cell2), Some(&99));
176
177		assert_eq!(<OnceLockBrand as Once>::take(&mut cell), Some(42));
178		assert_eq!(<OnceLockBrand as Once>::get(&cell), None);
179
180		assert_eq!(<OnceLockBrand as Once>::into_inner(cell2), Some(99));
181	}
182}