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