mlt_core/decoder/
model01.rs1use std::io;
7use std::io::Write;
8
9use num_enum::TryFromPrimitive;
10
11use crate::MltError::ParsingColumnType;
12use crate::decoder::{Geometry, GeometryValues, Id, ParsedProperty, Property};
13use crate::tile::Extent;
14use crate::utils::{BinarySerializer as _, parse_string, parse_u8};
15use crate::{DecodeState, Lazy, MltRefResult, Parsed, Parser};
16
17pub(crate) const OPTIONAL_FLAG: u8 = 0b0000_0001;
19
20pub(crate) const BASE_TYPE_MASK: u8 = 0b1111_1110;
23
24#[derive(Debug, Clone)]
38pub struct Layer01<'a, S: DecodeState = Lazy> {
39 pub(crate) name: &'a str,
40 pub(crate) extent: Extent,
41 pub(crate) id: Option<Id<'a, S>>,
42 pub(crate) geometry: Geometry<'a, S>,
43 pub(crate) properties: Vec<Property<'a, S>>,
44 #[cfg(fuzzing)]
45 pub(crate) layer_order: Vec<crate::decoder::fuzzing::LayerOrdering>,
46}
47
48pub type ParsedLayer01<'a> = Layer01<'a, Parsed>;
49
50impl<'a, S: DecodeState> Layer01<'a, S> {
51 #[must_use]
52 pub fn name(&self) -> &'a str {
53 self.name
54 }
55
56 #[must_use]
57 pub fn extent(&self) -> Extent {
58 self.extent
59 }
60}
61
62impl ParsedLayer01<'_> {
63 #[must_use]
70 pub fn geometry_values(&self) -> &GeometryValues {
71 &self.geometry
72 }
73
74 #[must_use]
75 pub fn feature_count(&self) -> usize {
76 self.geometry.vector_types.len()
77 }
78
79 #[must_use]
81 pub fn properties(&self) -> &[ParsedProperty<'_>] {
82 &self.properties
83 }
84}
85
86#[derive(Debug, PartialEq)]
88pub struct Column<'a> {
89 pub(crate) typ: ColumnType,
90 pub(crate) name: Option<&'a str>,
91 pub(crate) children: Vec<Self>,
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, TryFromPrimitive)]
96#[repr(u8)]
97pub enum ColumnType {
98 Id = 0b0000_0000,
99 OptId = 0b0000_0001,
100 LongId = 0b0000_0010,
101 OptLongId = 0b0000_0011,
102 Geometry = 0b0000_0100,
103 Bool = 0b0000_1010,
104 OptBool = 0b0000_1011,
105 I32 = 0b0001_0000,
106 OptI32 = 0b0001_0001,
107 U32 = 0b0001_0010,
108 OptU32 = 0b0001_0011,
109 I64 = 0b0001_0100,
110 OptI64 = 0b0001_0101,
111 U64 = 0b0001_0110,
112 OptU64 = 0b0001_0111,
113 F32 = 0b0001_1000,
114 OptF32 = 0b0001_1001,
115 F64 = 0b0001_1010,
116 OptF64 = 0b0001_1011,
117 Str = 0b0001_1100,
118 OptStr = 0b0001_1101,
119 SharedDict = 0b0001_1110,
120}
121
122impl Column<'_> {
123 pub(crate) fn from_bytes<'a>(
125 input: &'a [u8],
126 _parser: &mut Parser,
127 ) -> MltRefResult<'a, Column<'a>> {
128 let (mut input, typ) = ColumnType::from_bytes(input)?;
129 let name = if typ.has_name() {
130 let pair = parse_string(input)?;
131 input = pair.0;
132 Some(pair.1)
133 } else {
134 None
135 };
136
137 Ok((
138 input,
139 Column {
140 typ,
141 name,
142 children: Vec::new(),
143 },
144 ))
145 }
146}
147
148impl ColumnType {
149 pub(crate) fn from_bytes(input: &[u8]) -> MltRefResult<'_, Self> {
151 let (input, value) = parse_u8(input)?;
152 let value = Self::try_from(value).or(Err(ParsingColumnType(value)))?;
153 Ok((input, value))
154 }
155
156 pub(crate) fn write_to<W: Write>(self, writer: &mut W) -> io::Result<()> {
157 writer.write_u8(self as u8)?;
158 Ok(())
159 }
160
161 #[must_use]
164 pub(crate) fn has_name(self) -> bool {
165 !matches!(
166 self,
167 Self::Id | Self::OptId | Self::LongId | Self::OptLongId | Self::Geometry
168 )
169 }
170
171 #[must_use]
173 pub(crate) fn is_optional(self) -> bool {
174 (self as u8) & OPTIONAL_FLAG != 0
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use rstest::rstest;
181
182 use super::ColumnType;
183 use crate::MltError;
184
185 #[rstest]
186 fn column_type_rejects_unassigned(#[values(5, 6, 7, 8, 9, 12, 13, 14, 15, 31)] byte: u8) {
187 let err = ColumnType::from_bytes(&[byte]).unwrap_err();
188 assert!(matches!(err, MltError::ParsingColumnType(b) if b == byte));
189 }
190}