1 | use std::{ |
2 | convert::TryInto, |
3 | fmt::Display, |
4 | ops::{Deref, DerefMut}, |
5 | }; |
6 | |
7 | use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; |
8 | |
9 | use crate::Type; |
10 | |
11 | /// Type that uses a special value to be used as none. |
12 | /// |
13 | /// See [`Optional`] documentation for the rationale for this trait's existence. |
14 | /// |
15 | /// # Caveats |
16 | /// |
17 | /// Since use of default values as none is typical, this trait is implemented for all types that |
18 | /// implement [`Default`] for convenience. Unfortunately, this means you can not implement this |
19 | /// trait manually for types that implement [`Default`]. |
20 | pub trait NoneValue { |
21 | type NoneType; |
22 | |
23 | /// The none-equivalent value. |
24 | fn null_value() -> Self::NoneType; |
25 | } |
26 | |
27 | impl<T> NoneValue for T |
28 | where |
29 | T: Default, |
30 | { |
31 | type NoneType = Self; |
32 | |
33 | fn null_value() -> Self { |
34 | Default::default() |
35 | } |
36 | } |
37 | |
38 | /// An optional value. |
39 | /// |
40 | /// Since D-Bus doesn't have the concept of nullability, it uses a special value (typically the |
41 | /// default value) as the null value. For example [this signal][ts] uses empty strings for null |
42 | /// values. Serde has built-in support for `Option` but unfortunately that doesn't work for us. |
43 | /// Hence the need for this type. |
44 | /// |
45 | /// The serialization and deserialization of `Optional` relies on [`NoneValue`] implementation of |
46 | /// the underlying type. |
47 | /// |
48 | /// # Examples |
49 | /// |
50 | /// ``` |
51 | /// use zvariant::{EncodingContext, Optional, from_slice, to_bytes}; |
52 | /// use byteorder::LE; |
53 | /// |
54 | /// // `Null` case. |
55 | /// let ctxt = EncodingContext::<LE>::new_dbus(0); |
56 | /// let s = Optional::<&str>::default(); |
57 | /// let encoded = to_bytes(ctxt, &s).unwrap(); |
58 | /// assert_eq!(encoded, &[0, 0, 0, 0, 0]); |
59 | /// let s: Optional<&str> = from_slice(&encoded, ctxt).unwrap(); |
60 | /// assert_eq!(*s, None); |
61 | /// |
62 | /// // `Some` case. |
63 | /// let s = Optional::from(Some("hello" )); |
64 | /// let encoded = to_bytes(ctxt, &s).unwrap(); |
65 | /// assert_eq!(encoded.len(), 10); |
66 | /// // The first byte is the length of the string in Little-Endian format. |
67 | /// assert_eq!(encoded[0], 5); |
68 | /// let s: Optional<&str> = from_slice(&encoded, ctxt).unwrap(); |
69 | /// assert_eq!(*s, Some("hello" )); |
70 | /// ``` |
71 | /// |
72 | /// [ts]: https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-name-owner-changed |
73 | #[derive (Clone, Debug, PartialEq, Eq, Hash)] |
74 | pub struct Optional<T>(Option<T>); |
75 | |
76 | impl<T> Type for Optional<T> |
77 | where |
78 | T: Type, |
79 | { |
80 | fn signature() -> crate::Signature<'static> { |
81 | T::signature() |
82 | } |
83 | } |
84 | |
85 | impl<T> Serialize for Optional<T> |
86 | where |
87 | T: Type + NoneValue + Serialize, |
88 | <T as NoneValue>::NoneType: Serialize, |
89 | { |
90 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
91 | where |
92 | S: Serializer, |
93 | { |
94 | match &self.0 { |
95 | Some(value: &T) => value.serialize(serializer), |
96 | None => T::null_value().serialize(serializer), |
97 | } |
98 | } |
99 | } |
100 | |
101 | impl<'de, T, E> Deserialize<'de> for Optional<T> |
102 | where |
103 | T: Type + NoneValue + Deserialize<'de>, |
104 | <T as NoneValue>::NoneType: Deserialize<'de> + TryInto<T, Error = E> + PartialEq, |
105 | E: Display, |
106 | { |
107 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
108 | where |
109 | D: Deserializer<'de>, |
110 | { |
111 | let value: ::NoneType = <<T as NoneValue>::NoneType>::deserialize(deserializer)?; |
112 | if value == T::null_value() { |
113 | Ok(Optional(None)) |
114 | } else { |
115 | Ok(Optional(Some(value.try_into().map_err(op:de::Error::custom)?))) |
116 | } |
117 | } |
118 | } |
119 | |
120 | impl<T> From<Option<T>> for Optional<T> { |
121 | fn from(value: Option<T>) -> Self { |
122 | Optional(value) |
123 | } |
124 | } |
125 | |
126 | impl<T> From<Optional<T>> for Option<T> { |
127 | fn from(value: Optional<T>) -> Self { |
128 | value.0 |
129 | } |
130 | } |
131 | |
132 | impl<T> Deref for Optional<T> { |
133 | type Target = Option<T>; |
134 | |
135 | fn deref(&self) -> &Self::Target { |
136 | &self.0 |
137 | } |
138 | } |
139 | |
140 | impl<T> DerefMut for Optional<T> { |
141 | fn deref_mut(&mut self) -> &mut Self::Target { |
142 | &mut self.0 |
143 | } |
144 | } |
145 | |
146 | impl<T> Default for Optional<T> { |
147 | fn default() -> Self { |
148 | Self(None) |
149 | } |
150 | } |
151 | |