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().get();
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().clone(),
53 properties: values,
54 });
55 }
56
57 TileLayer::from_parts(name, extent, names, features)
58 }
59
60 #[must_use]
61 pub fn feature_count(&self) -> usize {
62 self.geometry.vector_types.len()
63 }
64}
65
66impl Layer01<'_> {
67 pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
69 self.decode_all(dec)?.into_tile(dec)
70 }
71}
72
73fn prop_value_from_ref(value: PropValueRef<'_>) -> PropValue {
76 match value {
77 PropValueRef::Bool(v) => PropValue::Bool(Some(v)),
78 PropValueRef::I8(v) => PropValue::I8(Some(v)),
79 PropValueRef::U8(v) => PropValue::U8(Some(v)),
80 PropValueRef::I32(v) => PropValue::I32(Some(v)),
81 PropValueRef::U32(v) => PropValue::U32(Some(v)),
82 PropValueRef::I64(v) => PropValue::I64(Some(v)),
83 PropValueRef::U64(v) => PropValue::U64(Some(v)),
84 PropValueRef::F32(v) => PropValue::F32(Some(v)),
85 PropValueRef::F64(v) => PropValue::F64(Some(v)),
86 PropValueRef::Str(s) => PropValue::Str(Some(s.to_string())),
87 }
88}
89
90fn typed_nulls(properties: &[ParsedProperty<'_>]) -> Vec<PropValue> {
97 use ParsedProperty as PP;
98 use PropValue as PV;
99 let mut nulls = Vec::new();
100 for prop in properties {
101 match prop {
102 PP::Bool(_) => nulls.push(PV::Bool(None)),
103 PP::I8(_) => nulls.push(PV::I8(None)),
104 PP::U8(_) => nulls.push(PV::U8(None)),
105 PP::I32(_) => nulls.push(PV::I32(None)),
106 PP::U32(_) => nulls.push(PV::U32(None)),
107 PP::I64(_) => nulls.push(PV::I64(None)),
108 PP::U64(_) => nulls.push(PV::U64(None)),
109 PP::F32(_) => nulls.push(PV::F32(None)),
110 PP::F64(_) => nulls.push(PV::F64(None)),
111 PP::Str(_) => nulls.push(PV::Str(None)),
112 PP::SharedDict(d) => {
113 for _ in &d.items {
114 nulls.push(PV::Str(None));
115 }
116 }
117 }
118 }
119 nulls
120}
121
122fn charge_str_props(dec: &mut Decoder, props: &[PropValue]) -> MltResult<()> {
124 let str_bytes = props
125 .iter()
126 .filter_map(|p| {
127 if let PropValue::Str(Some(s)) = p {
128 Some(s.len())
129 } else {
130 None
131 }
132 })
133 .try_fold(0u32, |acc, n| {
134 acc.checked_add(u32::try_from(n).or_overflow()?)
135 .or_overflow()
136 })?;
137 if str_bytes > 0 {
138 dec.consume(str_bytes)?;
139 }
140 Ok(())
141}