Skip to main content

zvariant/dbus/
ser.rs

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