zvariant/
de.rs

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 = 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 = 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 = 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 = 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 = 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 = S::dynamic_signature(&seed).to_owned();
331
332    let mut de = 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}