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