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}