1 use crate::{utils::*, Signature};
2 use serde::de::{Deserialize, DeserializeSeed};
3 use std::{convert::TryInto, marker::PhantomData};
4 
5 /// Trait implemented by all serializable types.
6 ///
7 /// This very simple trait provides the signature for the implementing type. Since the [D-Bus type
8 /// system] relies on these signatures, our [serialization and deserialization] API requires this
9 /// trait in addition to [`Serialize`] and [`Deserialize`], respectively.
10 ///
11 /// Implementation is provided for all the [basic types] and blanket implementations for common
12 /// container types, such as, arrays, slices, tuples, [`Vec`] and [`HashMap`]. For easy
13 /// implementation for custom types, use `Type` derive macro from [zvariant_derive] crate.
14 ///
15 /// If your type's signature cannot be determined statically, you should implement the
16 /// [DynamicType] trait instead, which is otherwise automatically implemented if you implement this
17 /// trait.
18 ///
19 /// [D-Bus type system]: https://dbus.freedesktop.org/doc/dbus-specification.html#type-system
20 /// [serialization and deserialization]: index.html#functions
21 /// [`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html
22 /// [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
23 /// [basic types]: trait.Basic.html
24 /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
25 /// [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html
26 /// [zvariant_derive]: https://docs.rs/zvariant_derive/2.10.0/zvariant_derive/
27 pub trait Type {
28     /// Get the signature for the implementing type.
29     ///
30     /// # Example
31     ///
32     /// ```
33     /// use std::collections::HashMap;
34     /// use zvariant::Type;
35     ///
36     /// assert_eq!(u32::signature(), "u");
37     /// assert_eq!(String::signature(), "s");
38     /// assert_eq!(<(u32, &str, u64)>::signature(), "(ust)");
39     /// assert_eq!(<(u32, &str, &[u64])>::signature(), "(usat)");
40     /// assert_eq!(<HashMap<u8, &str>>::signature(), "a{ys}");
41     /// ```
signature() -> Signature<'static>42     fn signature() -> Signature<'static>;
43 }
44 
45 /// Types with dynamic signatures.
46 ///
47 /// Prefer implementing [Type] if possible, but if the actual signature of your type cannot be
48 /// determined until runtime, you can implement this type to support serialization.  You should
49 /// also implement [DynamicDeserialize] for deserialization.
50 pub trait DynamicType {
51     /// Get the signature for the implementing type.
52     ///
53     /// See [Type::signature] for details.
dynamic_signature(&self) -> Signature<'_>54     fn dynamic_signature(&self) -> Signature<'_>;
55 }
56 
57 /// Types that deserialize based on dynamic signatures.
58 ///
59 /// Prefer implementing [Type] and [Deserialize] if possible, but if the actual signature of your
60 /// type cannot be determined until runtime, you should implement this type to support
61 /// deserialization given a signature.
62 pub trait DynamicDeserialize<'de>: DynamicType {
63     /// A [DeserializeSeed] implementation for this type.
64     type Deserializer: DeserializeSeed<'de, Value = Self> + DynamicType;
65 
66     /// Get a deserializer compatible with this signature.
deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer> where S: TryInto<Signature<'de>>, S::Error: Into<zvariant::Error>67     fn deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer>
68     where
69         S: TryInto<Signature<'de>>,
70         S::Error: Into<zvariant::Error>;
71 }
72 
73 impl<T> DynamicType for T
74 where
75     T: Type + ?Sized,
76 {
dynamic_signature(&self) -> Signature<'_>77     fn dynamic_signature(&self) -> Signature<'_> {
78         <T as Type>::signature()
79     }
80 }
81 
82 impl<T> Type for PhantomData<T>
83 where
84     T: Type + ?Sized,
85 {
signature() -> Signature<'static>86     fn signature() -> Signature<'static> {
87         T::signature()
88     }
89 }
90 
91 impl<'de, T> DynamicDeserialize<'de> for T
92 where
93     T: Type + ?Sized + Deserialize<'de>,
94 {
95     type Deserializer = PhantomData<T>;
96 
deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer> where S: TryInto<Signature<'de>>, S::Error: Into<zvariant::Error>,97     fn deserializer_for_signature<S>(signature: S) -> zvariant::Result<Self::Deserializer>
98     where
99         S: TryInto<Signature<'de>>,
100         S::Error: Into<zvariant::Error>,
101     {
102         let mut expected = <T as Type>::signature();
103         let original = signature.try_into().map_err(Into::into)?;
104 
105         if original == expected {
106             return Ok(PhantomData);
107         }
108 
109         let mut signature = original.clone();
110         while expected.len() < signature.len()
111             && signature.starts_with(STRUCT_SIG_START_CHAR)
112             && signature.ends_with(STRUCT_SIG_END_CHAR)
113         {
114             signature = signature.slice(1..signature.len() - 1);
115         }
116 
117         while signature.len() < expected.len()
118             && expected.starts_with(STRUCT_SIG_START_CHAR)
119             && expected.ends_with(STRUCT_SIG_END_CHAR)
120         {
121             expected = expected.slice(1..expected.len() - 1);
122         }
123 
124         if signature == expected {
125             Ok(PhantomData)
126         } else {
127             let expected = <T as Type>::signature();
128             Err(zvariant::Error::SignatureMismatch(
129                 original.to_owned(),
130                 format!("`{}`", expected),
131             ))
132         }
133     }
134 }
135 
136 macro_rules! array_type {
137     ($arr:ty) => {
138         impl<T> Type for $arr
139         where
140             T: Type,
141         {
142             #[inline]
143             fn signature() -> Signature<'static> {
144                 Signature::from_string_unchecked(format!("a{}", T::signature()))
145             }
146         }
147     };
148 }
149 
150 array_type!([T]);
151 array_type!(Vec<T>);
152 
153 #[cfg(feature = "arrayvec")]
154 impl<T, const CAP: usize> Type for arrayvec::ArrayVec<T, CAP>
155 where
156     T: Type,
157 {
158     #[inline]
signature() -> Signature<'static>159     fn signature() -> Signature<'static> {
160         <[T]>::signature()
161     }
162 }
163 
164 #[cfg(feature = "arrayvec")]
165 impl<const CAP: usize> Type for arrayvec::ArrayString<CAP> {
166     #[inline]
signature() -> Signature<'static>167     fn signature() -> Signature<'static> {
168         <&str>::signature()
169     }
170 }
171 
172 // Empty type deserves empty signature
173 impl Type for () {
174     #[inline]
signature() -> Signature<'static>175     fn signature() -> Signature<'static> {
176         Signature::from_static_str_unchecked("")
177     }
178 }
179 
180 impl<T> Type for &T
181 where
182     T: ?Sized + Type,
183 {
184     #[inline]
signature() -> Signature<'static>185     fn signature() -> Signature<'static> {
186         T::signature()
187     }
188 }
189 
190 #[cfg(feature = "gvariant")]
191 impl<T> Type for Option<T>
192 where
193     T: Type,
194 {
195     #[inline]
signature() -> Signature<'static>196     fn signature() -> Signature<'static> {
197         Signature::from_string_unchecked(format!("m{}", T::signature()))
198     }
199 }
200 
201 ////////////////////////////////////////////////////////////////////////////////
202 
203 macro_rules! tuple_impls {
204     ($($len:expr => ($($n:tt $name:ident)+))+) => {
205         $(
206             impl<$($name),+> Type for ($($name,)+)
207             where
208                 $($name: Type,)+
209             {
210                 #[inline]
211                 fn signature() -> Signature<'static> {
212                     let mut sig = String::with_capacity(255);
213                     sig.push(STRUCT_SIG_START_CHAR);
214                     $(
215                         sig.push_str($name::signature().as_str());
216                     )+
217                     sig.push(STRUCT_SIG_END_CHAR);
218 
219                     Signature::from_string_unchecked(sig)
220                 }
221             }
222         )+
223     }
224 }
225 
226 tuple_impls! {
227     1 => (0 T0)
228     2 => (0 T0 1 T1)
229     3 => (0 T0 1 T1 2 T2)
230     4 => (0 T0 1 T1 2 T2 3 T3)
231     5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
232     6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
233     7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
234     8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
235     9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
236     10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
237     11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
238     12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
239     13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
240     14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
241     15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
242     16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 
247 // Arrays are serialized as tuples/structs by Serde so we treat them as such too even though
248 // it's very strange. Slices and arrayvec::ArrayVec can be used anyway so I guess it's no big
249 // deal.
250 impl<T, const N: usize> Type for [T; N]
251 where
252     T: Type,
253 {
254     #[inline]
255     #[allow(clippy::reversed_empty_ranges)]
signature() -> Signature<'static>256     fn signature() -> Signature<'static> {
257         let mut sig = String::with_capacity(255);
258         sig.push(STRUCT_SIG_START_CHAR);
259         for _ in 0..N {
260             sig.push_str(T::signature().as_str());
261         }
262         sig.push(STRUCT_SIG_END_CHAR);
263 
264         Signature::from_string_unchecked(sig)
265     }
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 
270 use std::{
271     borrow::Cow,
272     collections::{BTreeMap, HashMap},
273     hash::{BuildHasher, Hash},
274 };
275 
276 macro_rules! map_impl {
277     ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
278         impl<K, V $(, $typaram)*> Type for $ty<K, V $(, $typaram)*>
279         where
280             K: Type $(+ $kbound1 $(+ $kbound2)*)*,
281             V: Type,
282             $($typaram: $bound,)*
283         {
284             #[inline]
285             fn signature() -> Signature<'static> {
286                 Signature::from_string_unchecked(format!("a{{{}{}}}", K::signature(), V::signature()))
287             }
288         }
289     }
290 }
291 
292 map_impl!(BTreeMap<K: Ord, V>);
293 map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
294 
295 impl<T> Type for Cow<'_, T>
296 where
297     T: ?Sized + Type + ToOwned,
298 {
299     #[inline]
signature() -> Signature<'static>300     fn signature() -> Signature<'static> {
301         T::signature()
302     }
303 }
304 
305 // BitFlags
306 #[cfg(feature = "enumflags2")]
307 impl<F> Type for enumflags2::BitFlags<F>
308 where
309     F: Type + enumflags2::BitFlag,
310 {
311     #[inline]
signature() -> Signature<'static>312     fn signature() -> Signature<'static> {
313         F::signature()
314     }
315 }
316 
317 #[cfg(feature = "serde_bytes")]
318 impl Type for serde_bytes::Bytes {
signature() -> Signature<'static>319     fn signature() -> Signature<'static> {
320         Signature::from_static_str_unchecked("ay")
321     }
322 }
323 
324 #[cfg(feature = "serde_bytes")]
325 impl Type for serde_bytes::ByteBuf {
signature() -> Signature<'static>326     fn signature() -> Signature<'static> {
327         Signature::from_static_str_unchecked("ay")
328     }
329 }
330 
331 // TODO: Blanket implementation for more types: https://github.com/serde-rs/serde/blob/master/serde/src/ser/impls.rs
332