1use serde::{
2 de::{self, DeserializeSeed, VariantAccess, Visitor},
3 Deserialize,
4};
5use static_assertions::assert_impl_all;
6
7use std::{marker::PhantomData, str};
8
9#[cfg(unix)]
10use std::os::unix::io::RawFd;
11
12#[cfg(feature = "gvariant")]
13use crate::gvariant::Deserializer as GVDeserializer;
14use crate::{
15 container_depths::ContainerDepths, dbus::Deserializer as DBusDeserializer,
16 signature_parser::SignatureParser, utils::*, Basic, DynamicDeserialize, DynamicType,
17 EncodingContext, EncodingFormat, Error, ObjectPath, Result, Signature, Type,
18};
19
20#[cfg(unix)]
21use crate::Fd;
22
23/// Deserialize `T` from a given slice of bytes, containing file descriptor indices.
24///
25/// Please note that actual file descriptors are not part of the encoding and need to be transferred
26/// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
27/// file descriptors and hence the reason, caller must pass a slice of file descriptors.
28///
29/// This function is not available on Windows.
30///
31/// # Examples
32///
33/// ```
34/// use zvariant::{to_bytes_fds, from_slice_fds};
35/// use zvariant::{EncodingContext, Fd};
36///
37/// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
38/// let (encoded, fds) = to_bytes_fds(ctxt, &Fd::from(42)).unwrap();
39/// let decoded: Fd = from_slice_fds(&encoded, Some(&fds), ctxt).unwrap();
40/// assert_eq!(decoded, Fd::from(42));
41/// ```
42///
43/// [`from_slice`]: fn.from_slice.html
44#[cfg(unix)]
45pub fn from_slice_fds<'d, 'r: 'd, B, T: ?Sized>(
46 bytes: &'r [u8],
47 fds: Option<&[RawFd]>,
48 ctxt: EncodingContext<B>,
49) -> Result<T>
50where
51 B: byteorder::ByteOrder,
52 T: Deserialize<'d> + Type,
53{
54 let signature: Signature<'_> = T::signature();
55 from_slice_fds_for_signature(bytes, fds, ctxt, &signature)
56}
57
58/// Deserialize `T` from a given slice of bytes.
59///
60/// If `T` is an, or (potentially) contains an [`Fd`], use [`from_slice_fds`] instead.
61///
62/// # Examples
63///
64/// ```
65/// use zvariant::{to_bytes, from_slice};
66/// use zvariant::EncodingContext;
67///
68/// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
69/// let encoded = to_bytes(ctxt, "hello world").unwrap();
70/// let decoded: &str = from_slice(&encoded, ctxt).unwrap();
71/// assert_eq!(decoded, "hello world");
72/// ```
73///
74/// [`Fd`]: struct.Fd.html
75/// [`from_slice_fds`]: fn.from_slice_fds.html
76pub fn from_slice<'d, 'r: 'd, B, T: ?Sized>(bytes: &'r [u8], ctxt: EncodingContext<B>) -> Result<T>
77where
78 B: byteorder::ByteOrder,
79 T: Deserialize<'d> + Type,
80{
81 let signature: Signature<'_> = T::signature();
82 from_slice_for_signature(bytes, ctxt, &signature)
83}
84
85/// Deserialize `T` from a given slice of bytes with the given signature.
86///
87/// Use this function instead of [`from_slice`] if the value being deserialized does not implement
88/// [`Type`]. Also, if `T` is an, or (potentially) contains an [`Fd`], use
89/// [`from_slice_fds_for_signature`] instead.
90///
91/// # Examples
92///
93/// While `Type` derive supports enums, for this example, let's supposed it doesn't and we don't
94/// want to manually implement `Type` trait either:
95///
96/// ```
97/// use std::convert::TryInto;
98/// use serde::{Deserialize, Serialize};
99///
100/// use zvariant::{to_bytes_for_signature, from_slice_for_signature};
101/// use zvariant::EncodingContext;
102///
103/// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
104/// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
105/// enum Unit {
106/// Variant1,
107/// Variant2,
108/// Variant3,
109/// }
110///
111/// let signature = "u".try_into().unwrap();
112/// let encoded = to_bytes_for_signature(ctxt, &signature, &Unit::Variant2).unwrap();
113/// assert_eq!(encoded.len(), 4);
114/// let decoded: Unit = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
115/// assert_eq!(decoded, Unit::Variant2);
116///
117/// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
118/// enum NewType<'s> {
119/// Variant1(&'s str),
120/// Variant2(&'s str),
121/// Variant3(&'s str),
122/// }
123///
124/// let signature = "(us)".try_into().unwrap();
125/// let encoded =
126/// to_bytes_for_signature(ctxt, &signature, &NewType::Variant2("hello")).unwrap();
127/// assert_eq!(encoded.len(), 14);
128/// let decoded: NewType<'_> = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
129/// assert_eq!(decoded, NewType::Variant2("hello"));
130///
131/// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
132/// enum Structs {
133/// Tuple(u8, u64),
134/// Struct { y: u8, t: u64 },
135/// }
136///
137/// // TODO: Provide convenience API to create complex signatures
138/// let signature = "(u(yt))".try_into().unwrap();
139/// let encoded = to_bytes_for_signature(ctxt, &signature, &Structs::Tuple(42, 42)).unwrap();
140/// assert_eq!(encoded.len(), 24);
141/// let decoded: Structs = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
142/// assert_eq!(decoded, Structs::Tuple(42, 42));
143///
144/// let s = Structs::Struct { y: 42, t: 42 };
145/// let encoded = to_bytes_for_signature(ctxt, &signature, &s).unwrap();
146/// assert_eq!(encoded.len(), 24);
147/// let decoded: Structs = from_slice_for_signature(&encoded, ctxt, &signature).unwrap();
148/// assert_eq!(decoded, Structs::Struct { y: 42, t: 42 });
149/// ```
150///
151/// [`Type`]: trait.Type.html
152/// [`Fd`]: struct.Fd.html
153/// [`from_slice_fds_for_signature`]: fn.from_slice_fds_for_signature.html
154// TODO: Return number of bytes parsed?
155pub fn from_slice_for_signature<'d, 'r: 'd, B, T: ?Sized>(
156 bytes: &'r [u8],
157 ctxt: EncodingContext<B>,
158 signature: &Signature<'_>,
159) -> Result<T>
160where
161 B: byteorder::ByteOrder,
162 T: Deserialize<'d>,
163{
164 _from_slice_fds_for_signature(
165 bytes,
166 #[cfg(unix)]
167 None,
168 ctxt,
169 signature,
170 )
171}
172
173/// Deserialize `T` from a given slice of bytes containing file descriptor indices, with the given
174/// signature.
175///
176/// Please note that actual file descriptors are not part of the encoding and need to be transferred
177/// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
178/// file descriptors and hence the reason, caller must pass a slice of file descriptors.
179///
180/// This function is not available on Windows.
181///
182/// [`from_slice`]: fn.from_slice.html
183/// [`from_slice_for_signature`]: fn.from_slice_for_signature.html
184// TODO: Return number of bytes parsed?
185#[cfg(unix)]
186pub fn from_slice_fds_for_signature<'d, 'r: 'd, B, T: ?Sized>(
187 bytes: &'r [u8],
188 fds: Option<&[RawFd]>,
189 ctxt: EncodingContext<B>,
190 signature: &Signature<'_>,
191) -> Result<T>
192where
193 B: byteorder::ByteOrder,
194 T: Deserialize<'d>,
195{
196 _from_slice_fds_for_signature(bytes, fds, ctxt, signature)
197}
198
199fn _from_slice_fds_for_signature<'d, 'r: 'd, B, T: ?Sized>(
200 bytes: &'r [u8],
201 #[cfg(unix)] fds: Option<&[RawFd]>,
202 ctxt: EncodingContext<B>,
203 signature: &Signature<'_>,
204) -> Result<T>
205where
206 B: byteorder::ByteOrder,
207 T: Deserialize<'d>,
208{
209 let mut de: Deserializer<'_, '_, '_, …> = match ctxt.format() {
210 #[cfg(feature = "gvariant")]
211 EncodingFormat::GVariant => Deserializer::GVariant(GVDeserializer::new(
212 bytes,
213 #[cfg(unix)]
214 fds,
215 signature,
216 ctxt,
217 )),
218 EncodingFormat::DBus => Deserializer::DBus(DBusDeserializer::new(
219 bytes,
220 #[cfg(unix)]
221 fds,
222 signature,
223 ctxt,
224 )),
225 };
226
227 T::deserialize(&mut de)
228}
229
230/// Deserialize `T` from a given slice of bytes containing file descriptor indices, with the given
231/// signature.
232///
233/// Please note that actual file descriptors are not part of the encoding and need to be transferred
234/// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
235/// file descriptors and hence the reason, caller must pass a slice of file descriptors.
236pub fn from_slice_for_dynamic_signature<'d, B, T>(
237 bytes: &'d [u8],
238 ctxt: EncodingContext<B>,
239 signature: &Signature<'d>,
240) -> Result<T>
241where
242 B: byteorder::ByteOrder,
243 T: DynamicDeserialize<'d>,
244{
245 let seed: ::Deserializer = T::deserializer_for_signature(signature)?;
246
247 from_slice_with_seed(bytes, ctxt, seed)
248}
249
250/// Deserialize `T` from a given slice of bytes containing file descriptor indices, with the given
251/// signature.
252///
253/// Please note that actual file descriptors are not part of the encoding and need to be transferred
254/// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
255/// file descriptors and hence the reason, caller must pass a slice of file descriptors.
256///
257/// This function is not available on Windows.
258#[cfg(unix)]
259pub fn from_slice_fds_for_dynamic_signature<'d, B, T>(
260 bytes: &'d [u8],
261 fds: Option<&[RawFd]>,
262 ctxt: EncodingContext<B>,
263 signature: &Signature<'d>,
264) -> Result<T>
265where
266 B: byteorder::ByteOrder,
267 T: DynamicDeserialize<'d>,
268{
269 let seed: ::Deserializer = T::deserializer_for_signature(signature)?;
270
271 from_slice_fds_with_seed(bytes, fds, ctxt, seed)
272}
273
274/// Deserialize `T` from a given slice of bytes containing file descriptor indices, using the given
275/// seed.
276///
277/// Please note that actual file descriptors are not part of the encoding and need to be transferred
278/// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
279/// file descriptors and hence the reason, caller must pass a slice of file descriptors.
280pub fn from_slice_with_seed<'d, B, S>(
281 bytes: &'d [u8],
282 ctxt: EncodingContext<B>,
283 seed: S,
284) -> Result<S::Value>
285where
286 B: byteorder::ByteOrder,
287 S: DeserializeSeed<'d> + DynamicType,
288{
289 _from_slice_fds_with_seed(
290 bytes,
291 #[cfg(unix)]
292 None,
293 ctxt,
294 seed,
295 )
296}
297
298/// Deserialize `T` from a given slice of bytes containing file descriptor indices, using the given
299/// seed.
300///
301/// Please note that actual file descriptors are not part of the encoding and need to be transferred
302/// via an out-of-band platform specific mechanism. The encoding only contain the indices of the
303/// file descriptors and hence the reason, caller must pass a slice of file descriptors.
304///
305/// This function is not available on Windows.
306#[cfg(unix)]
307pub fn from_slice_fds_with_seed<'d, B, S>(
308 bytes: &'d [u8],
309 fds: Option<&[RawFd]>,
310 ctxt: EncodingContext<B>,
311 seed: S,
312) -> Result<S::Value>
313where
314 B: byteorder::ByteOrder,
315 S: DeserializeSeed<'d> + DynamicType,
316{
317 _from_slice_fds_with_seed(bytes, fds, ctxt, seed)
318}
319
320fn _from_slice_fds_with_seed<'d, B, S>(
321 bytes: &'d [u8],
322 #[cfg(unix)] fds: Option<&[RawFd]>,
323 ctxt: EncodingContext<B>,
324 seed: S,
325) -> Result<S::Value>
326where
327 B: byteorder::ByteOrder,
328 S: DeserializeSeed<'d> + DynamicType,
329{
330 let signature: Signature<'_> = S::dynamic_signature(&seed).to_owned();
331
332 let mut de: Deserializer<'_, '_, '_, …> = match ctxt.format() {
333 #[cfg(feature = "gvariant")]
334 EncodingFormat::GVariant => Deserializer::GVariant(GVDeserializer::new(
335 bytes,
336 #[cfg(unix)]
337 fds,
338 &signature,
339 ctxt,
340 )),
341 EncodingFormat::DBus => Deserializer::DBus(DBusDeserializer::new(
342 bytes,
343 #[cfg(unix)]
344 fds,
345 &signature,
346 ctxt,
347 )),
348 };
349
350 seed.deserialize(&mut de)
351}
352
353/// Our deserialization implementation.
354#[derive(Debug)]
355pub(crate) struct DeserializerCommon<'de, 'sig, 'f, B> {
356 pub(crate) ctxt: EncodingContext<B>,
357 pub(crate) bytes: &'de [u8],
358
359 #[cfg(unix)]
360 pub(crate) fds: Option<&'f [RawFd]>,
361 #[cfg(not(unix))]
362 pub(crate) fds: PhantomData<&'f ()>,
363
364 pub(crate) pos: usize,
365
366 pub(crate) sig_parser: SignatureParser<'sig>,
367
368 pub(crate) container_depths: ContainerDepths,
369
370 pub(crate) b: PhantomData<B>,
371}
372
373/// Our deserialization implementation.
374///
375/// Using this deserializer involves an redirection to the actual deserializer. It's best
376/// to use the serialization functions, e.g [`crate::to_bytes`] or specific serializers,
377/// [`crate::dbus::Deserializer`] or [`crate::zvariant::Deserializer`].
378pub enum Deserializer<'ser, 'sig, 'f, B> {
379 DBus(DBusDeserializer<'ser, 'sig, 'f, B>),
380 #[cfg(feature = "gvariant")]
381 GVariant(GVDeserializer<'ser, 'sig, 'f, B>),
382}
383
384assert_impl_all!(Deserializer<'_, '_, '_, u8>: Send, Sync, Unpin);
385
386impl<'de, 'sig, 'f, B> Deserializer<'de, 'sig, 'f, B>
387where
388 B: byteorder::ByteOrder,
389{
390 /// Create a Deserializer struct instance.
391 ///
392 /// On Windows, there is no `fds` argument.
393 pub fn new<'r: 'de>(
394 bytes: &'r [u8],
395 #[cfg(unix)] fds: Option<&'f [RawFd]>,
396 signature: &Signature<'sig>,
397 ctxt: EncodingContext<B>,
398 ) -> Self {
399 match ctxt.format() {
400 #[cfg(feature = "gvariant")]
401 EncodingFormat::GVariant => Self::GVariant(GVDeserializer::new(
402 bytes,
403 #[cfg(unix)]
404 fds,
405 signature,
406 ctxt,
407 )),
408 EncodingFormat::DBus => Self::DBus(DBusDeserializer::new(
409 bytes,
410 #[cfg(unix)]
411 fds,
412 signature,
413 ctxt,
414 )),
415 }
416 }
417}
418
419impl<'de, 'sig, 'f, B> DeserializerCommon<'de, 'sig, 'f, B>
420where
421 B: byteorder::ByteOrder,
422{
423 #[cfg(unix)]
424 pub fn get_fd(&self, idx: u32) -> Result<i32> {
425 self.fds
426 .and_then(|fds| fds.get(idx as usize))
427 .copied()
428 .ok_or(Error::UnknownFd)
429 }
430
431 pub fn parse_padding(&mut self, alignment: usize) -> Result<usize> {
432 let padding = padding_for_n_bytes(self.abs_pos(), alignment);
433 if padding > 0 {
434 if self.pos + padding > self.bytes.len() {
435 return Err(serde::de::Error::invalid_length(
436 self.bytes.len(),
437 &format!(">= {}", self.pos + padding).as_str(),
438 ));
439 }
440
441 for i in 0..padding {
442 let byte = self.bytes[self.pos + i];
443 if byte != 0 {
444 return Err(Error::PaddingNot0(byte));
445 }
446 }
447 self.pos += padding;
448 }
449
450 Ok(padding)
451 }
452
453 pub fn prep_deserialize_basic<T>(&mut self) -> Result<()>
454 where
455 T: Basic,
456 {
457 self.sig_parser.skip_char()?;
458 self.parse_padding(T::alignment(self.ctxt.format()))?;
459
460 Ok(())
461 }
462
463 pub fn next_slice(&mut self, len: usize) -> Result<&'de [u8]> {
464 if self.pos + len > self.bytes.len() {
465 return Err(serde::de::Error::invalid_length(
466 self.bytes.len(),
467 &format!(">= {}", self.pos + len).as_str(),
468 ));
469 }
470
471 let slice = &self.bytes[self.pos..self.pos + len];
472 self.pos += len;
473
474 Ok(slice)
475 }
476
477 pub fn next_const_size_slice<T>(&mut self) -> Result<&[u8]>
478 where
479 T: Basic,
480 {
481 self.prep_deserialize_basic::<T>()?;
482
483 self.next_slice(T::alignment(self.ctxt.format()))
484 }
485
486 pub fn abs_pos(&self) -> usize {
487 self.ctxt.position() + self.pos
488 }
489}
490
491macro_rules! deserialize_method {
492 ($method:ident($($arg:ident: $type:ty),*)) => {
493 #[inline]
494 fn $method<V>(self, $($arg: $type,)* visitor: V) -> Result<V::Value>
495 where
496 V: Visitor<'de>,
497 {
498 match self {
499 #[cfg(feature = "gvariant")]
500 Deserializer::GVariant(de) => {
501 de.$method($($arg,)* visitor)
502 }
503 Deserializer::DBus(de) => {
504 de.$method($($arg,)* visitor)
505 }
506 }
507 }
508 }
509}
510
511impl<'de, 'd, 'sig, 'f, B> de::Deserializer<'de> for &'d mut Deserializer<'de, 'sig, 'f, B>
512where
513 B: byteorder::ByteOrder,
514{
515 type Error = Error;
516
517 deserialize_method!(deserialize_any());
518 deserialize_method!(deserialize_bool());
519 deserialize_method!(deserialize_i8());
520 deserialize_method!(deserialize_i16());
521 deserialize_method!(deserialize_i32());
522 deserialize_method!(deserialize_i64());
523 deserialize_method!(deserialize_u8());
524 deserialize_method!(deserialize_u16());
525 deserialize_method!(deserialize_u32());
526 deserialize_method!(deserialize_u64());
527 deserialize_method!(deserialize_f32());
528 deserialize_method!(deserialize_f64());
529 deserialize_method!(deserialize_char());
530 deserialize_method!(deserialize_str());
531 deserialize_method!(deserialize_string());
532 deserialize_method!(deserialize_bytes());
533 deserialize_method!(deserialize_byte_buf());
534 deserialize_method!(deserialize_option());
535 deserialize_method!(deserialize_unit());
536 deserialize_method!(deserialize_unit_struct(n: &'static str));
537 deserialize_method!(deserialize_newtype_struct(n: &'static str));
538 deserialize_method!(deserialize_seq());
539 deserialize_method!(deserialize_map());
540 deserialize_method!(deserialize_tuple(n: usize));
541 deserialize_method!(deserialize_tuple_struct(n: &'static str, l: usize));
542 deserialize_method!(deserialize_struct(
543 n: &'static str,
544 f: &'static [&'static str]
545 ));
546 deserialize_method!(deserialize_enum(
547 n: &'static str,
548 f: &'static [&'static str]
549 ));
550 deserialize_method!(deserialize_identifier());
551 deserialize_method!(deserialize_ignored_any());
552
553 fn is_human_readable(&self) -> bool {
554 false
555 }
556}
557
558#[derive(Debug)]
559pub(crate) enum ValueParseStage {
560 Signature,
561 Value,
562 Done,
563}
564
565pub(crate) fn deserialize_any<'de, 'sig, 'f, D, V>(
566 de: D,
567 next_char: char,
568 visitor: V,
569) -> Result<V::Value>
570where
571 D: de::Deserializer<'de, Error = Error>,
572 V: Visitor<'de>,
573{
574 match next_char {
575 u8::SIGNATURE_CHAR => de.deserialize_u8(visitor),
576 bool::SIGNATURE_CHAR => de.deserialize_bool(visitor),
577 i16::SIGNATURE_CHAR => de.deserialize_i16(visitor),
578 u16::SIGNATURE_CHAR => de.deserialize_u16(visitor),
579 i32::SIGNATURE_CHAR => de.deserialize_i32(visitor),
580 #[cfg(unix)]
581 Fd::SIGNATURE_CHAR => de.deserialize_i32(visitor),
582 u32::SIGNATURE_CHAR => de.deserialize_u32(visitor),
583 i64::SIGNATURE_CHAR => de.deserialize_i64(visitor),
584 u64::SIGNATURE_CHAR => de.deserialize_u64(visitor),
585 f64::SIGNATURE_CHAR => de.deserialize_f64(visitor),
586 <&str>::SIGNATURE_CHAR | ObjectPath::SIGNATURE_CHAR | Signature::SIGNATURE_CHAR => {
587 de.deserialize_str(visitor)
588 }
589 VARIANT_SIGNATURE_CHAR => de.deserialize_seq(visitor),
590 ARRAY_SIGNATURE_CHAR => de.deserialize_seq(visitor),
591 STRUCT_SIG_START_CHAR => de.deserialize_seq(visitor),
592 #[cfg(feature = "gvariant")]
593 MAYBE_SIGNATURE_CHAR => de.deserialize_option(visitor),
594 c => Err(de::Error::invalid_value(
595 de::Unexpected::Char(c),
596 &"a valid signature character",
597 )),
598 }
599}
600
601// Enum handling is very generic so it can be here and specific deserializers can use this.
602pub(crate) struct Enum<B, D> {
603 pub(crate) de: D,
604 pub(crate) name: &'static str,
605 pub(crate) phantom: PhantomData<B>,
606}
607
608impl<'de, B, D> VariantAccess<'de> for Enum<B, D>
609where
610 B: byteorder::ByteOrder,
611 D: de::Deserializer<'de, Error = Error>,
612{
613 type Error = Error;
614
615 fn unit_variant(self) -> std::result::Result<(), Self::Error> {
616 Ok(())
617 }
618
619 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
620 where
621 T: DeserializeSeed<'de>,
622 {
623 seed.deserialize(self.de)
624 }
625
626 fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
627 where
628 V: Visitor<'de>,
629 {
630 de::Deserializer::deserialize_struct(self.de, self.name, &[], visitor)
631 }
632
633 fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
634 where
635 V: Visitor<'de>,
636 {
637 de::Deserializer::deserialize_struct(self.de, self.name, fields, visitor)
638 }
639}
640