zvariant/dbus/
ser.rs

1use serde::{
2    ser::{self, SerializeMap, SerializeSeq, SerializeTuple},
3    Serialize,
4};
5use std::{
6    io::{Seek, Write},
7    str::{self, FromStr},
8};
9
10use crate::{
11    container_depths::ContainerDepths,
12    serialized::{Context, Format},
13    utils::*,
14    Basic, Error, ObjectPath, Result, Signature, WriteBytes,
15};
16
17/// Our D-Bus serialization implementation.
18pub(crate) struct Serializer<'ser, W>(pub(crate) crate::SerializerCommon<'ser, W>);
19
20impl<'ser, W> Serializer<'ser, W>
21where
22    W: Write + Seek,
23{
24    /// Create a D-Bus Serializer struct instance.
25    ///
26    /// On Windows, there is no `fds` argument.
27    pub fn new<'w: 'ser, 'f: 'ser>(
28        signature: &'ser Signature,
29        writer: &'w mut W,
30        #[cfg(unix)] fds: &'f mut crate::ser::FdList,
31        ctxt: Context,
32    ) -> Result<Self> {
33        assert_eq!(ctxt.format(), Format::DBus);
34
35        Ok(Self(crate::SerializerCommon {
36            ctxt,
37            signature,
38            writer,
39            #[cfg(unix)]
40            fds,
41            bytes_written: 0,
42            value_sign: None,
43            container_depths: Default::default(),
44        }))
45    }
46}
47
48macro_rules! serialize_basic {
49    ($method:ident($type:ty) $write_method:ident) => {
50        serialize_basic!($method($type) $write_method($type));
51    };
52    ($method:ident($type:ty) $write_method:ident($as:ty)) => {
53        fn $method(self, v: $type) -> Result<()> {
54            self.0.prep_serialize_basic::<$type>()?;
55            self.0.$write_method(self.0.ctxt.endian(), v as $as).map_err(|e| Error::InputOutput(e.into()))
56        }
57    };
58}
59
60impl<'ser, 'b, W> ser::Serializer for &'b mut Serializer<'ser, W>
61where
62    W: Write + Seek,
63{
64    type Ok = ();
65    type Error = Error;
66
67    type SerializeSeq = SeqSerializer<'ser, 'b, W>;
68    type SerializeTuple = StructSeqSerializer<'ser, 'b, W>;
69    type SerializeTupleStruct = StructSeqSerializer<'ser, 'b, W>;
70    type SerializeTupleVariant = StructSeqSerializer<'ser, 'b, W>;
71    type SerializeMap = MapSerializer<'ser, 'b, W>;
72    type SerializeStruct = StructSeqSerializer<'ser, 'b, W>;
73    type SerializeStructVariant = StructSeqSerializer<'ser, 'b, W>;
74
75    serialize_basic!(serialize_bool(bool) write_u32(u32));
76    // No i8 type in D-Bus/GVariant, let's pretend it's i16
77    serialize_basic!(serialize_i8(i8) write_i16(i16));
78    serialize_basic!(serialize_i16(i16) write_i16);
79    serialize_basic!(serialize_i64(i64) write_i64);
80
81    fn serialize_i32(self, v: i32) -> Result<()> {
82        match &self.0.signature {
83            #[cfg(unix)]
84            Signature::Fd => {
85                self.0.add_padding(u32::alignment(Format::DBus))?;
86                let idx = self.0.add_fd(v)?;
87                self.0
88                    .write_u32(self.0.ctxt.endian(), idx)
89                    .map_err(|e| Error::InputOutput(e.into()))
90            }
91            _ => {
92                self.0.prep_serialize_basic::<i32>()?;
93                self.0
94                    .write_i32(self.0.ctxt.endian(), v)
95                    .map_err(|e| Error::InputOutput(e.into()))
96            }
97        }
98    }
99
100    fn serialize_u8(self, v: u8) -> Result<()> {
101        self.0.prep_serialize_basic::<u8>()?;
102        // Endianness is irrelevant for single bytes.
103        self.0
104            .write_u8(self.0.ctxt.endian(), v)
105            .map_err(|e| Error::InputOutput(e.into()))
106    }
107
108    serialize_basic!(serialize_u16(u16) write_u16);
109    serialize_basic!(serialize_u32(u32) write_u32);
110    serialize_basic!(serialize_u64(u64) write_u64);
111    // No f32 type in D-Bus/GVariant, let's pretend it's f64
112    serialize_basic!(serialize_f32(f32) write_f64(f64));
113    serialize_basic!(serialize_f64(f64) write_f64);
114
115    fn serialize_char(self, v: char) -> Result<()> {
116        // No char type in D-Bus, let's pretend it's a string
117        self.serialize_str(&v.to_string())
118    }
119
120    fn serialize_str(self, v: &str) -> Result<()> {
121        self.0
122            .add_padding(self.0.signature.alignment(Format::DBus))?;
123
124        let signature = self.0.signature;
125        if matches!(signature, Signature::Variant) {
126            self.0.value_sign = Some(Signature::from_str(v)?);
127        }
128
129        match signature {
130            Signature::ObjectPath | Signature::Str => {
131                self.0
132                    .write_u32(self.0.ctxt.endian(), usize_to_u32(v.len()))
133                    .map_err(|e| Error::InputOutput(e.into()))?;
134            }
135            Signature::Signature | Signature::Variant => {
136                self.0
137                    .write_u8(self.0.ctxt.endian(), usize_to_u8(v.len()))
138                    .map_err(|e| Error::InputOutput(e.into()))?;
139            }
140            _ => {
141                let expected = format!(
142                    "`{}`, `{}`, `{}` or `{}`",
143                    <&str>::SIGNATURE_STR,
144                    Signature::SIGNATURE_STR,
145                    ObjectPath::SIGNATURE_STR,
146                    VARIANT_SIGNATURE_CHAR,
147                );
148                return Err(Error::SignatureMismatch(signature.clone(), expected));
149            }
150        }
151
152        self.0
153            .write_all(v.as_bytes())
154            .map_err(|e| Error::InputOutput(e.into()))?;
155        self.0
156            .write_all(&b"\0"[..])
157            .map_err(|e| Error::InputOutput(e.into()))?;
158
159        Ok(())
160    }
161
162    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
163        self.0.add_padding(ARRAY_ALIGNMENT_DBUS)?;
164        self.0
165            .write_u32(self.0.ctxt.endian(), v.len() as u32)
166            .map_err(|e| Error::InputOutput(e.into()))?;
167        self.0
168            .write(v)
169            .map(|_| ())
170            .map_err(|e| Error::InputOutput(e.into()))
171    }
172
173    fn serialize_none(self) -> Result<()> {
174        #[cfg(feature = "option-as-array")]
175        {
176            let seq = self.serialize_seq(Some(0))?;
177            seq.end()
178        }
179
180        #[cfg(not(feature = "option-as-array"))]
181        unreachable!(
182            "Can only encode Option<T> in D-Bus format if `option-as-array` feature is enabled",
183        );
184    }
185
186    fn serialize_some<T>(self, #[allow(unused)] value: &T) -> Result<()>
187    where
188        T: ?Sized + Serialize,
189    {
190        #[cfg(feature = "option-as-array")]
191        {
192            let mut seq = self.serialize_seq(Some(1))?;
193            seq.serialize_element(value)?;
194            seq.end()
195        }
196
197        #[cfg(not(feature = "option-as-array"))]
198        unreachable!(
199            "Can only encode Option<T> in D-Bus format if `option-as-array` feature is enabled",
200        );
201    }
202
203    fn serialize_unit(self) -> Result<()> {
204        Ok(())
205    }
206
207    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
208        self.serialize_unit()
209    }
210
211    fn serialize_unit_variant(
212        self,
213        _name: &'static str,
214        variant_index: u32,
215        variant: &'static str,
216    ) -> Result<()> {
217        if matches!(self.0.signature, Signature::Str) {
218            variant.serialize(self)
219        } else {
220            variant_index.serialize(self)
221        }
222    }
223
224    fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
225    where
226        T: ?Sized + Serialize,
227    {
228        value.serialize(self)?;
229
230        Ok(())
231    }
232
233    fn serialize_newtype_variant<T>(
234        self,
235        _name: &'static str,
236        variant_index: u32,
237        _variant: &'static str,
238        value: &T,
239    ) -> Result<()>
240    where
241        T: ?Sized + Serialize,
242    {
243        StructSerializer::enum_variant(self, variant_index)
244            .and_then(|mut ser| ser.serialize_element(value))
245    }
246
247    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
248        self.0.add_padding(ARRAY_ALIGNMENT_DBUS)?;
249        // Length in bytes (unfortunately not the same as len passed to us here) which we
250        // initially set to 0.
251        self.0
252            .write_u32(self.0.ctxt.endian(), 0_u32)
253            .map_err(|e| Error::InputOutput(e.into()))?;
254
255        // D-Bus expects us to add padding for the first element even when there is no first
256        // element (i-e empty array) so we add padding already.
257        let (alignment, child_signature) = match self.0.signature {
258            Signature::Array(child) => (child.alignment(self.0.ctxt.format()), child.signature()),
259            Signature::Dict { key, .. } => (DICT_ENTRY_ALIGNMENT_DBUS, key.signature()),
260            _ => {
261                return Err(Error::SignatureMismatch(
262                    self.0.signature.clone(),
263                    "an array or dict".to_string(),
264                ));
265            }
266        };
267
268        // In case of an array, we'll only be serializing the array's child elements from now on and
269        // in case of a dict, we'll swap key and value signatures during serlization of each entry,
270        // so let's assume the element signature for array and key signature for dict, from now on.
271        // We restore the original signature at the end of serialization.
272        let array_signature = self.0.signature;
273        self.0.signature = child_signature;
274        let first_padding = self.0.add_padding(alignment)?;
275        let start = self.0.bytes_written;
276        self.0.container_depths = self.0.container_depths.inc_array()?;
277
278        Ok(SeqSerializer {
279            ser: self,
280            start,
281            first_padding,
282            array_signature,
283        })
284    }
285
286    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
287        self.serialize_struct("", len)
288    }
289
290    fn serialize_tuple_struct(
291        self,
292        name: &'static str,
293        len: usize,
294    ) -> Result<Self::SerializeTupleStruct> {
295        self.serialize_struct(name, len)
296    }
297
298    fn serialize_tuple_variant(
299        self,
300        _name: &'static str,
301        variant_index: u32,
302        _variant: &'static str,
303        _len: usize,
304    ) -> Result<Self::SerializeTupleVariant> {
305        StructSerializer::enum_variant(self, variant_index).map(StructSeqSerializer::Struct)
306    }
307
308    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
309        let (key_signature, value_signature) = match self.0.signature {
310            Signature::Dict { key, value } => (key.signature(), value.signature()),
311            _ => {
312                return Err(Error::SignatureMismatch(
313                    self.0.signature.clone(),
314                    "a dict".to_string(),
315                ));
316            }
317        };
318
319        let seq = self.serialize_seq(len)?;
320
321        Ok(MapSerializer {
322            seq,
323            key_signature,
324            value_signature,
325        })
326    }
327
328    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
329        self.0
330            .add_padding(self.0.signature.alignment(self.0.ctxt.format()))?;
331        match &self.0.signature {
332            Signature::Variant => StructSerializer::variant(self).map(StructSeqSerializer::Struct),
333            Signature::Array(_) => self.serialize_seq(Some(len)).map(StructSeqSerializer::Seq),
334            Signature::U8 => StructSerializer::unit(self).map(StructSeqSerializer::Struct),
335            Signature::Structure(_) => {
336                StructSerializer::structure(self).map(StructSeqSerializer::Struct)
337            }
338            Signature::Dict { .. } => self.serialize_map(Some(len)).map(StructSeqSerializer::Map),
339            _ => Err(Error::SignatureMismatch(
340                self.0.signature.clone(),
341                "a struct, array, u8 or variant".to_string(),
342            )),
343        }
344    }
345
346    fn serialize_struct_variant(
347        self,
348        _name: &'static str,
349        variant_index: u32,
350        _variant: &'static str,
351        _len: usize,
352    ) -> Result<Self::SerializeStructVariant> {
353        StructSerializer::enum_variant(self, variant_index).map(StructSeqSerializer::Struct)
354    }
355
356    fn is_human_readable(&self) -> bool {
357        false
358    }
359}
360
361#[doc(hidden)]
362pub struct SeqSerializer<'ser, 'b, W> {
363    ser: &'b mut Serializer<'ser, W>,
364    start: usize,
365    // First element's padding
366    first_padding: usize,
367    array_signature: &'ser Signature,
368}
369
370impl<W> SeqSerializer<'_, '_, W>
371where
372    W: Write + Seek,
373{
374    pub(self) fn end_seq(self) -> Result<()> {
375        // Set size of array in bytes
376        let array_len = self.ser.0.bytes_written - self.start;
377        let len = usize_to_u32(array_len);
378        let total_array_len = (array_len + self.first_padding + 4) as i64;
379        self.ser
380            .0
381            .writer
382            .seek(std::io::SeekFrom::Current(-total_array_len))
383            .map_err(|e| Error::InputOutput(e.into()))?;
384        self.ser
385            .0
386            .writer
387            .write_u32(self.ser.0.ctxt.endian(), len)
388            .map_err(|e| Error::InputOutput(e.into()))?;
389        self.ser
390            .0
391            .writer
392            .seek(std::io::SeekFrom::Current(total_array_len - 4))
393            .map_err(|e| Error::InputOutput(e.into()))?;
394
395        self.ser.0.container_depths = self.ser.0.container_depths.dec_array();
396        self.ser.0.signature = self.array_signature;
397
398        Ok(())
399    }
400}
401
402impl<W> ser::SerializeSeq for SeqSerializer<'_, '_, W>
403where
404    W: Write + Seek,
405{
406    type Ok = ();
407    type Error = Error;
408
409    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
410    where
411        T: ?Sized + Serialize,
412    {
413        value.serialize(&mut *self.ser)
414    }
415
416    fn end(self) -> Result<()> {
417        self.end_seq()
418    }
419}
420
421#[doc(hidden)]
422pub struct StructSerializer<'ser, 'b, W> {
423    ser: &'b mut Serializer<'ser, W>,
424    // The original container depths. We restore to that at the end.
425    container_depths: ContainerDepths,
426    // Index of the next field to serialize.
427    field_idx: usize,
428}
429
430impl<'ser, 'b, W> StructSerializer<'ser, 'b, W>
431where
432    W: Write + Seek,
433{
434    fn variant(ser: &'b mut Serializer<'ser, W>) -> Result<Self> {
435        let container_depths = ser.0.container_depths;
436        ser.0.container_depths = ser.0.container_depths.inc_variant()?;
437
438        Ok(Self {
439            ser,
440            container_depths,
441            field_idx: 0,
442        })
443    }
444
445    fn structure(ser: &'b mut Serializer<'ser, W>) -> Result<Self> {
446        let container_depths = ser.0.container_depths;
447        ser.0.container_depths = ser.0.container_depths.inc_structure()?;
448
449        Ok(Self {
450            ser,
451            container_depths,
452            field_idx: 0,
453        })
454    }
455
456    fn unit(ser: &'b mut Serializer<'ser, W>) -> Result<Self> {
457        // serialize as a `0u8`
458        serde::Serializer::serialize_u8(&mut *ser, 0)?;
459
460        let container_depths = ser.0.container_depths;
461        Ok(Self {
462            ser,
463            container_depths,
464            field_idx: 0,
465        })
466    }
467
468    fn enum_variant(ser: &'b mut Serializer<'ser, W>, variant_index: u32) -> Result<Self> {
469        // Encode enum variants as a struct with first field as variant index
470        let Signature::Structure(fields) = ser.0.signature else {
471            return Err(Error::SignatureMismatch(
472                ser.0.signature.clone(),
473                "a struct".to_string(),
474            ));
475        };
476        let struct_field = fields.iter().nth(1).and_then(|f| {
477            if matches!(f, Signature::Structure(_)) {
478                Some(f)
479            } else {
480                None
481            }
482        });
483
484        ser.0.add_padding(STRUCT_ALIGNMENT_DBUS)?;
485        let mut struct_ser = Self::structure(ser)?;
486        struct_ser.serialize_struct_element(&variant_index)?;
487
488        if let Some(field) = struct_field {
489            // Add struct padding for inner struct and pretend we're the inner struct.
490            struct_ser.ser.0.add_padding(STRUCT_ALIGNMENT_DBUS)?;
491            struct_ser.field_idx = 0;
492            struct_ser.ser.0.signature = field;
493        }
494
495        Ok(struct_ser)
496    }
497
498    fn serialize_struct_element<T>(&mut self, value: &T) -> Result<()>
499    where
500        T: ?Sized + Serialize,
501    {
502        let signature = self.ser.0.signature;
503        let field_signature = match signature {
504            Signature::Variant => {
505                match &self.ser.0.value_sign {
506                    // Serializing the value of a Value, which means signature was serialized
507                    // already, and also put aside for us to be picked here.
508                    Some(signature) => signature,
509                    // Serializing the signature of a Value.
510                    None => &Signature::Variant,
511                }
512            }
513            Signature::Structure(fields) => {
514                let signature = fields.iter().nth(self.field_idx).ok_or_else(|| {
515                    Error::SignatureMismatch(signature.clone(), "a struct".to_string())
516                })?;
517                self.field_idx += 1;
518
519                signature
520            }
521            _ => unreachable!("Incorrect signature for struct"),
522        };
523        let bytes_written = self.ser.0.bytes_written;
524        let mut ser = Serializer(crate::SerializerCommon::<W> {
525            ctxt: self.ser.0.ctxt,
526            signature: field_signature,
527            writer: self.ser.0.writer,
528            #[cfg(unix)]
529            fds: self.ser.0.fds,
530            bytes_written,
531            value_sign: None,
532            container_depths: self.ser.0.container_depths,
533        });
534
535        value.serialize(&mut ser)?;
536        self.ser.0.bytes_written = ser.0.bytes_written;
537        self.ser.0.value_sign = ser.0.value_sign;
538
539        Ok(())
540    }
541
542    fn end_struct(self) -> Result<()> {
543        // Restore the original container depths.
544        self.ser.0.container_depths = self.container_depths;
545
546        Ok(())
547    }
548}
549
550#[doc(hidden)]
551/// Allows us to serialize a struct as an ARRAY.
552pub enum StructSeqSerializer<'ser, 'b, W> {
553    Struct(StructSerializer<'ser, 'b, W>),
554    Seq(SeqSerializer<'ser, 'b, W>),
555    Map(MapSerializer<'ser, 'b, W>),
556}
557
558macro_rules! serialize_struct_anon_fields {
559    ($trait:ident $method:ident) => {
560        impl<'ser, 'b, W> ser::$trait for StructSerializer<'ser, 'b, W>
561        where
562            W: Write + Seek,
563        {
564            type Ok = ();
565            type Error = Error;
566
567            fn $method<T>(&mut self, value: &T) -> Result<()>
568            where
569                T: ?Sized + Serialize,
570            {
571                self.serialize_struct_element(value)
572            }
573
574            fn end(self) -> Result<()> {
575                self.end_struct()
576            }
577        }
578
579        impl<'ser, 'b, W> ser::$trait for StructSeqSerializer<'ser, 'b, W>
580        where
581            W: Write + Seek,
582        {
583            type Ok = ();
584            type Error = Error;
585
586            fn $method<T>(&mut self, value: &T) -> Result<()>
587            where
588                T: ?Sized + Serialize,
589            {
590                match self {
591                    StructSeqSerializer::Struct(ser) => ser.$method(value),
592                    StructSeqSerializer::Seq(ser) => ser.serialize_element(value),
593                    StructSeqSerializer::Map(_) => unreachable!(),
594                }
595            }
596
597            fn end(self) -> Result<()> {
598                match self {
599                    StructSeqSerializer::Struct(ser) => ser.end_struct(),
600                    StructSeqSerializer::Seq(ser) => ser.end_seq(),
601                    StructSeqSerializer::Map(_) => unreachable!(),
602                }
603            }
604        }
605    };
606}
607serialize_struct_anon_fields!(SerializeTuple serialize_element);
608serialize_struct_anon_fields!(SerializeTupleStruct serialize_field);
609serialize_struct_anon_fields!(SerializeTupleVariant serialize_field);
610
611pub struct MapSerializer<'ser, 'b, W> {
612    seq: SeqSerializer<'ser, 'b, W>,
613    key_signature: &'ser Signature,
614    value_signature: &'ser Signature,
615}
616
617impl<W> SerializeMap for MapSerializer<'_, '_, W>
618where
619    W: Write + Seek,
620{
621    type Ok = ();
622    type Error = Error;
623
624    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
625    where
626        T: ?Sized + Serialize,
627    {
628        self.seq.ser.0.add_padding(DICT_ENTRY_ALIGNMENT_DBUS)?;
629
630        key.serialize(&mut *self.seq.ser)
631    }
632
633    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
634    where
635        T: ?Sized + Serialize,
636    {
637        self.seq.ser.0.signature = self.value_signature;
638        value.serialize(&mut *self.seq.ser)?;
639        self.seq.ser.0.signature = self.key_signature;
640
641        Ok(())
642    }
643
644    fn end(self) -> Result<()> {
645        self.seq.end_seq()
646    }
647}
648
649macro_rules! serialize_struct_named_fields {
650    ($trait:ident) => {
651        impl<'ser, 'b, W> ser::$trait for StructSerializer<'ser, 'b, W>
652        where
653            W: Write + Seek,
654        {
655            type Ok = ();
656            type Error = Error;
657
658            fn serialize_field<T>(&mut self, _key: &'static str, value: &T) -> Result<()>
659            where
660                T: ?Sized + Serialize,
661            {
662                self.serialize_struct_element(value)
663            }
664
665            fn end(self) -> Result<()> {
666                self.end_struct()
667            }
668        }
669
670        impl<'ser, 'b, W> ser::$trait for StructSeqSerializer<'ser, 'b, W>
671        where
672            W: Write + Seek,
673        {
674            type Ok = ();
675            type Error = Error;
676
677            fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
678            where
679                T: ?Sized + Serialize,
680            {
681                match self {
682                    StructSeqSerializer::Struct(ser) => ser.serialize_field(key, value),
683                    StructSeqSerializer::Seq(ser) => ser.serialize_element(value),
684                    StructSeqSerializer::Map(ser) => {
685                        ser.serialize_key(key)?;
686                        ser.serialize_value(value)
687                    }
688                }
689            }
690
691            fn end(self) -> Result<()> {
692                match self {
693                    StructSeqSerializer::Struct(ser) => ser.end_struct(),
694                    StructSeqSerializer::Seq(ser) => ser.end_seq(),
695                    StructSeqSerializer::Map(ser) => ser.end(),
696                }
697            }
698        }
699    };
700}
701serialize_struct_named_fields!(SerializeStruct);
702serialize_struct_named_fields!(SerializeStructVariant);