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