mlt_core/decoder/model.rs
1//! Version-agnostic decode-side layer types.
2//!
3//! [`Layer01`] is the in-memory columnar form for *both* tag `0x01` and tag
4//! `0x02` layers - the two differ only in wire format, which lives in
5//! [`super::model01`] and `model02`.
6
7use crate::decoder::model01::Layer01;
8#[cfg(feature = "unstable-v2")]
9use crate::decoder::model02::Layer02;
10use crate::{DecodeState, Lazy, MltResult, Parsed};
11
12/// A layer that can be one of the known types, or an unknown.
13///
14/// The decode-state type parameter `S` mirrors [`Layer01<'a, S>`]:
15/// - `Layer<'a>` / `Layer<'a, Lazy>` - freshly parsed; columns may still be raw bytes.
16/// - `Layer<'a, Parsed>` - returned by [`Layer::decode_all`]; all columns are decoded. Use `ParsedLayer` alias.
17#[derive(Debug)]
18#[non_exhaustive]
19pub enum Layer<'a, S: DecodeState = Lazy> {
20 /// MVT-compatible layer (tag = 1)
21 Tag01(Layer01<'a, S>),
22 /// Experimental v2 layer (tag = 2).
23 ///
24 /// Carries the same columnar representation as `Tag01` plus the columns only
25 /// v2 has, in a more compact wire format.
26 #[cfg(feature = "unstable-v2")]
27 Tag02(Layer02<'a, S>),
28 /// Unknown layer with tag, size, and value
29 Unknown(Unknown<'a>),
30}
31pub type ParsedLayer<'a> = Layer<'a, Parsed>;
32
33/// Every layer starts with a one-byte tag that its size varint counts.
34const TAG_LEN: u32 = 1;
35
36/// The bytes a layer spends on the wire, by what they hold.
37///
38/// Every byte the columns leave over is layer metadata: the tag, name and header.
39/// A v1 layer also keeps its column schema there, while a v2 column counts its own type byte and name.
40#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
41pub struct LayerBytes {
42 pub(crate) size: u32,
43 pub(crate) geometry: u32,
44 pub(crate) properties: u32,
45 pub(crate) ids: u32,
46}
47
48impl LayerBytes {
49 /// Start counting a layer whose body is `body_len` bytes.
50 pub(crate) fn of_body(body_len: usize) -> Self {
51 Self {
52 // The body never exceeds the u32 size varint that framed it.
53 size: u32::try_from(body_len).map_or(u32::MAX, |len| len.saturating_add(TAG_LEN)),
54 ..Self::default()
55 }
56 }
57
58 /// Count `spent` bytes against the geometry.
59 pub(crate) fn add_geometry(&mut self, spent: usize) -> MltResult<()> {
60 self.geometry += u32::try_from(spent)?;
61 Ok(())
62 }
63
64 /// Count `spent` bytes against the id column.
65 pub(crate) fn add_ids(&mut self, spent: usize) -> MltResult<()> {
66 self.ids += u32::try_from(spent)?;
67 Ok(())
68 }
69
70 /// Count `spent` bytes against the properties.
71 pub(crate) fn add_properties(&mut self, spent: usize) -> MltResult<()> {
72 self.properties += u32::try_from(spent)?;
73 Ok(())
74 }
75
76 /// The value of the layer's size varint: the tag and the body, without the varint itself.
77 #[must_use]
78 pub fn size(&self) -> u32 {
79 self.size
80 }
81
82 /// The geometry column, or the v2 geometry section.
83 #[must_use]
84 pub fn geometry(&self) -> u32 {
85 self.geometry
86 }
87
88 /// Every column that is neither geometry nor the id, nested and m-value columns included.
89 #[must_use]
90 pub fn properties(&self) -> u32 {
91 self.properties
92 }
93
94 /// The id column.
95 #[must_use]
96 pub fn ids(&self) -> u32 {
97 self.ids
98 }
99
100 /// What is left of [`Self::size`] once every column is taken out.
101 #[must_use]
102 pub fn metadata(&self) -> u32 {
103 self.size - self.geometry - self.properties - self.ids
104 }
105}
106
107/// Unknown layer data, stored as encoded bytes.
108///
109/// Returned inside [`Layer::Unknown`] for any layer tag that is not recognized
110/// by this version of the library. Consumers can inspect the tag and raw bytes
111/// to forward or log the layer without losing data.
112#[derive(Debug, Clone, Default, PartialEq)]
113pub struct Unknown<'a> {
114 pub(crate) tag: u8,
115 pub(crate) value: &'a [u8],
116}
117
118impl<'a> Unknown<'a> {
119 /// The raw layer tag identifying this unrecognised layer type.
120 #[must_use]
121 pub fn tag(&self) -> u32 {
122 u32::from(self.tag)
123 }
124
125 /// The raw encoded bytes of this layer's body.
126 #[must_use]
127 pub fn data(&self) -> &'a [u8] {
128 self.value
129 }
130}