1use std::{
2 fmt::Display,
3 ops::{Deref, DerefMut},
4};
5
6use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
7
8use crate::Type;
9
10pub trait NoneValue {
25 type NoneType;
26
27 fn null_value() -> Self::NoneType;
29}
30
31impl<T> NoneValue for T
32where
33 T: Default,
34{
35 type NoneType = Self;
36
37 fn null_value() -> Self {
38 Default::default()
39 }
40}
41
42#[derive(Clone, Debug, PartialEq, Eq, Hash)]
77pub struct Optional<T>(Option<T>);
78
79impl<T> Type for Optional<T>
80where
81 T: Type,
82{
83 fn signature() -> crate::Signature<'static> {
84 T::signature()
85 }
86}
87
88impl<T> Serialize for Optional<T>
89where
90 T: Type + NoneValue + Serialize,
91 <T as NoneValue>::NoneType: Serialize,
92{
93 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
94 where
95 S: Serializer,
96 {
97 if T::signature() == bool::signature() {
98 panic!("`Optional<bool>` type is not supported");
99 }
100
101 match &self.0 {
102 Some(value) => value.serialize(serializer),
103 None => T::null_value().serialize(serializer),
104 }
105 }
106}
107
108impl<'de, T, E> Deserialize<'de> for Optional<T>
109where
110 T: Type + NoneValue + Deserialize<'de>,
111 <T as NoneValue>::NoneType: Deserialize<'de> + TryInto<T, Error = E> + PartialEq,
112 E: Display,
113{
114 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
115 where
116 D: Deserializer<'de>,
117 {
118 if T::signature() == bool::signature() {
119 panic!("`Optional<bool>` type is not supported");
120 }
121
122 let value = <<T as NoneValue>::NoneType>::deserialize(deserializer)?;
123 if value == T::null_value() {
124 Ok(Optional(None))
125 } else {
126 Ok(Optional(Some(value.try_into().map_err(de::Error::custom)?)))
127 }
128 }
129}
130
131impl<T> From<Option<T>> for Optional<T> {
132 fn from(value: Option<T>) -> Self {
133 Optional(value)
134 }
135}
136
137impl<T> From<Optional<T>> for Option<T> {
138 fn from(value: Optional<T>) -> Self {
139 value.0
140 }
141}
142
143impl<T> Deref for Optional<T> {
144 type Target = Option<T>;
145
146 fn deref(&self) -> &Self::Target {
147 &self.0
148 }
149}
150
151impl<T> DerefMut for Optional<T> {
152 fn deref_mut(&mut self) -> &mut Self::Target {
153 &mut self.0
154 }
155}
156
157impl<T> Default for Optional<T> {
158 fn default() -> Self {
159 Self(None)
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use std::panic::catch_unwind;
166
167 #[test]
168 fn bool_in_optional() {
169 use crate::{to_bytes, Optional, LE};
171
172 let ctxt = crate::serialized::Context::new_dbus(LE, 0);
173 let res = catch_unwind(|| to_bytes(ctxt, &Optional::<bool>::default()));
174 assert!(res.is_err());
175
176 let data = crate::serialized::Data::new([0, 0, 0, 0].as_slice(), ctxt);
177 let res = catch_unwind(|| data.deserialize::<Optional<bool>>());
178 assert!(res.is_err());
179 }
180}