use bitvec::order::Lsb0;
use bitvec::slice::BitSlice;
use bitvec::view::BitView as _;
use usize_cast::IntoUsize as _;
use crate::LazyParsed::Raw;
use crate::MltError::{BufferUnderflow, MissingLayerName, TrailingLayerData};
use crate::codecs::varint::parse_varint;
use crate::decoder::stream::header02;
use crate::decoder::{
ColumnType02, DataType02, DictionaryType, GeoLayout, Id, Layer01, LayerLayout, LengthType,
Presence02, RawGeometry, RawId, RawIdValue, RawPresence, RawScalar, StreamType,
};
use crate::tile::Extent;
use crate::utils::{SetOptionOnce as _, parse_string, parse_u8, take};
use crate::{Lazy, MltError, MltRefResult, MltResult, Parser};
pub(crate) fn parse_layer02<'a>(
input: &'a [u8],
parser: &mut Parser,
) -> MltResult<Layer01<'a, Lazy>> {
let (input, layer_name) = parse_string(input)?;
if layer_name.is_empty() {
return Err(MissingLayerName);
}
let (input, extent) = parse_varint::<u32>(input)?;
let extent = Extent::new(extent)?;
let (input, feature_count) = parse_varint::<u32>(input)?;
let (input, layout_byte) = parse_u8(input)?;
let layout = LayerLayout::parse(layout_byte)?;
let (input, shared_presence) = parse_shared_presence(input, layout, feature_count)?;
let (input, geometry) = parse_geometry(input, layout.geometry, feature_count, parser)?;
let (mut input, column_count) = parse_varint::<u32>(input)?;
if input.len() < column_count.into_usize() {
return Err(BufferUnderflow(column_count, input.len()));
}
let mut id_column: Option<Id> = None;
let mut properties = Vec::with_capacity(column_count.into_usize());
#[cfg(fuzzing)]
let mut layer_order = vec![crate::decoder::fuzzing::LayerOrdering::Geometry];
for _ in 0..column_count {
use crate::decoder::RawProperty as RP;
let typ_byte;
(input, typ_byte) = parse_u8(input)?;
let typ = ColumnType02::parse(typ_byte, layout.shared_presence)?;
let name = if typ.data.has_name() {
let named;
(input, named) = parse_string(input)?;
named
} else {
""
};
let presence;
(input, presence) = parse_presence(typ, &shared_presence, input, feature_count)?;
let data_count = match &presence {
RawPresence::Bitfield(bits) => u32::try_from(bits.count_ones())?,
_ => feature_count,
};
let data = StreamType::Data(DictionaryType::None);
let value;
(input, value) = header02::parse_stream(input, data, data_count, parser)?;
#[cfg(fuzzing)]
layer_order.push(match typ.data {
DataType02::Id | DataType02::LongId => crate::decoder::fuzzing::LayerOrdering::Id,
_ => crate::decoder::fuzzing::LayerOrdering::Property,
});
let prop = match typ.data {
DataType02::Id => {
id_column.set_once(Raw(RawId {
presence,
value: RawIdValue::Id32(value),
}))?;
continue;
}
DataType02::LongId => {
id_column.set_once(Raw(RawId {
presence,
value: RawIdValue::Id64(value),
}))?;
continue;
}
DataType02::Bool => RP::Bool(RawScalar::new(name, presence, value)),
DataType02::I8 => RP::I8(RawScalar::new(name, presence, value)),
DataType02::U8 => RP::U8(RawScalar::new(name, presence, value)),
DataType02::I32 => RP::I32(RawScalar::new(name, presence, value)),
DataType02::U32 => RP::U32(RawScalar::new(name, presence, value)),
DataType02::I64 => RP::I64(RawScalar::new(name, presence, value)),
DataType02::U64 => RP::U64(RawScalar::new(name, presence, value)),
DataType02::F32 => RP::F32(RawScalar::new(name, presence, value)),
DataType02::F64 => RP::F64(RawScalar::new(name, presence, value)),
};
properties.push(Raw(prop));
}
if !input.is_empty() {
return Err(TrailingLayerData(input.len()));
}
Ok(Layer01 {
name: layer_name,
extent,
id: id_column,
geometry: Raw(geometry),
properties,
#[cfg(fuzzing)]
layer_order,
})
}
fn parse_shared_presence(
input: &[u8],
layout: LayerLayout,
feature_count: u32,
) -> MltRefResult<'_, Vec<&BitSlice<u8, Lsb0>>> {
let mut input = input;
let mut bitfields = Vec::with_capacity(usize::from(layout.shared_presence));
for _ in 0..layout.shared_presence {
let bits;
(input, bits) = parse_bitfield(input, feature_count)?;
bitfields.push(bits);
}
Ok((input, bitfields))
}
fn parse_bitfield(input: &[u8], feature_count: u32) -> MltRefResult<'_, &BitSlice<u8, Lsb0>> {
let (input, bytes) = take(input, feature_count.div_ceil(8))?;
Ok((
input,
&bytes.view_bits::<Lsb0>()[..feature_count.into_usize()],
))
}
fn parse_presence<'a>(
typ: ColumnType02,
shared: &[&'a BitSlice<u8, Lsb0>],
input: &'a [u8],
feature_count: u32,
) -> MltRefResult<'a, RawPresence<'a>> {
match typ.presence {
Presence02::AllPresent => Ok((input, RawPresence::AllPresent)),
Presence02::Inline => {
let (input, bits) = parse_bitfield(input, feature_count)?;
Ok((input, RawPresence::Bitfield(bits)))
}
Presence02::Shared(index) => shared
.get(usize::from(index))
.map(|&bits| (input, RawPresence::Bitfield(bits)))
.ok_or_else(|| MltError::ParsingColumnType(typ.to_byte())),
}
}
fn parse_geometry<'a>(
input: &'a [u8],
layout: GeoLayout,
feature_count: u32,
parser: &mut Parser,
) -> MltRefResult<'a, RawGeometry<'a>> {
if layout.is_dict() {
return Err(MltError::NotImplemented("v2 dict geometry layouts"));
}
if layout.is_tess() {
return Err(MltError::NotImplemented("v2 tessellated geometry layouts"));
}
let types_role = StreamType::Length(LengthType::VarBinary);
let (mut input, types) = header02::parse_stream(input, types_role, feature_count, parser)?;
let mut items = Vec::with_capacity(4);
let lengths = [
(layout.has_geo_lengths(), LengthType::Geometries),
(layout.has_part_lengths(), LengthType::Parts),
(layout.has_ring_lengths(), LengthType::Rings),
];
for (present, length_type) in lengths {
if present {
let role = StreamType::Length(length_type);
let stream;
(input, stream) = header02::parse_stream(input, role, feature_count, parser)?;
items.push(stream);
}
}
let vertex_role = StreamType::Data(DictionaryType::Vertex);
let (input, vertices) = header02::parse_stream(input, vertex_role, feature_count, parser)?;
items.push(vertices);
Ok((input, RawGeometry { meta: types, items }))
}