miden_utils_sync/
once_lock.rs1use core::fmt;
2#[cfg(feature = "std")]
3use std::sync::OnceLock;
4
5#[cfg(not(feature = "std"))]
6use once_cell::race::OnceBox;
7
8pub struct OnceLockCompat<T> {
23 #[cfg(feature = "std")]
24 inner: OnceLock<T>,
25 #[cfg(not(feature = "std"))]
26 inner: OnceBox<T>,
27}
28
29impl<T> OnceLockCompat<T> {
30 pub const fn new() -> Self {
32 #[cfg(feature = "std")]
33 {
34 Self { inner: OnceLock::new() }
35 }
36 #[cfg(not(feature = "std"))]
37 {
38 Self { inner: OnceBox::new() }
39 }
40 }
41
42 pub fn get(&self) -> Option<&T> {
44 #[cfg(feature = "std")]
45 {
46 self.inner.get()
47 }
48 #[cfg(not(feature = "std"))]
49 {
50 self.inner.get().map(|b| -> &T { b })
52 }
53 }
54
55 pub fn get_or_init<F>(&self, f: F) -> &T
60 where
61 F: FnOnce() -> T,
62 {
63 #[cfg(feature = "std")]
64 {
65 self.inner.get_or_init(f)
66 }
67 #[cfg(not(feature = "std"))]
68 {
69 let b: &T = self.inner.get_or_init(|| alloc::boxed::Box::new(f()));
71 b
72 }
73 }
74
75 pub fn reset(&mut self) {
84 #[cfg(feature = "std")]
85 {
86 self.inner = OnceLock::new();
87 }
88 #[cfg(not(feature = "std"))]
89 {
90 self.inner = OnceBox::new();
91 }
92 }
93}
94
95impl<T> Default for OnceLockCompat<T> {
96 fn default() -> Self {
97 Self::new()
98 }
99}
100
101impl<T: fmt::Debug> fmt::Debug for OnceLockCompat<T> {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 self.inner.fmt(f)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn new_is_empty() {
113 let lock: OnceLockCompat<u32> = OnceLockCompat::new();
114 assert!(lock.get().is_none());
115 }
116
117 #[test]
118 fn get_or_init_initializes() {
119 let lock: OnceLockCompat<u32> = OnceLockCompat::new();
120 let val = lock.get_or_init(|| 42);
121 assert_eq!(*val, 42);
122 assert_eq!(*lock.get().unwrap(), 42);
123 }
124
125 #[test]
126 fn reset_clears_value() {
127 let mut lock: OnceLockCompat<u32> = OnceLockCompat::new();
128 lock.get_or_init(|| 42);
129 assert!(lock.get().is_some());
130 lock.reset();
131 assert!(lock.get().is_none());
132 }
133
134 #[test]
135 fn get_or_init_after_reset() {
136 let mut lock: OnceLockCompat<u32> = OnceLockCompat::new();
137 lock.get_or_init(|| 1);
138 lock.reset();
139 let val = lock.get_or_init(|| 2);
140 assert_eq!(*val, 2);
141 }
142}