1#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct MaybeValue<V>(Option<V>);
18
19impl<V> MaybeValue<V> {
20 #[must_use]
22 pub fn from_value(value: V) -> Self {
23 Self(Some(value))
24 }
25
26 #[must_use]
28 pub fn none() -> Self {
29 Self(None)
30 }
31
32 #[must_use]
34 pub fn has_value(&self) -> bool {
35 self.0.is_some()
36 }
37
38 #[must_use]
40 pub fn value(&self) -> Option<&V> {
41 self.0.as_ref()
42 }
43
44 #[must_use]
46 pub fn into_value(self) -> Option<V> {
47 self.0
48 }
49
50 #[must_use]
52 pub fn value_or(self, default: V) -> V {
53 self.0.unwrap_or(default)
54 }
55
56 #[must_use]
58 pub fn map<U, F: FnOnce(V) -> U>(self, f: F) -> MaybeValue<U> {
59 MaybeValue(self.0.map(f))
60 }
61}
62
63impl<V: Clone> MaybeValue<V> {
64 #[must_use]
66 pub fn value_or_clone(&self, default: V) -> V {
67 self.0.clone().unwrap_or(default)
68 }
69}
70
71impl<V: Default> MaybeValue<V> {
72 #[must_use]
74 pub fn value_or_default(self) -> V {
75 self.0.unwrap_or_default()
76 }
77}
78
79impl<V> Default for MaybeValue<V> {
80 fn default() -> Self {
82 Self(None)
83 }
84}
85
86impl<V> From<V> for MaybeValue<V> {
87 fn from(value: V) -> Self {
88 Self::from_value(value)
89 }
90}
91
92impl<V> From<Option<V>> for MaybeValue<V> {
93 fn from(option: Option<V>) -> Self {
94 Self(option)
95 }
96}
97
98impl<V> From<MaybeValue<V>> for Option<V> {
99 fn from(maybe: MaybeValue<V>) -> Self {
100 maybe.0
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn none_has_no_value() {
110 let m: MaybeValue<i32> = MaybeValue::none();
111 assert!(!m.has_value());
112 assert_eq!(m.value(), None);
113 assert_eq!(MaybeValue::<i32>::default(), MaybeValue::none());
114 }
115
116 #[test]
117 fn from_value_round_trips() {
118 let m = MaybeValue::from_value(42);
119 assert!(m.has_value());
120 assert_eq!(m.value(), Some(&42));
121 assert_eq!(Option::from(m), Some(42));
122 }
123
124 #[test]
125 fn value_or_default_falls_back() {
126 assert_eq!(MaybeValue::<i32>::none().value_or_default(), 0);
127 assert_eq!(MaybeValue::from_value(7).value_or_default(), 7);
128 }
129}