mlt_core/decoder/
into_tile.rs1use crate::decoder::{Layer, Layer01, ParsedLayer, ParsedLayer01, ParsedProperty, PropValueRef};
9#[cfg(feature = "unstable-v2")]
10use crate::decoder::{Layer02, MValueSpans, ParsedLayer02, ParsedMValue, ParsedNested};
11use crate::errors::AsMltError as _;
12#[cfg(feature = "unstable-v2")]
13use crate::tile::{MValue, NestedKind, NestedValue};
14use crate::tile::{PropValue, TileFeature, TileLayer};
15use crate::{Decoder, Lazy, LendingIterator, MltResult};
16
17struct TileParts {
19 name: String,
20 extent: u32,
21 names: Vec<String>,
22 features: Vec<TileFeature>,
23}
24
25impl TileParts {
26 fn finish(self) -> MltResult<TileLayer> {
27 TileLayer::from_parts(self.name, self.extent, self.names, self.features)
28 }
29}
30
31impl ParsedLayer01<'_> {
32 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
35 self.collect_parts(dec)?.finish()
36 }
37
38 fn collect_parts(&self, dec: &mut Decoder) -> MltResult<TileParts> {
41 let name = self.name().to_string();
42 let extent = self.extent().get();
43 let names: Vec<String> = self.iterate_prop_names().map(|n| n.to_string()).collect();
44 let col_nulls = typed_nulls(&self.properties);
45 let mut features = dec.alloc::<TileFeature>(self.feature_count())?;
46 let mut feat_iter = self.iter_features();
47 while let Some(feat) = feat_iter.next() {
48 let feat = feat?;
49 let mut values = dec.alloc::<PropValue>(names.len())?;
50 for (col_idx, value) in feat.iter_all_properties().enumerate() {
51 values.push(match value {
52 Some(v) => prop_value_from_ref(v),
53 None => col_nulls[col_idx].clone(),
54 });
55 }
56
57 charge_str_props(dec, &values)?;
58
59 features.push(TileFeature {
60 id: feat.id(),
61 geometry: feat.geometry().clone(),
62 properties: values,
63 #[cfg(feature = "unstable-v2")]
64 m_values: Vec::new(),
65 #[cfg(feature = "unstable-v2")]
66 nested: Vec::new(),
67 });
68 }
69 Ok(TileParts {
70 name,
71 extent,
72 names,
73 features,
74 })
75 }
76}
77
78impl Layer01<'_> {
79 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
81 self.decode_all(dec)?.into_tile(dec)
82 }
83}
84
85#[cfg(feature = "unstable-v2")]
86impl ParsedLayer02<'_> {
87 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
90 let m_names: Vec<String> = self.m_values.iter().map(|m| m.name().to_string()).collect();
91 let nested_names: Vec<String> = self.nested.iter().map(|n| n.name().to_string()).collect();
92 let nested_kinds: Vec<NestedKind> = self.nested.iter().map(ParsedNested::kind).collect();
93 let mut m_spans = dec.alloc::<MValueSpans>(self.m_values.len())?;
97 m_spans.extend(self.m_values.iter().map(|m| m.spans(&self.layer.geometry)));
98
99 let mut parts = self.layer.collect_parts(dec)?;
100 for (index, feature) in parts.features.iter_mut().enumerate() {
101 feature.m_values = m_values_of(&self.m_values, &mut m_spans, dec)?;
102 feature.nested = nested_of(&self.nested, index, dec)?;
103 }
104 parts
105 .finish()?
106 .with_m_value_names(m_names)?
107 .with_nested(nested_names, nested_kinds)
108 }
109}
110
111#[cfg(feature = "unstable-v2")]
112impl Layer02<'_> {
113 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
115 self.decode_all(dec)?.into_tile(dec)
116 }
117}
118
119impl ParsedLayer<'_> {
120 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<Option<TileLayer>> {
123 match self {
124 Self::Tag01(l) => l.into_tile(dec).map(Some),
125 #[cfg(feature = "unstable-v2")]
126 Self::Tag02(l) => l.into_tile(dec).map(Some),
127 Self::Unknown(_) => Ok(None),
128 }
129 }
130}
131
132impl Layer<'_, Lazy> {
133 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<Option<TileLayer>> {
136 self.decode_all(dec)?.into_tile(dec)
137 }
138}
139
140#[cfg(feature = "unstable-v2")]
145fn m_values_of(
146 columns: &[ParsedMValue<'_>],
147 spans: &mut [MValueSpans<'_>],
148 dec: &mut Decoder,
149) -> MltResult<Vec<MValue>> {
150 let mut values = dec.alloc::<MValue>(columns.len())?;
151 for (column, spans) in columns.iter().zip(spans) {
152 let span = spans.next().transpose()?.flatten();
153 if let Some(span) = &span {
154 dec.consume(u32::try_from(column.values().row_bytes(span)).or_overflow()?)?;
155 }
156 values.push(column.values().row(column.name(), span)?);
157 }
158 Ok(values)
159}
160
161#[cfg(feature = "unstable-v2")]
163fn nested_of(
164 columns: &[ParsedNested<'_>],
165 index: usize,
166 dec: &mut Decoder,
167) -> MltResult<Vec<NestedValue>> {
168 let mut values = dec.alloc::<NestedValue>(columns.len())?;
169 for column in columns {
170 let value = column.row(index)?;
171 dec.consume(u32::try_from(value.heap_bytes()).or_overflow()?)?;
172 values.push(value);
173 }
174 Ok(values)
175}
176
177fn prop_value_from_ref(value: PropValueRef<'_>) -> PropValue {
180 match value {
181 PropValueRef::Bool(v) => PropValue::Bool(Some(v)),
182 PropValueRef::I8(v) => PropValue::I8(Some(v)),
183 PropValueRef::U8(v) => PropValue::U8(Some(v)),
184 PropValueRef::I32(v) => PropValue::I32(Some(v)),
185 PropValueRef::U32(v) => PropValue::U32(Some(v)),
186 PropValueRef::I64(v) => PropValue::I64(Some(v)),
187 PropValueRef::U64(v) => PropValue::U64(Some(v)),
188 PropValueRef::F32(v) => PropValue::F32(Some(v)),
189 PropValueRef::F64(v) => PropValue::F64(Some(v)),
190 PropValueRef::Str(s) => PropValue::Str(Some(s.to_string())),
191 }
192}
193
194fn typed_nulls(properties: &[ParsedProperty<'_>]) -> Vec<PropValue> {
201 use ParsedProperty as PP;
202 use PropValue as PV;
203 let mut nulls = Vec::new();
204 for prop in properties {
205 match prop {
206 PP::Bool(_) => nulls.push(PV::Bool(None)),
207 PP::I8(_) => nulls.push(PV::I8(None)),
208 PP::U8(_) => nulls.push(PV::U8(None)),
209 PP::I32(_) => nulls.push(PV::I32(None)),
210 PP::U32(_) => nulls.push(PV::U32(None)),
211 PP::I64(_) => nulls.push(PV::I64(None)),
212 PP::U64(_) => nulls.push(PV::U64(None)),
213 PP::F32(_) => nulls.push(PV::F32(None)),
214 PP::F64(_) => nulls.push(PV::F64(None)),
215 PP::Str(_) => nulls.push(PV::Str(None)),
216 PP::SharedDict(d) => {
217 for _ in &d.items {
218 nulls.push(PV::Str(None));
219 }
220 }
221 }
222 }
223 nulls
224}
225
226fn charge_str_props(dec: &mut Decoder, props: &[PropValue]) -> MltResult<()> {
228 let str_bytes = props
229 .iter()
230 .filter_map(|p| {
231 if let PropValue::Str(Some(s)) = p {
232 Some(s.len())
233 } else {
234 None
235 }
236 })
237 .try_fold(0u32, |acc, n| {
238 acc.checked_add(u32::try_from(n).or_overflow()?)
239 .or_overflow()
240 })?;
241 if str_bytes > 0 {
242 dec.consume(str_bytes)?;
243 }
244 Ok(())
245}