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