Skip to main content

mlt_core/frames/v01/
encoded.rs

1use std::io;
2use std::io::Write;
3
4use integer_encoding::VarIntWriter as _;
5use utils::BinarySerializer as _;
6
7use crate::v01::{EncodedGeometry, EncodedLayer01};
8use crate::{MltError, MltResult, utils};
9
10impl EncodedLayer01 {
11    /// Write layer's binary representation to a [`Write`] stream without allocating a Vec.
12    pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()> {
13        writer.write_string(&self.name)?;
14        writer.write_varint(self.extent)?;
15
16        let id_columns_count = u32::from(self.id.is_some());
17        let geometry_column_count = 1u32;
18        let property_column_count = u32::try_from(self.properties.len()).map_err(MltError::from)?;
19        let column_count = property_column_count + id_columns_count + geometry_column_count;
20        writer.write_varint(column_count)?;
21
22        let map_error_to_io = |e: MltError| match e {
23            MltError::Io(e) => e,
24            e => io::Error::other(e),
25        };
26        self.write_columns_meta_to(writer)
27            .map_err(map_error_to_io)?;
28        self.write_columns_to(writer).map_err(map_error_to_io)?;
29        Ok(())
30    }
31
32    fn write_id_meta(&self, writer: &mut impl Write) -> MltResult<()> {
33        if let Some(ref id) = self.id {
34            id.write_columns_meta_to(writer)?;
35        }
36        Ok(())
37    }
38
39    fn write_id(&self, writer: &mut impl Write) -> MltResult<()> {
40        if let Some(ref id) = self.id {
41            id.write_to(writer)?;
42        }
43        Ok(())
44    }
45
46    #[cfg(not(fuzzing))]
47    fn write_columns_meta_to(&self, writer: &mut impl Write) -> MltResult<()> {
48        self.write_id_meta(writer)?;
49        EncodedGeometry::write_columns_meta_to(writer)?;
50        for prop in &self.properties {
51            prop.write_columns_meta_to(writer)?;
52        }
53        Ok(())
54    }
55
56    /// TODO: force item ordering to be stable in the spec
57    #[cfg(fuzzing)]
58    fn write_columns_meta_to(&self, writer: &mut impl Write) -> MltResult<()> {
59        use crate::frames::v01::fuzzing::LayerOrdering;
60        let props = &mut self.properties.iter();
61        for ord in &self.layer_order {
62            match ord {
63                LayerOrdering::Id => self.write_id_meta(writer)?,
64                LayerOrdering::Geometry => EncodedGeometry::write_columns_meta_to(writer)?,
65                LayerOrdering::Property => {
66                    let prop = props.next().expect("layer order count mismatch");
67                    prop.write_columns_meta_to(writer)?;
68                }
69            }
70        }
71        Ok(())
72    }
73
74    #[cfg(not(fuzzing))]
75    fn write_columns_to(&self, writer: &mut impl Write) -> MltResult<()> {
76        self.write_id(writer)?;
77        self.geometry.write_to(writer)?;
78        for prop in &self.properties {
79            prop.write_to(writer)?;
80        }
81        Ok(())
82    }
83
84    /// TODO: force item ordering to be stable in the spec
85    #[cfg(fuzzing)]
86    fn write_columns_to(&self, writer: &mut impl Write) -> MltResult<()> {
87        use crate::frames::v01::fuzzing::LayerOrdering;
88        let props = &mut self.properties.iter();
89        for ord in &self.layer_order {
90            match ord {
91                LayerOrdering::Id => self.write_id(writer)?,
92                LayerOrdering::Geometry => self.geometry.write_to(writer)?,
93                LayerOrdering::Property => {
94                    let prop = props.next().expect("layer order count mismatch");
95                    prop.write_to(writer)?;
96                }
97            }
98        }
99        Ok(())
100    }
101}