Skip to main content

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}