use crate::decoder::{Layer01, ParsedLayer01, ParsedProperty, PropValueRef};
#[cfg(feature = "unstable-v2")]
use crate::decoder::{MValueSpans, ParsedMValue, ParsedNested};
use crate::errors::AsMltError as _;
#[cfg(feature = "unstable-v2")]
use crate::tile::{MValue, NestedKind, NestedValue};
use crate::tile::{PropValue, TileFeature, TileLayer};
use crate::{Decoder, LendingIterator, MltResult};
impl ParsedLayer01<'_> {
pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
let name = self.name().to_string();
let extent = self.extent().get();
let names: Vec<String> = self.iterate_prop_names().map(|n| n.to_string()).collect();
let col_nulls = typed_nulls(&self.properties);
#[cfg(feature = "unstable-v2")]
let m_names: Vec<String> = self.m_values.iter().map(|m| m.name().to_string()).collect();
#[cfg(feature = "unstable-v2")]
let nested_names: Vec<String> = self.nested.iter().map(|n| n.name().to_string()).collect();
#[cfg(feature = "unstable-v2")]
let nested_kinds: Vec<NestedKind> = self.nested.iter().map(ParsedNested::kind).collect();
#[cfg(feature = "unstable-v2")]
let mut m_spans = dec.alloc::<MValueSpans>(self.m_values.len())?;
#[cfg(feature = "unstable-v2")]
m_spans.extend(self.m_values.iter().map(|m| m.spans(&self.geometry)));
let mut features = dec.alloc::<TileFeature>(self.feature_count())?;
#[cfg(feature = "unstable-v2")]
let mut index = 0_usize;
let mut feat_iter = self.iter_features();
while let Some(feat) = feat_iter.next() {
let feat = feat?;
let mut values = dec.alloc::<PropValue>(names.len())?;
for (col_idx, value) in feat.iter_all_properties().enumerate() {
values.push(match value {
Some(v) => prop_value_from_ref(v),
None => col_nulls[col_idx].clone(),
});
}
charge_str_props(dec, &values)?;
features.push(TileFeature {
id: feat.id(),
geometry: feat.geometry().clone(),
properties: values,
#[cfg(feature = "unstable-v2")]
m_values: m_values_of(&self.m_values, &mut m_spans, dec)?,
#[cfg(feature = "unstable-v2")]
nested: nested_of(&self.nested, index, dec)?,
});
#[cfg(feature = "unstable-v2")]
{
index += 1;
}
}
let layer = TileLayer::from_parts(name, extent, names, features)?;
#[cfg(feature = "unstable-v2")]
let layer = layer
.with_m_value_names(m_names)?
.with_nested(nested_names, nested_kinds)?;
Ok(layer)
}
}
impl Layer01<'_> {
pub fn into_tile(self, dec: &mut Decoder) -> MltResult<TileLayer> {
self.decode_all(dec)?.into_tile(dec)
}
}
#[cfg(feature = "unstable-v2")]
fn m_values_of(
columns: &[ParsedMValue<'_>],
spans: &mut [MValueSpans<'_>],
dec: &mut Decoder,
) -> MltResult<Vec<MValue>> {
let mut values = dec.alloc::<MValue>(columns.len())?;
for (column, spans) in columns.iter().zip(spans) {
let span = spans.next().transpose()?.flatten();
if let Some(span) = &span {
dec.consume(u32::try_from(column.values().row_bytes(span)).or_overflow()?)?;
}
values.push(column.values().row(column.name(), span)?);
}
Ok(values)
}
#[cfg(feature = "unstable-v2")]
fn nested_of(
columns: &[ParsedNested<'_>],
index: usize,
dec: &mut Decoder,
) -> MltResult<Vec<NestedValue>> {
let mut values = dec.alloc::<NestedValue>(columns.len())?;
for column in columns {
let value = column.row(index)?;
dec.consume(u32::try_from(value.heap_bytes()).or_overflow()?)?;
values.push(value);
}
Ok(values)
}
fn prop_value_from_ref(value: PropValueRef<'_>) -> PropValue {
match value {
PropValueRef::Bool(v) => PropValue::Bool(Some(v)),
PropValueRef::I8(v) => PropValue::I8(Some(v)),
PropValueRef::U8(v) => PropValue::U8(Some(v)),
PropValueRef::I32(v) => PropValue::I32(Some(v)),
PropValueRef::U32(v) => PropValue::U32(Some(v)),
PropValueRef::I64(v) => PropValue::I64(Some(v)),
PropValueRef::U64(v) => PropValue::U64(Some(v)),
PropValueRef::F32(v) => PropValue::F32(Some(v)),
PropValueRef::F64(v) => PropValue::F64(Some(v)),
PropValueRef::Str(s) => PropValue::Str(Some(s.to_string())),
}
}
fn typed_nulls(properties: &[ParsedProperty<'_>]) -> Vec<PropValue> {
use ParsedProperty as PP;
use PropValue as PV;
let mut nulls = Vec::new();
for prop in properties {
match prop {
PP::Bool(_) => nulls.push(PV::Bool(None)),
PP::I8(_) => nulls.push(PV::I8(None)),
PP::U8(_) => nulls.push(PV::U8(None)),
PP::I32(_) => nulls.push(PV::I32(None)),
PP::U32(_) => nulls.push(PV::U32(None)),
PP::I64(_) => nulls.push(PV::I64(None)),
PP::U64(_) => nulls.push(PV::U64(None)),
PP::F32(_) => nulls.push(PV::F32(None)),
PP::F64(_) => nulls.push(PV::F64(None)),
PP::Str(_) => nulls.push(PV::Str(None)),
PP::SharedDict(d) => {
for _ in &d.items {
nulls.push(PV::Str(None));
}
}
}
}
nulls
}
fn charge_str_props(dec: &mut Decoder, props: &[PropValue]) -> MltResult<()> {
let str_bytes = props
.iter()
.filter_map(|p| {
if let PropValue::Str(Some(s)) = p {
Some(s.len())
} else {
None
}
})
.try_fold(0u32, |acc, n| {
acc.checked_add(u32::try_from(n).or_overflow()?)
.or_overflow()
})?;
if str_bytes > 0 {
dec.consume(str_bytes)?;
}
Ok(())
}