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, LayerBytes, 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 pub(crate) bytes: LayerBytes,
45 #[cfg(fuzzing)]
46 pub(crate) layer_order: Vec<crate::decoder::fuzzing::LayerOrdering>,
47}
48
49pub type ParsedLayer01<'a> = Layer01<'a, Parsed>;
50
51impl<'a, S: DecodeState> Layer01<'a, S> {
52 #[must_use]
53 pub fn name(&self) -> &'a str {
54 self.name
55 }
56
57 #[must_use]
58 pub fn extent(&self) -> Extent {
59 self.extent
60 }
61
62 #[must_use]
64 pub fn bytes(&self) -> LayerBytes {
65 self.bytes
66 }
67}
68
69impl ParsedLayer01<'_> {
70 #[must_use]
77 pub fn geometry_values(&self) -> &GeometryValues {
78 &self.geometry
79 }
80
81 #[must_use]
82 pub fn feature_count(&self) -> usize {
83 self.geometry.vector_types.len()
84 }
85
86 #[must_use]
88 pub fn properties(&self) -> &[ParsedProperty<'_>] {
89 &self.properties
90 }
91}
92
93#[derive(Debug, PartialEq)]
95pub struct Column<'a> {
96 pub(crate) typ: ColumnType,
97 pub(crate) name: Option<&'a str>,
98 pub(crate) children: Vec<Self>,
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, TryFromPrimitive)]
103#[repr(u8)]
104pub enum ColumnType {
105 Id = 0b0000_0000,
106 OptId = 0b0000_0001,
107 LongId = 0b0000_0010,
108 OptLongId = 0b0000_0011,
109 Geometry = 0b0000_0100,
110 Bool = 0b0000_1010,
111 OptBool = 0b0000_1011,
112 I32 = 0b0001_0000,
113 OptI32 = 0b0001_0001,
114 U32 = 0b0001_0010,
115 OptU32 = 0b0001_0011,
116 I64 = 0b0001_0100,
117 OptI64 = 0b0001_0101,
118 U64 = 0b0001_0110,
119 OptU64 = 0b0001_0111,
120 F32 = 0b0001_1000,
121 OptF32 = 0b0001_1001,
122 F64 = 0b0001_1010,
123 OptF64 = 0b0001_1011,
124 Str = 0b0001_1100,
125 OptStr = 0b0001_1101,
126 SharedDict = 0b0001_1110,
127}
128
129impl Column<'_> {
130 pub(crate) fn from_bytes<'a>(
132 input: &'a [u8],
133 _parser: &mut Parser,
134 ) -> MltRefResult<'a, Column<'a>> {
135 let (mut input, typ) = ColumnType::from_bytes(input)?;
136 let name = if typ.has_name() {
137 let pair = parse_string(input)?;
138 input = pair.0;
139 Some(pair.1)
140 } else {
141 None
142 };
143
144 Ok((
145 input,
146 Column {
147 typ,
148 name,
149 children: Vec::new(),
150 },
151 ))
152 }
153}
154
155impl ColumnType {
156 pub(crate) fn from_bytes(input: &[u8]) -> MltRefResult<'_, Self> {
158 let (input, value) = parse_u8(input)?;
159 let value = Self::try_from(value).or(Err(ParsingColumnType(value)))?;
160 Ok((input, value))
161 }
162
163 pub(crate) fn write_to<W: Write>(self, writer: &mut W) -> io::Result<()> {
164 writer.write_u8(self as u8)?;
165 Ok(())
166 }
167
168 #[must_use]
171 pub(crate) fn has_name(self) -> bool {
172 !matches!(
173 self,
174 Self::Id | Self::OptId | Self::LongId | Self::OptLongId | Self::Geometry
175 )
176 }
177
178 #[must_use]
180 pub(crate) fn is_id(self) -> bool {
181 matches!(
182 self,
183 Self::Id | Self::OptId | Self::LongId | Self::OptLongId
184 )
185 }
186
187 #[must_use]
189 pub(crate) fn is_optional(self) -> bool {
190 (self as u8) & OPTIONAL_FLAG != 0
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use rstest::rstest;
197
198 use super::ColumnType;
199 use crate::MltError;
200
201 #[rstest]
202 fn column_type_rejects_unassigned(#[values(5, 6, 7, 8, 9, 12, 13, 14, 15, 31)] byte: u8) {
203 let err = ColumnType::from_bytes(&[byte]).unwrap_err();
204 assert!(matches!(err, MltError::ParsingColumnType(b) if b == byte));
205 }
206}