Skip to main content

mlt_core/frames/v01/property/
serialize.rs

1use std::io::Write;
2
3use integer_encoding::VarIntWriter as _;
4
5use crate::utils::{BinarySerializer as _, checked_sum3};
6use crate::v01::{ColumnType, EncodedProperty, PropertyKind, StagedProperty};
7use crate::{MltError, MltResult};
8
9impl StagedProperty {
10    #[must_use]
11    pub fn kind(&self) -> PropertyKind {
12        use PropertyKind as T;
13        match self {
14            Self::Bool(_) => T::Bool,
15            Self::I8(_)
16            | Self::I32(_)
17            | Self::I64(_)
18            | Self::U8(_)
19            | Self::U32(_)
20            | Self::U64(_) => T::Integer,
21            Self::F32(_) | Self::F64(_) => T::Float,
22            Self::Str(_) => T::String,
23            Self::SharedDict(_) => T::SharedDict,
24        }
25    }
26}
27
28impl EncodedProperty {
29    pub fn write_columns_meta_to<W: Write>(&self, writer: &mut W) -> MltResult<()> {
30        let col_type = match self {
31            Self::Bool(s) => {
32                if s.presence.0.is_some() {
33                    ColumnType::OptBool
34                } else {
35                    ColumnType::Bool
36                }
37            }
38            Self::I8(s) => {
39                if s.presence.0.is_some() {
40                    ColumnType::OptI8
41                } else {
42                    ColumnType::I8
43                }
44            }
45            Self::U8(s) => {
46                if s.presence.0.is_some() {
47                    ColumnType::OptU8
48                } else {
49                    ColumnType::U8
50                }
51            }
52            Self::I32(s) => {
53                if s.presence.0.is_some() {
54                    ColumnType::OptI32
55                } else {
56                    ColumnType::I32
57                }
58            }
59            Self::U32(s) => {
60                if s.presence.0.is_some() {
61                    ColumnType::OptU32
62                } else {
63                    ColumnType::U32
64                }
65            }
66            Self::I64(s) => {
67                if s.presence.0.is_some() {
68                    ColumnType::OptI64
69                } else {
70                    ColumnType::I64
71                }
72            }
73            Self::U64(s) => {
74                if s.presence.0.is_some() {
75                    ColumnType::OptU64
76                } else {
77                    ColumnType::U64
78                }
79            }
80            Self::F32(s) => {
81                if s.presence.0.is_some() {
82                    ColumnType::OptF32
83                } else {
84                    ColumnType::F32
85                }
86            }
87            Self::F64(s) => {
88                if s.presence.0.is_some() {
89                    ColumnType::OptF64
90                } else {
91                    ColumnType::F64
92                }
93            }
94            Self::Str(s) => {
95                if s.presence.0.is_some() {
96                    ColumnType::OptStr
97                } else {
98                    ColumnType::Str
99                }
100            }
101            Self::SharedDict(..) => ColumnType::SharedDict,
102        };
103        col_type.write_to(writer)?;
104
105        let name = match self {
106            Self::Bool(s)
107            | Self::I8(s)
108            | Self::U8(s)
109            | Self::I32(s)
110            | Self::U32(s)
111            | Self::I64(s)
112            | Self::U64(s)
113            | Self::F32(s)
114            | Self::F64(s) => &s.name.0,
115            Self::Str(s) => &s.name.0,
116            Self::SharedDict(s) => &s.name.0,
117        };
118        writer.write_string(name)?;
119
120        // Struct children metadata must be written inline here so subsequent column
121        // metadata offsets remain correct.
122        if let Self::SharedDict(s) = self {
123            writer.write_varint(u32::try_from(s.children.len())?)?;
124            for child in &s.children {
125                child.write_columns_meta_to(writer)?;
126                writer.write_string(&child.name.0)?;
127            }
128        }
129        Ok(())
130    }
131
132    pub fn write_to<W: Write>(&self, writer: &mut W) -> MltResult<()> {
133        match self {
134            Self::Bool(s) => {
135                writer.write_optional_stream(s.presence.0.as_ref())?;
136                writer.write_boolean_stream(&s.data)?;
137            }
138            Self::I8(s)
139            | Self::U8(s)
140            | Self::I32(s)
141            | Self::U32(s)
142            | Self::I64(s)
143            | Self::U64(s)
144            | Self::F32(s)
145            | Self::F64(s) => {
146                writer.write_optional_stream(s.presence.0.as_ref())?;
147                writer.write_stream(&s.data)?;
148            }
149            Self::Str(s) => {
150                let content = s.encoding.content_streams();
151                let stream_count =
152                    u32::try_from(content.len() + usize::from(s.presence.0.is_some()))
153                        .map_err(MltError::from)?;
154                writer.write_varint(stream_count)?;
155                writer.write_optional_stream(s.presence.0.as_ref())?;
156                for stream in content {
157                    writer.write_stream(stream)?;
158                }
159            }
160            Self::SharedDict(s) => {
161                let dict_streams = s.encoding.dict_streams();
162                let dict_stream_len = u32::try_from(dict_streams.len()).map_err(MltError::from)?;
163                let children_len = u32::try_from(s.children.len()).map_err(MltError::from)?;
164                let optional_children_count =
165                    s.children.iter().filter(|c| c.presence.0.is_some()).count();
166                let optional_children_len =
167                    u32::try_from(optional_children_count).map_err(MltError::from)?;
168                let stream_len =
169                    checked_sum3(dict_stream_len, children_len, optional_children_len)?;
170                writer.write_varint(stream_len)?;
171                for stream in dict_streams {
172                    writer.write_stream(stream)?;
173                }
174                for child in &s.children {
175                    writer.write_varint(1 + u32::from(child.presence.0.is_some()))?;
176                    writer.write_optional_stream(child.presence.0.as_ref())?;
177                    writer.write_stream(&child.data)?;
178                }
179            }
180        }
181        Ok(())
182    }
183}