1 use byteorder::WriteBytesExt;
2 use serde::{ser, Serialize};
3 use static_assertions::assert_impl_all;
4 use std::{
5     io::{Seek, Write},
6     marker::PhantomData,
7     os::unix::io::RawFd,
8     str,
9 };
10 
11 #[cfg(feature = "gvariant")]
12 use crate::gvariant::{self, Serializer as GVSerializer};
13 use crate::{
14     dbus::{self, Serializer as DBusSerializer},
15     signature_parser::SignatureParser,
16     utils::*,
17     Basic, DynamicType, EncodingContext, EncodingFormat, Error, Result, Signature,
18 };
19 
20 struct NullWriteSeek;
21 
22 impl Write for NullWriteSeek {
write(&mut self, buf: &[u8]) -> std::io::Result<usize>23     fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
24         Ok(buf.len())
25     }
26 
flush(&mut self) -> std::io::Result<()>27     fn flush(&mut self) -> std::io::Result<()> {
28         Ok(())
29     }
30 }
31 
32 impl Seek for NullWriteSeek {
seek(&mut self, _pos: std::io::SeekFrom) -> std::io::Result<u64>33     fn seek(&mut self, _pos: std::io::SeekFrom) -> std::io::Result<u64> {
34         Ok(std::u64::MAX) // should never read the return value!
35     }
36 }
37 
38 /// Calculate the serialized size of `T`.
39 ///
40 /// # Panics
41 ///
42 /// This function will panic if the value to serialize contains file descriptors. Use
43 /// [`serialized_size_fds`] if `T` (potentially) contains FDs.
44 ///
45 /// # Examples
46 ///
47 /// ```
48 /// use zvariant::{EncodingContext, serialized_size};
49 ///
50 /// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
51 /// let len = serialized_size(ctxt, "hello world").unwrap();
52 /// assert_eq!(len, 16);
53 ///
54 /// let len = serialized_size(ctxt, &("hello world!", 42_u64)).unwrap();
55 /// assert_eq!(len, 32);
56 /// ```
57 ///
58 /// [`serialized_size_fds`]: fn.serialized_size_fds.html
serialized_size<B, T: ?Sized>(ctxt: EncodingContext<B>, value: &T) -> Result<usize> where B: byteorder::ByteOrder, T: Serialize + DynamicType,59 pub fn serialized_size<B, T: ?Sized>(ctxt: EncodingContext<B>, value: &T) -> Result<usize>
60 where
61     B: byteorder::ByteOrder,
62     T: Serialize + DynamicType,
63 {
64     let mut null = NullWriteSeek;
65 
66     to_writer(&mut null, ctxt, value)
67 }
68 
69 /// Calculate the serialized size of `T` that (potentially) contains FDs.
70 ///
71 /// Returns the serialized size of `T` and the number of FDs.
serialized_size_fds<B, T: ?Sized>( ctxt: EncodingContext<B>, value: &T, ) -> Result<(usize, usize)> where B: byteorder::ByteOrder, T: Serialize + DynamicType,72 pub fn serialized_size_fds<B, T: ?Sized>(
73     ctxt: EncodingContext<B>,
74     value: &T,
75 ) -> Result<(usize, usize)>
76 where
77     B: byteorder::ByteOrder,
78     T: Serialize + DynamicType,
79 {
80     let mut null = NullWriteSeek;
81 
82     let (len, fds) = to_writer_fds(&mut null, ctxt, value)?;
83     Ok((len, fds.len()))
84 }
85 
86 /// Serialize `T` to the given `writer`.
87 ///
88 /// This function returns the number of bytes written to the given `writer`.
89 ///
90 /// # Panics
91 ///
92 /// This function will panic if the value to serialize contains file descriptors. Use
93 /// [`to_writer_fds`] if you'd want to potentially pass FDs.
94 ///
95 /// # Examples
96 ///
97 /// ```
98 /// use zvariant::{EncodingContext, from_slice, to_writer};
99 ///
100 /// let ctxt = EncodingContext::<byteorder::LE>::new_dbus(0);
101 /// let mut cursor = std::io::Cursor::new(vec![]);
102 /// to_writer(&mut cursor, ctxt, &42u32).unwrap();
103 /// let value: u32 = from_slice(cursor.get_ref(), ctxt).unwrap();
104 /// assert_eq!(value, 42);
105 /// ```
106 ///
107 /// [`to_writer_fds`]: fn.to_writer_fds.html
to_writer<B, W, T: ?Sized>( writer: &mut W, ctxt: EncodingContext<B>, value: &T, ) -> Result<usize> where B: byteorder::ByteOrder, W: Write + Seek, T: Serialize + DynamicType,108 pub fn to_writer<B, W, T: ?Sized>(
109     writer: &mut W,
110     ctxt: EncodingContext<B>,
111     value: &T,
112 ) -> Result<usize>
113 where
114     B: byteorder::ByteOrder,
115     W: Write + Seek,
116     T: Serialize + DynamicType,
117 {
118     let signature = value.dynamic_signature();
119 
120     to_writer_for_signature(writer, ctxt, &signature, value)
121 }
122 
123 /// Serialize `T` that (potentially) contains FDs, to the given `writer`.
124 ///
125 /// This function returns the number of bytes written to the given `writer` and the file descriptor
126 /// vector, which needs to be transferred via an out-of-band platform specific mechanism.
to_writer_fds<B, W, T: ?Sized>( writer: &mut W, ctxt: EncodingContext<B>, value: &T, ) -> Result<(usize, Vec<RawFd>)> where B: byteorder::ByteOrder, W: Write + Seek, T: Serialize + DynamicType,127 pub fn to_writer_fds<B, W, T: ?Sized>(
128     writer: &mut W,
129     ctxt: EncodingContext<B>,
130     value: &T,
131 ) -> Result<(usize, Vec<RawFd>)>
132 where
133     B: byteorder::ByteOrder,
134     W: Write + Seek,
135     T: Serialize + DynamicType,
136 {
137     let signature = value.dynamic_signature();
138 
139     to_writer_fds_for_signature(writer, ctxt, &signature, value)
140 }
141 
142 /// Serialize `T` as a byte vector.
143 ///
144 /// See [`from_slice`] documentation for an example of how to use this function.
145 ///
146 /// # Panics
147 ///
148 /// This function will panic if the value to serialize contains file descriptors. Use
149 /// [`to_bytes_fds`] if you'd want to potentially pass FDs.
150 ///
151 /// [`to_bytes_fds`]: fn.to_bytes_fds.html
152 /// [`from_slice`]: fn.from_slice.html#examples
to_bytes<B, T: ?Sized>(ctxt: EncodingContext<B>, value: &T) -> Result<Vec<u8>> where B: byteorder::ByteOrder, T: Serialize + DynamicType,153 pub fn to_bytes<B, T: ?Sized>(ctxt: EncodingContext<B>, value: &T) -> Result<Vec<u8>>
154 where
155     B: byteorder::ByteOrder,
156     T: Serialize + DynamicType,
157 {
158     let (bytes, fds) = to_bytes_fds(ctxt, value)?;
159     if !fds.is_empty() {
160         panic!("can't serialize with FDs")
161     }
162 
163     Ok(bytes)
164 }
165 
166 /// Serialize `T` that (potentially) contains FDs, as a byte vector.
167 ///
168 /// The returned file descriptor needs to be transferred via an out-of-band platform specific
169 /// mechanism.
to_bytes_fds<B, T: ?Sized>( ctxt: EncodingContext<B>, value: &T, ) -> Result<(Vec<u8>, Vec<RawFd>)> where B: byteorder::ByteOrder, T: Serialize + DynamicType,170 pub fn to_bytes_fds<B, T: ?Sized>(
171     ctxt: EncodingContext<B>,
172     value: &T,
173 ) -> Result<(Vec<u8>, Vec<RawFd>)>
174 where
175     B: byteorder::ByteOrder,
176     T: Serialize + DynamicType,
177 {
178     let mut cursor = std::io::Cursor::new(vec![]);
179     let (_, fds) = to_writer_fds(&mut cursor, ctxt, value)?;
180     Ok((cursor.into_inner(), fds))
181 }
182 
183 /// Serialize `T` that has the given signature, to the given `writer`.
184 ///
185 /// Use this function instead of [`to_writer`] if the value being serialized does not implement
186 /// [`Type`].
187 ///
188 /// This function returns the number of bytes written to the given `writer`.
189 ///
190 /// [`to_writer`]: fn.to_writer.html
191 /// [`Type`]: trait.Type.html
to_writer_for_signature<B, W, T: ?Sized>( writer: &mut W, ctxt: EncodingContext<B>, signature: &Signature<'_>, value: &T, ) -> Result<usize> where B: byteorder::ByteOrder, W: Write + Seek, T: Serialize,192 pub fn to_writer_for_signature<B, W, T: ?Sized>(
193     writer: &mut W,
194     ctxt: EncodingContext<B>,
195     signature: &Signature<'_>,
196     value: &T,
197 ) -> Result<usize>
198 where
199     B: byteorder::ByteOrder,
200     W: Write + Seek,
201     T: Serialize,
202 {
203     let (len, fds) = to_writer_fds_for_signature(writer, ctxt, signature, value)?;
204     if !fds.is_empty() {
205         panic!("can't serialize with FDs")
206     }
207 
208     Ok(len)
209 }
210 
211 /// Serialize `T` that (potentially) contains FDs and has the given signature, to the given `writer`.
212 ///
213 /// Use this function instead of [`to_writer_fds`] if the value being serialized does not implement
214 /// [`Type`].
215 ///
216 /// This function returns the number of bytes written to the given `writer` and the file descriptor
217 /// vector, which needs to be transferred via an out-of-band platform specific mechanism.
218 ///
219 /// [`to_writer_fds`]: fn.to_writer_fds.html
220 /// [`Type`]: trait.Type.html
to_writer_fds_for_signature<B, W, T: ?Sized>( writer: &mut W, ctxt: EncodingContext<B>, signature: &Signature<'_>, value: &T, ) -> Result<(usize, Vec<RawFd>)> where B: byteorder::ByteOrder, W: Write + Seek, T: Serialize,221 pub fn to_writer_fds_for_signature<B, W, T: ?Sized>(
222     writer: &mut W,
223     ctxt: EncodingContext<B>,
224     signature: &Signature<'_>,
225     value: &T,
226 ) -> Result<(usize, Vec<RawFd>)>
227 where
228     B: byteorder::ByteOrder,
229     W: Write + Seek,
230     T: Serialize,
231 {
232     let mut fds = vec![];
233     match ctxt.format() {
234         EncodingFormat::DBus => {
235             let mut ser = DBusSerializer::<B, W>::new(signature, writer, &mut fds, ctxt);
236             value.serialize(&mut ser)?;
237             Ok((ser.0.bytes_written, fds))
238         }
239         #[cfg(feature = "gvariant")]
240         EncodingFormat::GVariant => {
241             let mut ser = GVSerializer::<B, W>::new(signature, writer, &mut fds, ctxt);
242             value.serialize(&mut ser)?;
243             Ok((ser.0.bytes_written, fds))
244         }
245     }
246 }
247 
248 /// Serialize `T` that has the given signature, to a new byte vector.
249 ///
250 /// Use this function instead of [`to_bytes`] if the value being serialized does not implement
251 /// [`Type`]. See [`from_slice_for_signature`] documentation for an example of how to use this
252 /// function.
253 ///
254 /// # Panics
255 ///
256 /// This function will panic if the value to serialize contains file descriptors. Use
257 /// [`to_bytes_fds_for_signature`] if you'd want to potentially pass FDs.
258 ///
259 /// [`to_bytes`]: fn.to_bytes.html
260 /// [`Type`]: trait.Type.html
261 /// [`from_slice_for_signature`]: fn.from_slice_for_signature.html#examples
to_bytes_for_signature<B, T: ?Sized>( ctxt: EncodingContext<B>, signature: &Signature<'_>, value: &T, ) -> Result<Vec<u8>> where B: byteorder::ByteOrder, T: Serialize,262 pub fn to_bytes_for_signature<B, T: ?Sized>(
263     ctxt: EncodingContext<B>,
264     signature: &Signature<'_>,
265     value: &T,
266 ) -> Result<Vec<u8>>
267 where
268     B: byteorder::ByteOrder,
269     T: Serialize,
270 {
271     let (bytes, fds) = to_bytes_fds_for_signature(ctxt, signature, value)?;
272     if !fds.is_empty() {
273         panic!("can't serialize with FDs")
274     }
275 
276     Ok(bytes)
277 }
278 
279 /// Serialize `T` that (potentially) contains FDs and has the given signature, to a new byte vector.
280 ///
281 /// Use this function instead of [`to_bytes_fds`] if the value being serialized does not implement
282 /// [`Type`].
283 ///
284 /// Please note that the serialized bytes only contain the indices of the file descriptors from the
285 /// returned file descriptor vector, which needs to be transferred via an out-of-band platform
286 /// specific mechanism.
287 ///
288 /// [`to_bytes_fds`]: fn.to_bytes_fds.html
289 /// [`Type`]: trait.Type.html
to_bytes_fds_for_signature<B, T: ?Sized>( ctxt: EncodingContext<B>, signature: &Signature<'_>, value: &T, ) -> Result<(Vec<u8>, Vec<RawFd>)> where B: byteorder::ByteOrder, T: Serialize,290 pub fn to_bytes_fds_for_signature<B, T: ?Sized>(
291     ctxt: EncodingContext<B>,
292     signature: &Signature<'_>,
293     value: &T,
294 ) -> Result<(Vec<u8>, Vec<RawFd>)>
295 where
296     B: byteorder::ByteOrder,
297     T: Serialize,
298 {
299     let mut cursor = std::io::Cursor::new(vec![]);
300     let (_, fds) = to_writer_fds_for_signature(&mut cursor, ctxt, signature, value)?;
301     Ok((cursor.into_inner(), fds))
302 }
303 
304 /// Context for all our serializers and provides shared functionality.
305 pub(crate) struct SerializerCommon<'ser, 'sig, B, W> {
306     pub(crate) ctxt: EncodingContext<B>,
307     pub(crate) writer: &'ser mut W,
308     pub(crate) bytes_written: usize,
309     pub(crate) fds: &'ser mut Vec<RawFd>,
310 
311     pub(crate) sig_parser: SignatureParser<'sig>,
312 
313     pub(crate) value_sign: Option<Signature<'static>>,
314 
315     pub(crate) b: PhantomData<B>,
316 }
317 
318 /// Our serialization implementation.
319 ///
320 /// Using this serializer involves an redirection to the actual serializer. It's best to use the
321 /// serialization functions, e.g [`to_bytes`] or specific serializers, [`dbus::Serializer`] or
322 /// [`zvariant::Serializer`].
323 pub enum Serializer<'ser, 'sig, B, W> {
324     DBus(DBusSerializer<'ser, 'sig, B, W>),
325     #[cfg(feature = "gvariant")]
326     GVariant(GVSerializer<'ser, 'sig, B, W>),
327 }
328 
329 assert_impl_all!(Serializer<'_, '_, i32, i32>: Send, Sync, Unpin);
330 
331 impl<'ser, 'sig, B, W> Serializer<'ser, 'sig, B, W>
332 where
333     B: byteorder::ByteOrder,
334     W: Write + Seek,
335 {
336     /// Create a Serializer struct instance.
new<'w: 'ser, 'f: 'ser>( signature: &Signature<'sig>, writer: &'w mut W, fds: &'f mut Vec<RawFd>, ctxt: EncodingContext<B>, ) -> Self337     pub fn new<'w: 'ser, 'f: 'ser>(
338         signature: &Signature<'sig>,
339         writer: &'w mut W,
340         fds: &'f mut Vec<RawFd>,
341         ctxt: EncodingContext<B>,
342     ) -> Self {
343         match ctxt.format() {
344             #[cfg(feature = "gvariant")]
345             EncodingFormat::GVariant => {
346                 Self::GVariant(GVSerializer::new(signature, writer, fds, ctxt))
347             }
348             EncodingFormat::DBus => Self::DBus(DBusSerializer::new(signature, writer, fds, ctxt)),
349         }
350     }
351 
352     /// Unwrap the `Writer` reference from the `Serializer`.
353     #[inline]
into_inner(self) -> &'ser mut W354     pub fn into_inner(self) -> &'ser mut W {
355         match self {
356             #[cfg(feature = "gvariant")]
357             Self::GVariant(ser) => ser.0.writer,
358             Self::DBus(ser) => ser.0.writer,
359         }
360     }
361 }
362 
363 impl<'ser, 'sig, B, W> SerializerCommon<'ser, 'sig, B, W>
364 where
365     B: byteorder::ByteOrder,
366     W: Write + Seek,
367 {
add_fd(&mut self, fd: RawFd) -> u32368     pub(crate) fn add_fd(&mut self, fd: RawFd) -> u32 {
369         if let Some(idx) = self.fds.iter().position(|&x| x == fd) {
370             return idx as u32;
371         }
372         let idx = self.fds.len();
373         self.fds.push(fd);
374 
375         idx as u32
376     }
377 
add_padding(&mut self, alignment: usize) -> Result<usize>378     pub(crate) fn add_padding(&mut self, alignment: usize) -> Result<usize> {
379         let padding = padding_for_n_bytes(self.abs_pos(), alignment);
380         if padding > 0 {
381             let byte = [0_u8; 1];
382             for _ in 0..padding {
383                 self.write_all(&byte).map_err(Error::Io)?;
384             }
385         }
386 
387         Ok(padding)
388     }
389 
prep_serialize_basic<T>(&mut self) -> Result<()> where T: Basic,390     pub(crate) fn prep_serialize_basic<T>(&mut self) -> Result<()>
391     where
392         T: Basic,
393     {
394         self.sig_parser.skip_char()?;
395         self.add_padding(T::alignment(self.ctxt.format()))?;
396 
397         Ok(())
398     }
399 
prep_serialize_enum_variant(&mut self, variant_index: u32) -> Result<()>400     pub(crate) fn prep_serialize_enum_variant(&mut self, variant_index: u32) -> Result<()> {
401         // Encode enum variants as a struct with first field as variant index
402         self.add_padding(u32::alignment(self.ctxt.format()))?;
403         self.write_u32::<B>(variant_index).map_err(Error::Io)?;
404 
405         Ok(())
406     }
407 
abs_pos(&self) -> usize408     fn abs_pos(&self) -> usize {
409         self.ctxt.position() + self.bytes_written
410     }
411 }
412 
413 impl<'ser, 'sig, B, W> Write for SerializerCommon<'ser, 'sig, B, W>
414 where
415     B: byteorder::ByteOrder,
416     W: Write + Seek,
417 {
418     /// Write `buf` and increment internal bytes written counter.
write(&mut self, buf: &[u8]) -> std::io::Result<usize>419     fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
420         self.writer.write(buf).map(|n| {
421             self.bytes_written += n;
422 
423             n
424         })
425     }
426 
flush(&mut self) -> std::io::Result<()>427     fn flush(&mut self) -> std::io::Result<()> {
428         self.writer.flush()
429     }
430 }
431 
432 macro_rules! serialize_method {
433     ($method:ident($($arg:ident: $type:ty),*)) => {
434         serialize_method!(; $method($($arg: $type),*) => () =);
435     };
436     ($($generic:ident),* ; $method:ident($($arg:ident: $type:ty),*)) => {
437         serialize_method!($($generic),*; $method($($arg: $type),*) => () =);
438     };
439     ($($generic:ident),* ; $method:ident($($arg:ident: $type:ty),*) => $ret:ty = $($map:ident)*) => {
440         #[inline]
441         fn $method<$($generic),*>(self, $($arg: $type),*) -> Result<$ret>
442         where
443             $($generic: ?Sized + Serialize),*
444         {
445             match self {
446                 #[cfg(feature = "gvariant")]
447                 Serializer::GVariant(ser) => {
448                     ser.$method($($arg),*)$(.map($map::GVariant))*
449                 }
450                 Serializer::DBus(ser) => {
451                     ser.$method($($arg),*)$(.map($map::DBus))*
452                 }
453             }
454         }
455     }
456 }
457 
458 impl<'ser, 'sig, 'b, B, W> ser::Serializer for &'b mut Serializer<'ser, 'sig, B, W>
459 where
460     B: byteorder::ByteOrder,
461     W: Write + Seek,
462 {
463     type Ok = ();
464     type Error = Error;
465 
466     type SerializeSeq = SeqSerializer<'ser, 'sig, 'b, B, W>;
467     type SerializeTuple = StructSerializer<'ser, 'sig, 'b, B, W>;
468     type SerializeTupleStruct = StructSerializer<'ser, 'sig, 'b, B, W>;
469     type SerializeTupleVariant = StructSerializer<'ser, 'sig, 'b, B, W>;
470     type SerializeMap = SeqSerializer<'ser, 'sig, 'b, B, W>;
471     type SerializeStruct = StructSerializer<'ser, 'sig, 'b, B, W>;
472     type SerializeStructVariant = StructSerializer<'ser, 'sig, 'b, B, W>;
473 
474     serialize_method!(serialize_bool(b: bool));
475     serialize_method!(serialize_i8(i: i8));
476     serialize_method!(serialize_i16(i: i16));
477     serialize_method!(serialize_i32(i: i32));
478     serialize_method!(serialize_i64(i: i64));
479     serialize_method!(serialize_u8(u: u8));
480     serialize_method!(serialize_u16(u: u16));
481     serialize_method!(serialize_u32(u: u32));
482     serialize_method!(serialize_u64(u: u64));
483     serialize_method!(serialize_f32(f: f32));
484     serialize_method!(serialize_f64(f: f64));
485     serialize_method!(serialize_char(c: char));
486     serialize_method!(serialize_str(s: &str));
487     serialize_method!(serialize_bytes(b: &[u8]));
488     serialize_method!(T; serialize_some(v: &T));
489     serialize_method!(serialize_none());
490     serialize_method!(serialize_unit());
491     serialize_method!(serialize_unit_struct(s: &'static str));
492     serialize_method!(serialize_unit_variant(
493         n: &'static str,
494         i: u32,
495         v: &'static str
496     ));
497     serialize_method!(T; serialize_newtype_struct(n: &'static str, v: &T));
498     serialize_method!(T; serialize_newtype_variant(n: &'static str, i: u32, va: &'static str, v: &T));
499     serialize_method!(; serialize_seq(l: Option<usize>) => Self::SerializeSeq = SeqSerializer);
500     serialize_method!(; serialize_tuple_variant(
501         n: &'static str,
502         i: u32,
503         v: &'static str,
504         l: usize
505     ) => Self::SerializeTupleVariant = StructSerializer);
506     serialize_method!(;serialize_struct_variant(
507         n: &'static str,
508         i: u32,
509         v: &'static str,
510         l: usize
511     ) => Self::SerializeStructVariant = StructSerializer);
512     serialize_method!(; serialize_tuple(l: usize) => Self::SerializeTuple = StructSerializer);
513     serialize_method!(; serialize_tuple_struct(
514         n: &'static str,
515         l: usize
516     ) => Self::SerializeTupleStruct = StructSerializer);
517     serialize_method!(; serialize_map(l: Option<usize>) => Self::SerializeMap = SeqSerializer);
518     serialize_method!(; serialize_struct(
519         n: &'static str,
520         l: usize
521     ) => Self::SerializeStruct = StructSerializer);
522 }
523 
524 macro_rules! serialize_impl {
525     ($trait:ident, $impl:ident, $($method:ident($($arg:ident: $type:ty),*))+) => {
526         impl<'ser, 'sig, 'b, B, W> ser::$trait for $impl<'ser, 'sig, 'b, B, W>
527         where
528             B: byteorder::ByteOrder,
529             W: Write + Seek,
530         {
531             type Ok = ();
532             type Error = Error;
533 
534             $(
535                 fn $method<T>(&mut self, $($arg: $type),*) -> Result<()>
536                 where
537                     T: ?Sized + Serialize,
538                 {
539                     match self {
540                         #[cfg(feature = "gvariant")]
541                         $impl::GVariant(ser) => ser.$method($($arg),*),
542                         $impl::DBus(ser) => ser.$method($($arg),*),
543                     }
544                 }
545             )*
546 
547             fn end(self) -> Result<()> {
548                 match self {
549                     #[cfg(feature = "gvariant")]
550                     $impl::GVariant(ser) => ser.end(),
551                     $impl::DBus(ser) => ser.end(),
552                 }
553             }
554         }
555     }
556 }
557 
558 #[doc(hidden)]
559 pub enum SeqSerializer<'ser, 'sig, 'b, B, W> {
560     DBus(dbus::SeqSerializer<'ser, 'sig, 'b, B, W>),
561     #[cfg(feature = "gvariant")]
562     GVariant(gvariant::SeqSerializer<'ser, 'sig, 'b, B, W>),
563 }
564 
565 serialize_impl!(SerializeSeq, SeqSerializer, serialize_element(value: &T));
566 
567 #[doc(hidden)]
568 pub enum StructSerializer<'ser, 'sig, 'b, B, W> {
569     DBus(dbus::StructSerializer<'ser, 'sig, 'b, B, W>),
570     #[cfg(feature = "gvariant")]
571     GVariant(gvariant::StructSerializer<'ser, 'sig, 'b, B, W>),
572 }
573 
574 serialize_impl!(SerializeTuple, StructSerializer, serialize_element(v: &T));
575 serialize_impl!(
576     SerializeTupleStruct,
577     StructSerializer,
578     serialize_field(v: &T)
579 );
580 serialize_impl!(
581     SerializeTupleVariant,
582     StructSerializer,
583     serialize_field(v: &T)
584 );
585 serialize_impl!(
586     SerializeStruct,
587     StructSerializer,
588     serialize_field(k: &'static str, v: &T)
589 );
590 serialize_impl!(
591     SerializeStructVariant,
592     StructSerializer,
593     serialize_field(k: &'static str, v: &T)
594 );
595 serialize_impl!(SerializeMap, SeqSerializer, serialize_key(v: &T) serialize_value(v: &T));
596