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