Skip to main content

mlt_core/decoder/
layer.rs

1use crate::codecs::varint::parse_varint;
2#[cfg(feature = "unstable-v2")]
3use crate::decoder::root02::parse_layer02;
4use crate::decoder::{Layer01, ParsedLayer01, Unknown};
5#[cfg(feature = "unstable-v2")]
6use crate::decoder::{Layer02, ParsedLayer02};
7use crate::utils::{parse_u8, take};
8use crate::{
9    DecodeState, Decoder, Layer, Lazy, MltError, MltRefResult, MltResult, ParsedLayer, Parser,
10};
11
12impl<'a, S: DecodeState> Layer<'a, S> {
13    /// The layer's name whatever its tag, or `None` for a tag this build does not
14    /// know. A value, unlike a layer, cannot silently lose a version's columns.
15    #[must_use]
16    pub fn name(&self) -> Option<&'a str> {
17        match self {
18            Self::Tag01(l) => Some(l.name()),
19            #[cfg(feature = "unstable-v2")]
20            Self::Tag02(l) => Some(l.layer().name()),
21            Self::Unknown(_) => None,
22        }
23    }
24}
25
26impl<'a> Layer<'a> {
27    /// Parse a single tuple that consists of `size (varint)`, `tag (varint)`, and `value (bytes)`.
28    /// Reserves memory for decoded data against the parser's budget.
29    pub(crate) fn from_bytes(input: &'a [u8], parser: &mut Parser) -> MltRefResult<'a, Self> {
30        let (input, size) = parse_varint::<u32>(input)?;
31
32        // tag is a varint, but we know fewer than 127 tags for now,
33        // so we can use a faster u8 and fail if it is bigger than 127.
34        let (input, tag) = parse_u8(input)?;
35        // 1 byte must be parsed for the tag, so if size is 0, it's invalid
36        let size = size.checked_sub(1).ok_or(MltError::ZeroLayerSize)?;
37        let (input, value) = take(input, size)?;
38
39        let layer = match tag {
40            1 => Layer::Tag01(Layer01::from_bytes(value, parser)?),
41            #[cfg(feature = "unstable-v2")]
42            2 => Layer::Tag02(parse_layer02(value, parser)?),
43            tag => Layer::Unknown(Unknown { tag, value }),
44        };
45
46        Ok((input, layer))
47    }
48
49    /// Decode all columns and return a fully-decoded [`ParsedLayer`].
50    ///
51    /// Consumes `self`.  For partial / incremental decoding, destructure with
52    /// `Layer::Tag01(lazy)` and call the individual methods on [`Layer01`].
53    pub fn decode_all(self, dec: &mut Decoder) -> MltResult<ParsedLayer<'a>> {
54        match self {
55            Layer::Tag01(v) => Ok(Layer::Tag01(v.decode_all(dec)?)),
56            #[cfg(feature = "unstable-v2")]
57            Layer::Tag02(v) => Ok(Layer::Tag02(v.decode_all(dec)?)),
58            Layer::Unknown(u) => Ok(Layer::Unknown(u)),
59        }
60    }
61}
62
63impl<'a> Layer01<'a, Lazy> {
64    /// Decode all columns and transition to [`Layer01<Parsed>`].
65    ///
66    /// Consumes `self` (a `Layer01<Lazy>`) and returns a `Layer01<Parsed>` where every
67    /// column field holds its parsed value directly, enabling infallible readonly access.
68    pub fn decode_all(self, dec: &mut Decoder) -> MltResult<ParsedLayer01<'a>> {
69        Ok(Layer01 {
70            name: self.name,
71            extent: self.extent,
72            id: self.id.map(|id| id.into_parsed(dec)).transpose()?,
73            geometry: self.geometry.into_parsed(dec)?,
74            properties: self
75                .properties
76                .into_iter()
77                .map(|p| p.into_parsed(dec))
78                .collect::<MltResult<Vec<_>>>()?,
79            #[cfg(fuzzing)]
80            layer_order: self.layer_order,
81        })
82    }
83}
84
85#[cfg(feature = "unstable-v2")]
86impl<'a> Layer02<'a, Lazy> {
87    /// Decode every column, shared and v2-only.
88    pub fn decode_all(self, dec: &mut Decoder) -> MltResult<ParsedLayer02<'a>> {
89        let layer = Layer02 {
90            layer: self.layer.decode_all(dec)?,
91            nested: self
92                .nested
93                .into_iter()
94                .map(|n| n.into_parsed(dec))
95                .collect::<MltResult<Vec<_>>>()?,
96            m_values: self
97                .m_values
98                .into_iter()
99                .map(|m| m.into_parsed(dec))
100                .collect::<MltResult<Vec<_>>>()?,
101        };
102        // An m-value column's length is only checkable once the geometry is decoded
103        // too, which it now is. Every later walk of a column relies on this check.
104        for column in &layer.m_values {
105            column.check_length(&layer.layer.geometry)?;
106        }
107        Ok(layer)
108    }
109}