1use serde::ser::{Serialize, Serializer};
2use std::fmt::Display;
3
4use crate::{value_display_fmt, Error, Signature, Type, Value};
5
6#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
12pub struct Maybe<'a> {
13 value: Box<Option<Value<'a>>>,
14 signature: Signature,
15}
16
17impl<'a> Maybe<'a> {
18 pub fn inner(&self) -> &Option<Value<'a>> {
20 &self.value
21 }
22
23 pub fn just(value: Value<'a>) -> Self {
25 let value_signature = value.value_signature().clone();
26 let signature = Signature::maybe(value_signature);
27 Self {
28 signature,
29 value: Box::new(Some(value)),
30 }
31 }
32
33 pub(crate) fn just_full_signature(value: Value<'a>, signature: &Signature) -> Self {
34 Self {
35 signature: signature.clone(),
36 value: Box::new(Some(value)),
37 }
38 }
39
40 pub fn nothing(value_signature: &Signature) -> Self {
42 let signature = Signature::maybe(value_signature.clone());
43 Self {
44 signature,
45 value: Box::new(None),
46 }
47 }
48
49 pub(crate) fn nothing_full_signature(signature: &Signature) -> Self {
50 Self {
51 signature: signature.clone(),
52 value: Box::new(None),
53 }
54 }
55
56 pub fn get<T>(&'a self) -> core::result::Result<Option<T>, Error>
58 where
59 T: ?Sized + TryFrom<&'a Value<'a>>,
60 <T as TryFrom<&'a Value<'a>>>::Error: Into<crate::Error>,
61 {
62 self.value
63 .as_ref()
64 .as_ref()
65 .map(|v| v.downcast_ref())
66 .transpose()
67 }
68
69 pub fn signature(&self) -> &Signature {
71 &self.signature
72 }
73
74 pub fn value_signature(&self) -> &Signature {
76 match self.signature() {
77 Signature::Maybe(signature) => signature,
78 _ => unreachable!("Invalid `Maybe` signature"),
79 }
80 }
81
82 pub(crate) fn try_to_owned(&self) -> crate::Result<Maybe<'static>> {
83 Ok(Maybe {
84 value: Box::new(
85 self.value
86 .as_ref()
87 .as_ref()
88 .map(|v| v.try_to_owned().map(Into::into))
89 .transpose()?,
90 ),
91 signature: self.signature.clone(),
92 })
93 }
94
95 pub(crate) fn try_into_owned(self) -> crate::Result<Maybe<'static>> {
96 Ok(Maybe {
97 value: Box::new(
98 self.value
99 .map(|v| v.try_into_owned().map(Into::into))
100 .transpose()?,
101 ),
102 signature: self.signature,
103 })
104 }
105
106 pub fn try_clone(&self) -> Result<Self, crate::Error> {
108 Ok(Maybe {
109 value: Box::new(
110 self.value
111 .as_ref()
112 .as_ref()
113 .map(|v| v.try_clone().map(Into::into))
114 .transpose()?,
115 ),
116 signature: self.signature.clone(),
117 })
118 }
119}
120
121impl Display for Maybe<'_> {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 maybe_display_fmt(self, f, true)
124 }
125}
126
127pub(crate) fn maybe_display_fmt(
128 maybe: &Maybe<'_>,
129 f: &mut std::fmt::Formatter<'_>,
130 type_annotate: bool,
131) -> std::fmt::Result {
132 if type_annotate {
133 write!(f, "@{} ", maybe.signature())?;
134 }
135
136 let (last_inner, depth) = {
137 let mut curr = maybe.inner();
138 let mut depth = 0;
139
140 while let Some(Value::Maybe(child_maybe)) = curr {
141 curr = child_maybe.inner();
142 depth += 1;
143 }
144
145 (curr, depth)
146 };
147
148 if let Some(last_inner) = last_inner {
149 value_display_fmt(last_inner, f, false)?;
151 } else {
152 for _ in 0..depth {
154 f.write_str("just ")?;
155 }
156 f.write_str("nothing")?;
157 }
158
159 Ok(())
160}
161
162impl<'a, T> From<Option<T>> for Maybe<'a>
163where
164 T: Type + Into<Value<'a>>,
165{
166 fn from(value: Option<T>) -> Self {
167 value
168 .map(|v| Self::just(Value::new(v)))
169 .unwrap_or_else(|| Self::nothing(T::SIGNATURE))
170 }
171}
172
173impl<'a, T> From<&Option<T>> for Maybe<'a>
174where
175 T: Type + Into<Value<'a>> + Clone,
176{
177 fn from(value: &Option<T>) -> Self {
178 value
179 .as_ref()
180 .map(|v| Self::just(Value::new(v.clone())))
181 .unwrap_or_else(|| Self::nothing(T::SIGNATURE))
182 }
183}
184
185impl<'a> Serialize for Maybe<'a> {
186 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
187 where
188 S: Serializer,
189 {
190 match &*self.value {
191 Some(value) => value.serialize_value_as_some(serializer),
192 None => serializer.serialize_none(),
193 }
194 }
195}