1#[derive(Clone, Debug, PartialEq, Eq, Hash)]
10pub struct LogosOpt<T>(pub Option<T>);
11
12impl<T> LogosOpt<T> {
13 pub const NOTHING: Self = LogosOpt(None);
15
16 #[inline]
18 pub fn is_nothing(&self) -> bool {
19 self.0.is_none()
20 }
21
22 #[inline]
24 pub fn held(&self, failure: &str) -> &T {
25 match &self.0 {
26 Some(value) => value,
27 None => stopped(failure),
28 }
29 }
30
31 #[inline]
33 pub fn held_mut(&mut self, failure: &str) -> &mut T {
34 match &mut self.0 {
35 Some(value) => value,
36 None => stopped(failure),
37 }
38 }
39
40 #[inline]
42 pub fn into_held(self, failure: &str) -> T {
43 match self.0 {
44 Some(value) => value,
45 None => stopped(failure),
46 }
47 }
48
49 #[inline]
52 pub fn pair<U>(left: LogosOpt<T>, right: LogosOpt<U>, failures: [&str; 3]) -> (T, U) {
53 match (left.0, right.0) {
54 (Some(l), Some(r)) => (l, r),
55 (None, Some(_)) => stopped(failures[0]),
56 (Some(_), None) => stopped(failures[1]),
57 (None, None) => stopped(failures[2]),
58 }
59 }
60
61 #[inline]
63 pub fn equals_with<U>(&self, other: &LogosOpt<U>, same: impl FnOnce(&T, &U) -> bool) -> bool {
64 match (&self.0, &other.0) {
65 (Some(a), Some(b)) => same(a, b),
66 (None, None) => true,
67 _ => false,
68 }
69 }
70}
71
72impl<T: Default> Default for LogosOpt<T> {
74 #[inline]
75 fn default() -> Self {
76 LogosOpt(Some(T::default()))
77 }
78}
79
80impl<T> From<T> for LogosOpt<T> {
81 #[inline]
82 fn from(value: T) -> Self {
83 LogosOpt(Some(value))
84 }
85}
86
87impl<T: crate::ops::Truthy> crate::ops::Truthy for LogosOpt<T> {
89 #[inline]
90 fn truthy(&self) -> bool {
91 self.0.as_ref().is_some_and(crate::ops::Truthy::truthy)
92 }
93}
94
95#[cold]
96#[inline(never)]
97fn stopped(failure: &str) -> ! {
98 panic!("{failure}")
99}
100
101#[cfg(test)]
102#[path = "../../logicaffeine_tests/unit/logicaffeine_data/opt/tests.rs"]
103mod tests;