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    const SIGNATURE: &'static crate::Signature = T::SIGNATURE;
84}
85
86impl<T> Serialize for Optional<T>
87where
88    T: Type + NoneValue + Serialize,
89    <T as NoneValue>::NoneType: Serialize,
90{
91    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
92    where
93        S: Serializer,
94    {
95        if T::SIGNATURE == bool::SIGNATURE {
96            panic!("`Optional<bool>` type is not supported");
97        }
98
99        match &self.0 {
100            Some(value) => value.serialize(serializer),
101            None => T::null_value().serialize(serializer),
102        }
103    }
104}
105
106impl<'de, T, E> Deserialize<'de> for Optional<T>
107where
108    T: Type + NoneValue + Deserialize<'de>,
109    <T as NoneValue>::NoneType: Deserialize<'de> + TryInto<T, Error = E> + PartialEq,
110    E: Display,
111{
112    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
113    where
114        D: Deserializer<'de>,
115    {
116        if T::SIGNATURE == bool::SIGNATURE {
117            panic!("`Optional<bool>` type is not supported");
118        }
119
120        let value = <<T as NoneValue>::NoneType>::deserialize(deserializer)?;
121        if value == T::null_value() {
122            Ok(Optional(None))
123        } else {
124            Ok(Optional(Some(value.try_into().map_err(de::Error::custom)?)))
125        }
126    }
127}
128
129impl<T> From<Option<T>> for Optional<T> {
130    fn from(value: Option<T>) -> Self {
131        Optional(value)
132    }
133}
134
135impl<T> From<Optional<T>> for Option<T> {
136    fn from(value: Optional<T>) -> Self {
137        value.0
138    }
139}
140
141impl<T> Deref for Optional<T> {
142    type Target = Option<T>;
143
144    fn deref(&self) -> &Self::Target {
145        &self.0
146    }
147}
148
149impl<T> DerefMut for Optional<T> {
150    fn deref_mut(&mut self) -> &mut Self::Target {
151        &mut self.0
152    }
153}
154
155impl<T> Default for Optional<T> {
156    fn default() -> Self {
157        Self(None)
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use std::panic::catch_unwind;
164
165    #[test]
166    fn bool_in_optional() {
167        use crate::{to_bytes, Optional, LE};
169
170        let ctxt = crate::serialized::Context::new_dbus(LE, 0);
171        let res = catch_unwind(|| to_bytes(ctxt, &Optional::<bool>::default()));
172        assert!(res.is_err());
173
174        let data = crate::serialized::Data::new([0, 0, 0, 0].as_slice(), ctxt);
175        let res = catch_unwind(|| data.deserialize::<Optional<bool>>());
176        assert!(res.is_err());
177    }
178}