libspa/pod/
serialize.rs

1//! This module deals with serializing rust types into raw SPA pods.
2//!
3//! A raw pod can be serialized by passing a implementor of the [`PodSerialize`] trait
4//! to [`PodSerializer::serialize`].
5//!
6//! The crate provides a number of implementors of this trait either directly,
7//! or through [`FixedSizedPod`](`super::FixedSizedPod`).
8//!
9//! You can also implement the [`PodSerialize`] trait on another type yourself. See the traits documentation for more
10//! information on how to do that.
11
12use std::{
13    convert::TryInto,
14    ffi::CString,
15    io::{Seek, SeekFrom, Write},
16    marker::PhantomData,
17};
18
19pub use cookie_factory::GenError;
20use cookie_factory::{
21    bytes::{ne_u32, ne_u64, ne_u8},
22    combinator::slice,
23    gen,
24    multi::all,
25    sequence::{pair, tuple},
26    SerializeFn,
27};
28
29use crate::{
30    pod::ChoiceValue,
31    utils::{Choice, ChoiceEnum},
32};
33
34use super::{CanonicalFixedSizedPod, FixedSizedPod, PropertyFlags, Value, ValueArray};
35
36/// Implementors of this trait are able to serialize themselves into a SPA pod by using a [`PodSerializer`].
37///
38/// Their [`serialize`](`PodSerialize::serialize`) method should invoke exactly one of the `serialize_*()` methods
39/// of the provided [`PodSerializer`] that fits the type that will be serialized.
40///
41/// If you want to serialize into a pod that always has the same size, implement [`FixedSizedPod`] instead
42/// and this trait will be implemented for you automatically.
43///
44/// # Examples
45/// Make a type serialize into a `String` pod.
46/// ```rust
47/// use std::io;
48/// use libspa::pod::serialize::{GenError, PodSerialize, PodSerializer, SerializeSuccess};
49///
50/// struct StringNewtype(String);
51///
52/// impl PodSerialize for StringNewtype {
53///     fn serialize<O: io::Write + io::Seek>(
54///         &self,
55///         serializer: PodSerializer<O>,
56///     ) -> Result<SerializeSuccess<O>, GenError> {
57///         serializer.serialize_string(self.0.as_str())
58///     }
59/// }
60/// ```
61/// `Bytes` pods are created in the same way, but with the `serialize_bytes` method.
62///
63/// Make a type serialize into a `Array` pod with `Int` pod elements:
64/// ```rust
65/// use std::io;
66/// use libspa::pod::serialize::{GenError, PodSerialize, PodSerializer, SerializeSuccess};
67///
68/// struct Numbers(Vec<i32>);
69///
70/// impl PodSerialize for Numbers {
71///     fn serialize<O: io::Write + io::Seek>(
72///         &self,
73///         serializer: PodSerializer<O>,
74///     ) -> Result<SerializeSuccess<O>, GenError> {
75///         let mut array_serializer = serializer.serialize_array(self.0.len() as u32)?;
76///         for element in self.0.iter() {
77///             array_serializer.serialize_element(element)?;
78///         }
79///         array_serializer.end()
80///     }
81/// }
82/// ```
83///
84/// Make a struct serialize into a `Struct` pod:
85/// ```rust
86/// use std::io;
87/// use libspa::pod::serialize::{GenError, PodSerialize, PodSerializer, SerializeSuccess};
88///
89/// struct Animal {
90///     name: String,
91///     feet: u8,
92///     can_fly: bool,
93/// }
94///
95/// impl PodSerialize for Animal {
96///     fn serialize<O: io::Write + io::Seek>(
97///         &self,
98///         serializer: PodSerializer<O>,
99///     ) -> Result<SerializeSuccess<O>, GenError> {
100///         let mut struct_serializer = serializer.serialize_struct()?;
101///         struct_serializer.serialize_field(self.name.as_str())?;
102///         // No pod exists for u8, we need to use an `Int` type pod by casting to `i32`.
103///         struct_serializer.serialize_field(&(self.feet as i32))?;
104///         struct_serializer.serialize_field(&self.can_fly)?;
105///         struct_serializer.end()
106///     }
107/// }
108/// ```
109pub trait PodSerialize {
110    /// Serialize the type by using the provided [`PodSerializer`]
111    fn serialize<O: Write + Seek>(
112        &self,
113        serializer: PodSerializer<O>,
114    ) -> Result<SerializeSuccess<O>, GenError>;
115}
116
117// Serialize into a `String` pod.
118impl PodSerialize for str {
119    fn serialize<O: Write + Seek>(
120        &self,
121        serializer: PodSerializer<O>,
122    ) -> Result<SerializeSuccess<O>, GenError> {
123        serializer.serialize_string(self)
124    }
125}
126
127// Serialize into a `Bytes` pod.
128impl PodSerialize for [u8] {
129    fn serialize<O: Write + Seek>(
130        &self,
131        serializer: PodSerializer<O>,
132    ) -> Result<SerializeSuccess<O>, GenError> {
133        serializer.serialize_bytes(self)
134    }
135}
136
137// Serialize into the kind of pod represented by the value.
138impl PodSerialize for Value {
139    fn serialize<O: Write + Seek>(
140        &self,
141        serializer: PodSerializer<O>,
142    ) -> Result<SerializeSuccess<O>, GenError> {
143        /// Helper function that fully serializes an array containing FixedSizedPod elements.
144        fn serialize_array<E: FixedSizedPod, O: Write + Seek>(
145            array: &[E],
146            serializer: PodSerializer<O>,
147        ) -> Result<SerializeSuccess<O>, GenError> {
148            let mut arr_serializer = serializer.serialize_array(array.len() as u32)?;
149            for e in array.iter() {
150                arr_serializer.serialize_element(e)?;
151            }
152            arr_serializer.end()
153        }
154
155        match self {
156            Value::None => serializer.serialized_fixed_sized_pod(&()),
157            Value::Bool(b) => serializer.serialized_fixed_sized_pod(b),
158            Value::Id(id) => serializer.serialized_fixed_sized_pod(id),
159            Value::Int(i) => serializer.serialized_fixed_sized_pod(i),
160            Value::Long(l) => serializer.serialized_fixed_sized_pod(l),
161            Value::Float(f) => serializer.serialized_fixed_sized_pod(f),
162            Value::Double(d) => serializer.serialized_fixed_sized_pod(d),
163            Value::String(s) => serializer.serialize_string(s.as_str()),
164            Value::Bytes(b) => serializer.serialize_bytes(b.as_slice()),
165            Value::Rectangle(rect) => serializer.serialized_fixed_sized_pod(rect),
166            Value::Fraction(frac) => serializer.serialized_fixed_sized_pod(frac),
167            Value::Fd(fd) => serializer.serialized_fixed_sized_pod(fd),
168            Value::ValueArray(array) => match array {
169                ValueArray::None(arr) => serialize_array(arr, serializer),
170                ValueArray::Bool(arr) => serialize_array(arr, serializer),
171                ValueArray::Id(arr) => serialize_array(arr, serializer),
172                ValueArray::Int(arr) => serialize_array(arr, serializer),
173                ValueArray::Long(arr) => serialize_array(arr, serializer),
174                ValueArray::Float(arr) => serialize_array(arr, serializer),
175                ValueArray::Double(arr) => serialize_array(arr, serializer),
176                ValueArray::Rectangle(arr) => serialize_array(arr, serializer),
177                ValueArray::Fraction(arr) => serialize_array(arr, serializer),
178                ValueArray::Fd(arr) => serialize_array(arr, serializer),
179            },
180            Value::Struct(array) => {
181                let mut struct_serializer = serializer.serialize_struct()?;
182                for elem in array.iter() {
183                    struct_serializer.serialize_field(elem)?;
184                }
185                struct_serializer.end()
186            }
187            Value::Object(object) => {
188                let mut object_serializer = serializer.serialize_object(object.type_, object.id)?;
189                for prop in object.properties.iter() {
190                    object_serializer.serialize_property(prop.key, &prop.value, prop.flags)?;
191                }
192                object_serializer.end()
193            }
194            Value::Choice(choice) => match choice {
195                ChoiceValue::Bool(choice) => serializer.serialize_choice(choice),
196                ChoiceValue::Int(choice) => serializer.serialize_choice(choice),
197                ChoiceValue::Long(choice) => serializer.serialize_choice(choice),
198                ChoiceValue::Float(choice) => serializer.serialize_choice(choice),
199                ChoiceValue::Double(choice) => serializer.serialize_choice(choice),
200                ChoiceValue::Id(choice) => serializer.serialize_choice(choice),
201                ChoiceValue::Rectangle(choice) => serializer.serialize_choice(choice),
202                ChoiceValue::Fraction(choice) => serializer.serialize_choice(choice),
203                ChoiceValue::Fd(choice) => serializer.serialize_choice(choice),
204            },
205            Value::Pointer(type_, pointer) => serializer.serialize_pointer(*type_, *pointer),
206        }
207    }
208}
209
210impl<P: FixedSizedPod> PodSerialize for [P] {
211    fn serialize<O: Write + Seek>(
212        &self,
213        serializer: PodSerializer<O>,
214    ) -> Result<SerializeSuccess<O>, GenError> {
215        let mut arr_serializer = serializer.serialize_array(
216            self.len()
217                .try_into()
218                .expect("Array length does not fit in a u32"),
219        )?;
220
221        for element in self.iter() {
222            arr_serializer.serialize_element(element)?;
223        }
224
225        arr_serializer.end()
226    }
227}
228
229impl<T> PodSerialize for (u32, *const T) {
230    fn serialize<O: Write + Seek>(
231        &self,
232        serializer: PodSerializer<O>,
233    ) -> Result<SerializeSuccess<O>, GenError> {
234        serializer.serialize_pointer(self.0, self.1)
235    }
236}
237
238/// This struct is returned by [`PodSerialize`] implementors on serialization success.
239///
240/// Because this can only be constructed by the [`PodSerializer`], [`PodSerialize`] implementors are forced
241/// to finish serialization of their pod instead of stopping after serializing only part of a pod.
242pub struct SerializeSuccess<O: Write + Seek> {
243    /// Because [`PodSerialize`] implementors get ownership of the serializer,
244    /// it is returned back to the caller in this struct.
245    serializer: PodSerializer<O>,
246    /// The number of bytes written by the serialization operation that returns this struct.
247    len: u64,
248}
249
250/// This struct is responsible for serializing a [`PodSerialize`] implementor into the raw POD format.
251pub struct PodSerializer<O: Write + Seek> {
252    /// The writer is saved in an option, but can be expected to always be a `Some` when a `serialize_*` function
253    /// is called.
254    /// The function should then `take()` the writer, use it to serialize the item,
255    /// and must then put the writer back inside.
256    /// The [`Self::gen`] function can be used to do this.
257    out: Option<O>,
258}
259
260impl<O: Write + Seek> PodSerializer<O> {
261    /// Serialize the provided POD into the raw pod format, writing it into `out`.
262    ///
263    /// When serializing into an in-memory-buffer such as [`Vec`], you might have to wrap it into a [`std::io::Cursor`]
264    /// to provide the [`Seek`] trait.
265    ///
266    /// The function returns back the `out` writer and the number of bytes written,
267    /// or a generation error if serialization failed.
268    pub fn serialize<P>(out: O, pod: &P) -> Result<(O, u64), GenError>
269    where
270        P: PodSerialize + ?Sized,
271    {
272        let serializer = Self { out: Some(out) };
273
274        pod.serialize(serializer).map(|success| {
275            (
276                success
277                    .serializer
278                    .out
279                    .expect("Serializer does not contain a writer"),
280                success.len,
281            )
282        })
283    }
284
285    /// Helper serialization method for serializing the Pod header.
286    ///
287    /// # Parameters
288    /// - size: The size of the pod body
289    /// - type: The type of the pod, e.g. `spa_sys::SPA_TYPE_Int` for a `spa_pod_int`
290    fn header(size: usize, ty: u32) -> impl SerializeFn<O> {
291        pair(ne_u32(size as u32), ne_u32(ty))
292    }
293
294    /// Helper serialization function for adding padding to a pod..
295    ///
296    /// Pad output with 0x00 bytes so that it is aligned to 8 bytes.
297    fn padding(len: usize) -> impl SerializeFn<O> {
298        let zeroes = std::iter::repeat(0u8);
299        all(zeroes.take(len).map(ne_u8))
300    }
301
302    /// Use the provided serialization function to write into the writer contained in self.
303    fn gen(&mut self, f: impl SerializeFn<O>) -> Result<u64, GenError> {
304        gen(
305            f,
306            self.out
307                .take()
308                .expect("PodSerializer does not contain a writer"),
309        )
310        .map(|(writer, len)| {
311            self.out = Some(writer);
312            len
313        })
314    }
315
316    /// Write out a full pod (header, body, padding), with the body computed using the provided serialization function.
317    fn write_pod(
318        mut self,
319        size: usize,
320        type_: u32,
321        f: impl SerializeFn<O>,
322    ) -> Result<SerializeSuccess<O>, GenError> {
323        let padding = if size % 8 == 0 { 0 } else { 8 - (size % 8) };
324        let written = self.gen(tuple((
325            Self::header(size, type_),
326            f,
327            Self::padding(padding),
328        )))?;
329
330        Ok(SerializeSuccess {
331            serializer: self,
332            len: written,
333        })
334    }
335
336    // Implementation note:
337    // Each `serialize_*` function must serialize the _full_ pod, meaning header, body, and padding.
338    // The `write_pod` method may be used to help with this.
339
340    /// Serialize any fixed size pod.
341    ///
342    /// The type of the serialized pod will depend on the [`FixedSizedPod::CanonicalType`] that the passed type has.
343    pub fn serialized_fixed_sized_pod<P>(self, pod: &P) -> Result<SerializeSuccess<O>, GenError>
344    where
345        P: FixedSizedPod + ?Sized,
346    {
347        self.write_pod(
348            P::CanonicalType::SIZE as usize,
349            P::CanonicalType::TYPE,
350            |out| pod.as_canonical_type().serialize_body(out),
351        )
352    }
353
354    /// Serialize a `String` pod.
355    pub fn serialize_string(self, string: &str) -> Result<SerializeSuccess<O>, GenError> {
356        let cstr = CString::new(string)
357            .expect("Pod::String contains string with '\0' byte")
358            .into_bytes_with_nul();
359        self.write_pod(cstr.len(), spa_sys::SPA_TYPE_String, slice(cstr))
360    }
361
362    /// Serialize a `Bytes` pod.
363    pub fn serialize_bytes(self, bytes: &[u8]) -> Result<SerializeSuccess<O>, GenError> {
364        self.write_pod(bytes.len(), spa_sys::SPA_TYPE_Bytes, slice(bytes))
365    }
366
367    /// Begin serializing an `Array` pod with exactly `length` elements.
368    pub fn serialize_array<P: FixedSizedPod>(
369        mut self,
370        length: u32,
371    ) -> Result<ArrayPodSerializer<O, P>, GenError> {
372        self.gen(pair(
373            Self::header(
374                (8 + length * P::CanonicalType::SIZE) as usize,
375                spa_sys::SPA_TYPE_Array,
376            ),
377            Self::header(P::CanonicalType::SIZE as usize, P::CanonicalType::TYPE),
378        ))?;
379
380        Ok(ArrayPodSerializer {
381            serializer: self,
382            length,
383            written: 0,
384            _phantom: PhantomData,
385        })
386    }
387
388    /// Begin serializing a `Struct` pod.
389    pub fn serialize_struct(mut self) -> Result<StructPodSerializer<O>, GenError> {
390        let header_position = self
391            .out
392            .as_mut()
393            .expect("PodSerializer does not contain a writer")
394            .stream_position()
395            .expect("Could not get current position in writer");
396
397        // Write a size of 0 for now, this will be updated when calling `StructPodSerializer.end()`.
398        self.gen(Self::header(0, spa_sys::SPA_TYPE_Struct))?;
399
400        Ok(StructPodSerializer {
401            serializer: Some(self),
402            header_position,
403            written: 0,
404        })
405    }
406
407    /// Begin serializing an `Object` pod.
408    pub fn serialize_object(
409        mut self,
410        object_type: u32,
411        object_id: u32,
412    ) -> Result<ObjectPodSerializer<O>, GenError> {
413        let header_position = self
414            .out
415            .as_mut()
416            .expect("PodSerializer does not contain a writer")
417            .stream_position()
418            .expect("Could not get current position in writer");
419
420        // Write a size of 0 for now, this will be updated when calling `ObjectPodSerializer.end()`.
421        self.gen(Self::header(0, spa_sys::SPA_TYPE_Object))?;
422        self.gen(pair(ne_u32(object_type), ne_u32(object_id)))?;
423
424        Ok(ObjectPodSerializer {
425            serializer: Some(self),
426            header_position,
427            written: 0,
428        })
429    }
430
431    /// Serialize a `Choice` pod.
432    pub fn serialize_choice<T: CanonicalFixedSizedPod>(
433        mut self,
434        choice: &Choice<T>,
435    ) -> Result<SerializeSuccess<O>, GenError> {
436        let flags = choice.0;
437
438        let (choice_type, values) = match &choice.1 {
439            ChoiceEnum::None(value) => (spa_sys::SPA_CHOICE_None, vec![value]),
440            ChoiceEnum::Range { default, min, max } => {
441                (spa_sys::SPA_CHOICE_Range, vec![default, min, max])
442            }
443            ChoiceEnum::Step {
444                default,
445                min,
446                max,
447                step,
448            } => (spa_sys::SPA_CHOICE_Step, vec![default, min, max, step]),
449            ChoiceEnum::Enum {
450                default,
451                alternatives,
452            } => {
453                let mut values = vec![default];
454                values.extend(alternatives);
455                (spa_sys::SPA_CHOICE_Enum, values)
456            }
457            ChoiceEnum::Flags { default, flags } => {
458                let mut values = vec![default];
459                values.extend(flags);
460                (spa_sys::SPA_CHOICE_Flags, values)
461            }
462        };
463
464        let len: usize = 2 * 8 + values.len() * (T::SIZE as usize);
465
466        self.gen(Self::header(len, spa_sys::SPA_TYPE_Choice))?;
467        self.gen(pair(ne_u32(choice_type), ne_u32(flags.bits())))?;
468        self.gen(pair(ne_u32(T::SIZE), ne_u32(T::TYPE)))?;
469
470        for v in values {
471            self.gen(|out| v.serialize_body(out))?;
472        }
473
474        let padding = if len % 8 == 0 { 0 } else { 8 - (len % 8) };
475
476        // Add padding to the pod.
477        let pad_bytes = self.gen(PodSerializer::padding(padding))?;
478
479        Ok(SerializeSuccess {
480            serializer: self,
481            // pod header + choice body + padding
482            len: 8 + len as u64 + pad_bytes,
483        })
484    }
485
486    /// Serialize a pointer pod.
487    pub fn serialize_pointer<T>(
488        mut self,
489        type_: u32,
490        ptr: *const T,
491    ) -> Result<SerializeSuccess<O>, GenError> {
492        let ptr_size = std::mem::size_of::<usize>();
493        let len = 8 + ptr_size;
494
495        let mut written = self.gen(Self::header(len, spa_sys::SPA_TYPE_Pointer))?;
496        written += self.gen(pair(ne_u32(type_), ne_u32(0)))?;
497
498        written += match ptr_size {
499            4 => self.gen(ne_u32(ptr as u32))?,
500            8 => self.gen(ne_u64(ptr as u64))?,
501            _ => panic!("unsupported pointer size {ptr_size}"),
502        };
503
504        Ok(SerializeSuccess {
505            serializer: self,
506            len: written,
507        })
508    }
509}
510
511/// This struct handles serializing arrays.
512///
513/// It can be obtained by calling [`PodSerializer::serialize_array`].
514///
515/// The exact number of elements that was specified during that call must be written into it
516/// using its [`serialize_element`](`Self::serialize_element`) function,
517/// followed by calling its [`end`](`Self::end`) function to finish serialization of the array.
518pub struct ArrayPodSerializer<O: Write + Seek, P: FixedSizedPod> {
519    serializer: PodSerializer<O>,
520    /// The total length the array should have
521    length: u32,
522    /// The number of elements that have been written already
523    written: u32,
524    /// The struct has the type parameter P to ensure all serialized elements are the same type,
525    /// but doesn't actually own any P, so we need the `PhantomData<P>` instead.
526    _phantom: PhantomData<P>,
527}
528
529impl<O: Write + Seek, P: FixedSizedPod> ArrayPodSerializer<O, P> {
530    /// Serialize a single element.
531    ///
532    /// Returns the amount of bytes written for this field.
533    pub fn serialize_element(&mut self, elem: &P) -> Result<u64, GenError> {
534        if !self.written < self.length {
535            panic!("More elements than specified were serialized into the array POD");
536        }
537
538        let result = self
539            .serializer
540            .gen(|out| elem.as_canonical_type().serialize_body(out));
541        self.written += 1;
542        result
543    }
544
545    /// Finish serializing the array.
546    pub fn end(mut self) -> Result<SerializeSuccess<O>, GenError> {
547        assert_eq!(
548            self.length, self.written,
549            "Array POD was not serialized with the specified amount of elements"
550        );
551
552        let bytes_written = self.written * P::CanonicalType::SIZE;
553
554        let padding = if bytes_written % 8 == 0 {
555            0
556        } else {
557            8 - (bytes_written as usize % 8)
558        };
559
560        // Add padding to the pod.
561        let pad_bytes = self.serializer.gen(PodSerializer::padding(padding))?;
562
563        Ok(SerializeSuccess {
564            serializer: self.serializer,
565            // Number of bytes written for the pod is two headers + body length + padding
566            len: 16 + u64::from(self.written * P::CanonicalType::SIZE) + pad_bytes,
567        })
568    }
569}
570
571/// This struct handles serializing structs.
572///
573/// It can be obtained by calling [`PodSerializer::serialize_struct`].
574///
575/// Its [`serialize_field`](`Self::serialize_field`) method can be repeatedly called to serialize one field each.
576/// To finalize the struct, its [`end`](`Self::end`) method must be called.
577pub struct StructPodSerializer<O: Write + Seek> {
578    /// The serializer is saved in an option, but can be expected to always be a `Some`
579    /// when `serialize_field()` or `end()` is called.
580    ///
581    /// `serialize_field()` `take()`s the serializer, uses it to serialize the field,
582    /// and then puts the serializer back inside.
583    serializer: Option<PodSerializer<O>>,
584    /// The position to seek to when modifying header.
585    header_position: u64,
586    written: usize,
587}
588
589impl<O: Write + Seek> StructPodSerializer<O> {
590    /// Serialize a single field of the struct.
591    ///
592    /// Returns the amount of bytes written for this field.
593    pub fn serialize_field<P>(&mut self, field: &P) -> Result<u64, GenError>
594    where
595        P: PodSerialize + ?Sized,
596    {
597        let success = field.serialize(
598            self.serializer
599                .take()
600                .expect("StructSerializer does not contain a serializer"),
601        )?;
602        self.written += success.len as usize;
603        self.serializer = Some(success.serializer);
604        Ok(success.len)
605    }
606
607    /// Finish serialization of the pod.
608    pub fn end(self) -> Result<SerializeSuccess<O>, GenError> {
609        let mut serializer = self
610            .serializer
611            .expect("StructSerializer does not contain a serializer");
612
613        // Seek to header position, write header with updates size, seek back.
614        serializer
615            .out
616            .as_mut()
617            .expect("Serializer does not contain a writer")
618            .seek(SeekFrom::Start(self.header_position))
619            .expect("Failed to seek to header position");
620
621        serializer.gen(PodSerializer::header(
622            self.written,
623            spa_sys::SPA_TYPE_Struct,
624        ))?;
625
626        serializer
627            .out
628            .as_mut()
629            .expect("Serializer does not contain a writer")
630            .seek(SeekFrom::End(0))
631            .expect("Failed to seek to end");
632
633        // No padding needed: Last field will already end aligned.
634
635        // Return full length of written pod.
636        Ok(SerializeSuccess {
637            serializer,
638            len: self.written as u64 + 8,
639        })
640    }
641}
642
643/// This struct handles serializing objects.
644///
645/// It can be obtained by calling [`PodSerializer::serialize_object`].
646///
647/// Its [`serialize_property`](`Self::serialize_property`) method can be repeatedly called to serialize each property.
648/// To finalize the object, its [`end`](`Self::end`) method must be called.
649pub struct ObjectPodSerializer<O: Write + Seek> {
650    /// The serializer is saved in an option, but can be expected to always be a `Some`
651    /// when `serialize_field()` or `end()` is called.
652    ///
653    /// `serialize_property()` `take()`s the serializer, uses it to serialize the property,
654    /// and then puts the serializer back inside.
655    serializer: Option<PodSerializer<O>>,
656    /// The position to seek to when modifying header.
657    header_position: u64,
658    written: usize,
659}
660
661impl<O: Write + Seek> ObjectPodSerializer<O> {
662    /// Serialize a single property of the object.
663    ///
664    /// Returns the amount of bytes written for this field.
665    pub fn serialize_property<P>(
666        &mut self,
667        key: u32,
668        value: &P,
669        flags: PropertyFlags,
670    ) -> Result<u64, GenError>
671    where
672        P: PodSerialize + ?Sized,
673    {
674        let mut serializer = self
675            .serializer
676            .take()
677            .expect("ObjectPodSerializer does not contain a serializer");
678
679        serializer.gen(pair(ne_u32(key), ne_u32(flags.bits())))?;
680        let mut success = value.serialize(serializer)?;
681        success.len += 8; // add the key and flags len
682
683        self.written += success.len as usize;
684        self.serializer = Some(success.serializer);
685
686        Ok(success.len)
687    }
688
689    /// Finish serialization of the pod.
690    pub fn end(self) -> Result<SerializeSuccess<O>, GenError> {
691        let mut serializer = self
692            .serializer
693            .expect("ObjectSerializer does not contain a serializer");
694
695        // Seek to header position, write header with updates size, seek back.
696        serializer
697            .out
698            .as_mut()
699            .expect("Serializer does not contain a writer")
700            .seek(SeekFrom::Start(self.header_position))
701            .expect("Failed to seek to header position");
702
703        // size of properties + object type + object id
704        let written = self.written + 8;
705
706        serializer.gen(PodSerializer::header(written, spa_sys::SPA_TYPE_Object))?;
707
708        serializer
709            .out
710            .as_mut()
711            .expect("Serializer does not contain a writer")
712            .seek(SeekFrom::End(0))
713            .expect("Failed to seek to end");
714
715        // No padding needed: Last field will already end aligned.
716
717        // Return full length of written pod.
718        Ok(SerializeSuccess {
719            serializer,
720            // pod header + object body
721            len: 8 + written as u64,
722        })
723    }
724}
725
726impl<T: CanonicalFixedSizedPod + FixedSizedPod> PodSerialize for Choice<T> {
727    fn serialize<O: Write + Seek>(
728        &self,
729        serializer: PodSerializer<O>,
730    ) -> Result<SerializeSuccess<O>, GenError> {
731        serializer.serialize_choice(self)
732    }
733}