1use core::{
4 cmp, hash, mem,
5 ops::{Deref, DerefMut},
6};
7
8use crate::{seal::Seal, Portable};
9
10#[derive(Clone, Copy, Debug, Portable)]
15#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
16#[repr(u8)]
17#[rkyv(crate)]
18pub enum ArchivedOption<T> {
19 None,
21 Some(T),
23}
24
25impl<T> ArchivedOption<T> {
26 pub fn ok_or<E>(self, err: E) -> Result<T, E> {
29 match self {
30 ArchivedOption::None => Err(err),
31 ArchivedOption::Some(x) => Ok(x),
32 }
33 }
34 pub fn unwrap(self) -> T {
36 match self {
37 ArchivedOption::None => {
38 panic!("called `ArchivedOption::unwrap()` on a `None` value")
39 }
40 ArchivedOption::Some(value) => value,
41 }
42 }
43 pub fn unwrap_or(self, default: T) -> T {
45 match self {
46 ArchivedOption::None => default,
47 ArchivedOption::Some(value) => value,
48 }
49 }
50 pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
52 match self {
53 ArchivedOption::None => f(),
54 ArchivedOption::Some(value) => value,
55 }
56 }
57 pub fn is_none(&self) -> bool {
59 match self {
60 ArchivedOption::None => true,
61 ArchivedOption::Some(_) => false,
62 }
63 }
64
65 pub fn is_some(&self) -> bool {
67 match self {
68 ArchivedOption::None => false,
69 ArchivedOption::Some(_) => true,
70 }
71 }
72
73 pub const fn as_ref(&self) -> Option<&T> {
75 match self {
76 ArchivedOption::None => None,
77 ArchivedOption::Some(value) => Some(value),
78 }
79 }
80
81 pub fn as_mut(&mut self) -> Option<&mut T> {
83 match self {
84 ArchivedOption::None => None,
85 ArchivedOption::Some(value) => Some(value),
86 }
87 }
88
89 pub fn as_seal(this: Seal<'_, Self>) -> Option<Seal<'_, T>> {
91 let inner = unsafe { Seal::unseal_unchecked(this) };
92 inner.as_mut().map(Seal::new)
93 }
94
95 pub const fn iter(&self) -> Iter<&'_ T> {
97 Iter {
98 inner: self.as_ref(),
99 }
100 }
101
102 pub fn iter_mut(&mut self) -> Iter<&'_ mut T> {
104 Iter {
105 inner: self.as_mut(),
106 }
107 }
108
109 pub fn iter_seal(this: Seal<'_, Self>) -> Iter<Seal<'_, T>> {
111 Iter {
112 inner: Self::as_seal(this),
113 }
114 }
115
116 pub fn get_or_insert(&mut self, v: T) -> &mut T {
119 self.get_or_insert_with(move || v)
120 }
121
122 pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
125 if let ArchivedOption::Some(ref mut value) = self {
126 value
127 } else {
128 *self = ArchivedOption::Some(f());
129 self.as_mut().unwrap()
130 }
131 }
132}
133
134impl<T: Deref> ArchivedOption<T> {
135 pub fn as_deref(&self) -> Option<&<T as Deref>::Target> {
141 self.as_ref().map(|x| x.deref())
142 }
143}
144
145impl<T: DerefMut> ArchivedOption<T> {
146 pub fn as_deref_mut(&mut self) -> Option<&mut <T as Deref>::Target> {
151 self.as_mut().map(|x| x.deref_mut())
152 }
153}
154
155impl<T: Eq> Eq for ArchivedOption<T> {}
156
157impl<T: hash::Hash> hash::Hash for ArchivedOption<T> {
158 fn hash<H: hash::Hasher>(&self, state: &mut H) {
159 self.as_ref().hash(state)
160 }
161}
162
163impl<T: Ord> Ord for ArchivedOption<T> {
164 fn cmp(&self, other: &Self) -> cmp::Ordering {
165 self.as_ref().cmp(&other.as_ref())
166 }
167}
168
169impl<T: PartialEq> PartialEq for ArchivedOption<T> {
170 fn eq(&self, other: &Self) -> bool {
171 self.as_ref().eq(&other.as_ref())
172 }
173}
174
175impl<T: PartialOrd> PartialOrd for ArchivedOption<T> {
176 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
177 self.as_ref().partial_cmp(&other.as_ref())
178 }
179}
180
181impl<T, U: PartialOrd<T>> PartialOrd<Option<T>> for ArchivedOption<U> {
182 fn partial_cmp(&self, other: &Option<T>) -> Option<cmp::Ordering> {
183 match (self, other) {
184 (ArchivedOption::None, None) => Some(cmp::Ordering::Equal),
185 (ArchivedOption::None, Some(_)) => Some(cmp::Ordering::Less),
186 (ArchivedOption::Some(_), None) => Some(cmp::Ordering::Greater),
187 (ArchivedOption::Some(self_value), Some(other_value)) => {
188 self_value.partial_cmp(other_value)
189 }
190 }
191 }
192}
193
194impl<T, U: PartialEq<T>> PartialEq<Option<T>> for ArchivedOption<U> {
195 fn eq(&self, other: &Option<T>) -> bool {
196 if let ArchivedOption::Some(self_value) = self {
197 if let Some(other_value) = other {
198 self_value.eq(other_value)
199 } else {
200 false
201 }
202 } else {
203 other.is_none()
204 }
205 }
206}
207
208impl<T> From<T> for ArchivedOption<T> {
209 fn from(val: T) -> ArchivedOption<T> {
220 ArchivedOption::Some(val)
221 }
222}
223
224pub struct Iter<P> {
229 inner: Option<P>,
230}
231
232impl<P> Iter<P> {
233 pub fn new(inner: Option<P>) -> Self {
235 Self { inner }
236 }
237}
238
239impl<P> Iterator for Iter<P> {
240 type Item = P;
241
242 fn next(&mut self) -> Option<Self::Item> {
243 let mut result = None;
244 mem::swap(&mut self.inner, &mut result);
245 result
246 }
247}
248
249impl<P> DoubleEndedIterator for Iter<P> {
250 fn next_back(&mut self) -> Option<Self::Item> {
251 self.next()
252 }
253}
254
255impl<'a, T> IntoIterator for &'a ArchivedOption<T> {
256 type Item = &'a T;
257 type IntoIter = Iter<&'a T>;
258
259 fn into_iter(self) -> Self::IntoIter {
260 self.iter()
261 }
262}
263
264impl<'a, T> IntoIterator for &'a mut ArchivedOption<T> {
265 type Item = &'a mut T;
266 type IntoIter = Iter<&'a mut T>;
267
268 fn into_iter(self) -> Self::IntoIter {
269 self.iter_mut()
270 }
271}
272
273impl<'a, T> IntoIterator for Seal<'a, ArchivedOption<T>> {
274 type Item = Seal<'a, T>;
275 type IntoIter = Iter<Seal<'a, T>>;
276
277 fn into_iter(self) -> Self::IntoIter {
278 ArchivedOption::iter_seal(self)
279 }
280}
281
282#[cfg(test)]
283mod tests {
284 use super::*;
285
286 #[test]
287 fn partial_ord_option() {
288 use core::cmp::Ordering;
289
290 use super::ArchivedOption;
291
292 let a: ArchivedOption<u8> = ArchivedOption::Some(42);
293 let b = Some(42);
294 assert_eq!(Some(Ordering::Equal), a.partial_cmp(&b));
295
296 let a: ArchivedOption<u8> = ArchivedOption::Some(1);
297 let b = Some(2);
298 assert_eq!(Some(Ordering::Less), a.partial_cmp(&b));
299
300 let a: ArchivedOption<u8> = ArchivedOption::Some(2);
301 let b = Some(1);
302 assert_eq!(Some(Ordering::Greater), a.partial_cmp(&b));
303 }
304
305 #[test]
306 fn into_iter() {
307 let x: ArchivedOption<u8> = ArchivedOption::Some(1);
308 let mut iter = IntoIterator::into_iter(&x);
309 assert_eq!(iter.next(), Some(&1));
310 assert_eq!(iter.next(), None);
311
312 let x: ArchivedOption<u8> = ArchivedOption::None;
313 let mut iter = IntoIterator::into_iter(&x);
314 assert_eq!(iter.next(), None);
315 }
316}