1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, PartialEq, Eq)]
35pub enum Maybe<T> {
36 #[default]
37 Unspecified,
38 Specified(T),
39}
40
41impl<T> Maybe<T> {
42 pub fn is_unspecified(&self) -> bool {
43 matches!(self, Self::Unspecified)
44 }
45
46 pub fn map<U, F>(self, f: F) -> Maybe<U>
47 where
48 F: FnOnce(T) -> U,
49 {
50 match self {
51 Self::Unspecified => Maybe::Unspecified,
52 Self::Specified(x) => Maybe::Specified(f(x)),
53 }
54 }
55
56 pub fn unwrap_or_default(self) -> T
57 where
58 T: Default,
59 {
60 match self {
61 Self::Unspecified => T::default(),
62 Self::Specified(x) => x,
63 }
64 }
65}
66
67impl<T> Maybe<Option<T>> {
68 pub fn map_opt<U, F>(self, f: F) -> Maybe<Option<U>>
69 where
70 F: FnOnce(T) -> U,
71 {
72 self.map(|opt| opt.map(f))
73 }
74
75 pub fn try_map_opt<U, E, F>(self, f: F) -> Result<Maybe<Option<U>>, E>
76 where
77 F: FnOnce(T) -> Result<U, E>,
78 {
79 match self {
80 Maybe::Unspecified => Ok(Maybe::Unspecified),
81 Maybe::Specified(opt) => match opt {
82 Some(value) => f(value).map(|converted| Maybe::Specified(Some(converted))),
83 None => Ok(Maybe::Specified(None)),
84 },
85 }
86 }
87
88 pub fn opt_or_default_mut(&mut self) -> &mut T
89 where
90 T: Default,
91 {
92 match self {
93 Maybe::Unspecified | Maybe::Specified(None) => {
94 *self = Self::Specified(Some(T::default()));
95 match self {
96 Self::Specified(Some(x)) => x,
97 _ => unreachable!(),
98 }
99 }
100 Maybe::Specified(Some(x)) => x,
101 }
102 }
103}
104
105impl<T> From<T> for Maybe<T> {
106 fn from(value: T) -> Self {
107 Self::Specified(value)
108 }
109}
110
111impl<T: Serialize> Serialize for Maybe<T> {
112 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113 where
114 S: serde::Serializer,
115 {
116 match self {
117 Self::Unspecified => serializer.serialize_none(),
118 Self::Specified(v) => v.serialize(serializer),
119 }
120 }
121}
122
123impl<'de, T: Deserialize<'de>> Deserialize<'de> for Maybe<T> {
124 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
125 where
126 D: serde::Deserializer<'de>,
127 {
128 let v = T::deserialize(deserializer)?;
129 Ok(v.into())
130 }
131}