mlt_core/decoder/
into_tile.rs1use crate::decoder::{Layer01, ParsedLayer01, ParsedProperty, PropValueRef};
9use crate::errors::AsMltError as _;
10use crate::tile::{PropValue, TileFeature, TileLayer};
11use crate::{Decoder, LendingIterator, MltResult};
12
13impl ParsedLayer01<'_> {
14 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
17 let name = self.name().to_string();
19 let extent = self.extent().get();
20 let names: Vec<String> = self.iterate_prop_names().map(|n| n.to_string()).collect();
21 let col_nulls = typed_nulls(&self.properties);
22 let mut features = dec.alloc::<TileFeature>(self.feature_count())?;
23 let mut feat_iter = self.iter_features();
24 while let Some(feat) = feat_iter.next() {
25 let feat = feat?;
26 let mut values = dec.alloc::<PropValue>(names.len())?;
27 for (col_idx, value) in feat.iter_all_properties().enumerate() {
28 values.push(match value {
29 Some(v) => prop_value_from_ref(v),
30 None => col_nulls[col_idx].clone(),
31 });
32 }
33
34 charge_str_props(dec, &values)?;
35
36 features.push(TileFeature {
37 id: feat.id(),
38 geometry: feat.geometry().clone(),
39 properties: values,
40 });
41 }
42
43 TileLayer::from_parts(name, extent, names, features)
44 }
45}
46
47impl Layer01<'_> {
48 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
50 self.decode_all(dec)?.into_tile(dec)
51 }
52}
53
54fn prop_value_from_ref(value: PropValueRef<'_>) -> PropValue {
57 match value {
58 PropValueRef::Bool(v) => PropValue::Bool(Some(v)),
59 PropValueRef::I8(v) => PropValue::I8(Some(v)),
60 PropValueRef::U8(v) => PropValue::U8(Some(v)),
61 PropValueRef::I32(v) => PropValue::I32(Some(v)),
62 PropValueRef::U32(v) => PropValue::U32(Some(v)),
63 PropValueRef::I64(v) => PropValue::I64(Some(v)),
64 PropValueRef::U64(v) => PropValue::U64(Some(v)),
65 PropValueRef::F32(v) => PropValue::F32(Some(v)),
66 PropValueRef::F64(v) => PropValue::F64(Some(v)),
67 PropValueRef::Str(s) => PropValue::Str(Some(s.to_string())),
68 }
69}
70
71fn typed_nulls(properties: &[ParsedProperty<'_>]) -> Vec<PropValue> {
78 use ParsedProperty as PP;
79 use PropValue as PV;
80 let mut nulls = Vec::new();
81 for prop in properties {
82 match prop {
83 PP::Bool(_) => nulls.push(PV::Bool(None)),
84 PP::I8(_) => nulls.push(PV::I8(None)),
85 PP::U8(_) => nulls.push(PV::U8(None)),
86 PP::I32(_) => nulls.push(PV::I32(None)),
87 PP::U32(_) => nulls.push(PV::U32(None)),
88 PP::I64(_) => nulls.push(PV::I64(None)),
89 PP::U64(_) => nulls.push(PV::U64(None)),
90 PP::F32(_) => nulls.push(PV::F32(None)),
91 PP::F64(_) => nulls.push(PV::F64(None)),
92 PP::Str(_) => nulls.push(PV::Str(None)),
93 PP::SharedDict(d) => {
94 for _ in &d.items {
95 nulls.push(PV::Str(None));
96 }
97 }
98 }
99 }
100 nulls
101}
102
103fn charge_str_props(dec: &mut Decoder, props: &[PropValue]) -> MltResult<()> {
105 let str_bytes = props
106 .iter()
107 .filter_map(|p| {
108 if let PropValue::Str(Some(s)) = p {
109 Some(s.len())
110 } else {
111 None
112 }
113 })
114 .try_fold(0u32, |acc, n| {
115 acc.checked_add(u32::try_from(n).or_overflow()?)
116 .or_overflow()
117 })?;
118 if str_bytes > 0 {
119 dec.consume(str_bytes)?;
120 }
121 Ok(())
122}