1use core::fmt::Debug;
19use core::hash::Hash;
20use core::marker::PhantomData;
21use core::mem::MaybeUninit;
22use core::ops::{Deref, DerefMut};
23use core::ptr::addr_of_mut;
24
25use super::init;
26
27#[derive(Debug)]
41pub struct Maybe<T, G = ()> {
42 some: bool,
43 value: MaybeUninit<T>,
44 _tag: PhantomData<G>,
45}
46
47impl<T, G> Maybe<T, G> {
48 pub fn new(value: Option<T>) -> Self {
53 match value {
54 Some(v) => Self::some(v),
55 None => Self::none(),
56 }
57 }
58
59 pub const fn none() -> Self {
61 Self {
62 some: false,
63 value: MaybeUninit::uninit(),
64 _tag: PhantomData,
65 }
66 }
67
68 pub const fn some(value: T) -> Self {
70 Self {
71 some: true,
72 value: MaybeUninit::new(value),
73 _tag: PhantomData,
74 }
75 }
76
77 pub fn init_none() -> impl init::Init<Self> {
79 unsafe {
80 init::init_from_closure(move |slot: *mut Self| {
81 addr_of_mut!((*slot).some).write(false);
82
83 Ok(())
84 })
85 }
86 }
87
88 pub fn init_some<I: init::Init<T, E>, E>(value: I) -> impl init::Init<Self, E> {
91 Self::init(Some(value))
92 }
93
94 pub fn init<I: init::Init<T, E>, E>(value: Option<I>) -> impl init::Init<Self, E> {
97 unsafe {
98 init::init_from_closure(move |slot: *mut Self| {
99 let some = value.is_some();
100
101 if let Some(value) = value {
102 value.__init(addr_of_mut!((*slot).value) as _)?;
103 }
104
105 addr_of_mut!((*slot).some).write(some);
107
108 Ok(())
109 })
110 }
111 }
112
113 pub fn clear(&mut self) {
115 if self.some {
116 unsafe {
117 let slot = addr_of_mut!(*self);
118
119 addr_of_mut!((*slot).some).write(false);
120
121 let value = addr_of_mut!((*slot).value) as *mut T;
122
123 core::ptr::drop_in_place(value);
124 }
125 }
126 }
127
128 pub fn reinit<I: init::Init<Self>>(&mut self, value: I) {
130 unwrap!(Self::try_reinit(self, value));
132 }
133
134 pub fn try_reinit<I: init::Init<Self, E>, E>(&mut self, value: I) -> Result<(), E> {
138 self.clear();
139
140 unsafe {
141 let slot = addr_of_mut!(*self);
142
143 value.__init(slot)
144 }
145 }
146
147 pub fn as_mut(&mut self) -> Maybe<&mut T, G> {
149 if self.some {
150 Maybe::some(unsafe { self.value.assume_init_mut() })
151 } else {
152 Maybe::none()
153 }
154 }
155
156 pub fn as_ref(&self) -> Maybe<&T, G> {
158 if self.some {
159 Maybe::some(unsafe { self.value.assume_init_ref() })
160 } else {
161 Maybe::none()
162 }
163 }
164
165 pub fn as_opt_mut(&mut self) -> Option<&mut T> {
167 if self.some {
168 Some(unsafe { self.value.assume_init_mut() })
169 } else {
170 None
171 }
172 }
173
174 pub fn as_opt_ref(&self) -> Option<&T> {
176 if self.some {
177 Some(unsafe { self.value.assume_init_ref() })
178 } else {
179 None
180 }
181 }
182
183 pub fn as_deref(&self) -> Maybe<&T::Target, G>
185 where
186 T: Deref,
187 {
188 match self.as_opt_ref() {
189 Some(t) => Maybe::some(t.deref()),
190 None => Maybe::none(),
191 }
192 }
193
194 pub fn as_deref_mut(&mut self) -> Maybe<&mut T::Target, G>
196 where
197 T: DerefMut,
198 {
199 match self.as_opt_mut() {
200 Some(t) => Maybe::some(t.deref_mut()),
201 None => Maybe::none(),
202 }
203 }
204
205 pub fn as_opt_deref(&self) -> Option<&T::Target>
207 where
208 T: Deref,
209 {
210 match self.as_opt_ref() {
211 Some(t) => Some(t.deref()),
212 None => None,
213 }
214 }
215
216 pub fn as_opt_deref_mut(&mut self) -> Option<&mut T::Target>
218 where
219 T: DerefMut,
220 {
221 match self.as_opt_mut() {
222 Some(t) => Some(t.deref_mut()),
223 None => None,
224 }
225 }
226
227 pub fn into_option(mut self) -> Option<T> {
233 if !self.some {
234 return None;
235 }
236
237 Some(unsafe {
238 let slot = addr_of_mut!(self);
239
240 let ret = core::ptr::read(addr_of_mut!((*slot).value) as *mut _);
241
242 self.some = false;
244
245 ret
246 })
247 }
248
249 pub fn is_none(&self) -> bool {
251 !self.some
252 }
253
254 pub fn is_some(&self) -> bool {
256 self.some
257 }
258}
259
260impl<T, G> Drop for Maybe<T, G> {
261 fn drop(&mut self) {
262 self.clear();
266 }
267}
268
269impl<T, G> Default for Maybe<T, G> {
270 fn default() -> Self {
271 Self::none()
272 }
273}
274
275impl<T, G> From<Option<T>> for Maybe<T, G> {
276 fn from(value: Option<T>) -> Self {
277 Self::new(value)
278 }
279}
280
281impl<T, G> From<Maybe<T, G>> for Option<T> {
282 fn from(value: Maybe<T, G>) -> Self {
283 value.into_option()
284 }
285}
286
287impl<T, G> Clone for Maybe<T, G>
288where
289 T: Clone,
290{
291 fn clone(&self) -> Self {
292 Maybe::<_, G>::new(self.as_opt_ref().cloned())
293 }
294}
295
296impl<T, G> PartialEq for Maybe<T, G>
297where
298 T: PartialEq,
299{
300 fn eq(&self, other: &Self) -> bool {
301 self.as_opt_ref() == other.as_opt_ref()
302 }
303}
304
305impl<T, G> Eq for Maybe<T, G> where T: Eq {}
306
307impl<T, G> Hash for Maybe<T, G>
308where
309 T: Hash,
310{
311 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
312 self.as_opt_ref().hash(state)
313 }
314}
315
316#[cfg(feature = "defmt")]
317impl<T, G> defmt::Format for Maybe<T, G>
318where
319 T: defmt::Format,
320{
321 fn format(&self, f: defmt::Formatter<'_>) {
322 if self.is_none() {
323 defmt::write!(f, "None")
324 } else {
325 defmt::write!(f, "Some({})", unsafe { self.value.assume_init_ref() })
326 }
327 }
328}
329
330#[cfg(test)]
331mod tests {
332 use super::Maybe;
333
334 macro_rules! droppable {
335 () => {
336 static COUNT: core::sync::atomic::AtomicI32 = core::sync::atomic::AtomicI32::new(0);
337
338 #[derive(Eq, Ord, PartialEq, PartialOrd)]
339 struct Droppable(());
340
341 impl Droppable {
342 fn new() -> Self {
343 COUNT.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
344 Droppable(())
345 }
346
347 fn count() -> i32 {
348 COUNT.load(core::sync::atomic::Ordering::Relaxed)
349 }
350 }
351
352 impl Drop for Droppable {
353 fn drop(&mut self) {
354 COUNT.fetch_sub(1, core::sync::atomic::Ordering::Relaxed);
355 }
356 }
357
358 impl Clone for Droppable {
359 fn clone(&self) -> Self {
360 COUNT.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
361
362 Self(())
363 }
364 }
365 };
366 }
367
368 #[test]
369 fn drop() {
370 droppable!();
371
372 assert_eq!(Droppable::count(), 0);
375
376 {
377 let _m: Maybe<Droppable> = Maybe::none();
378 }
379
380 assert_eq!(Droppable::count(), 0);
381
382 {
385 let _m: Maybe<Droppable> = Maybe::some(Droppable::new());
386 }
387
388 assert_eq!(Droppable::count(), 0);
389
390 {
392 let m: Maybe<Droppable> = Maybe::some(Droppable::new());
393 m.into_option();
394 }
395
396 assert_eq!(Droppable::count(), 0);
397
398 {
401 let m: Maybe<Droppable> = Maybe::some(Droppable::new());
402
403 let _m2 = m.clone();
404
405 core::mem::drop(m);
406
407 assert_eq!(Droppable::count(), 1);
408 }
409
410 assert_eq!(Droppable::count(), 0);
411
412 {
415 let mut m: Maybe<Droppable> = Maybe::some(Droppable::new());
416
417 m.clear();
418 }
419
420 assert_eq!(Droppable::count(), 0);
421 }
422}