Skip to main content

mlt_core/
enc_dec.rs

1use std::mem;
2
3use crate::analyse::{Analyze, StatType};
4use crate::v01::StreamMeta;
5use crate::{Decoder, MltError, MltResult};
6
7pub trait Decode<Parsed>: Sized {
8    fn decode(self, decoder: &mut Decoder) -> MltResult<Parsed>;
9}
10
11/// Shared wrapper for values that may still be in the original (raw) format or
12/// already parsed (but still columnar).
13/// Used by: `Id`, `Geometry`, `Property`, and eventually - `SharedDictItem`
14#[allow(clippy::large_enum_variant)]
15#[derive(Debug, PartialEq, Clone)]
16#[cfg_attr(all(not(test), feature = "arbitrary"), derive(arbitrary::Arbitrary))]
17pub enum EncDec<Raw, Parsed> {
18    Raw(Raw),       // Raw
19    Parsed(Parsed), // Parsed
20    ParsingFailed,
21}
22
23impl<Raw: Decode<Parsed>, Parsed> EncDec<Raw, Parsed> {
24    /// Decode in place, replacing the raw value with the parsed result.
25    pub fn decode(&mut self, decoder: &mut Decoder) -> MltResult<&mut Parsed> {
26        match self {
27            Self::Parsed(v) => Ok(v),
28            Self::Raw(_) => {
29                let Self::Raw(raw) = mem::replace(self, Self::ParsingFailed) else {
30                    unreachable!();
31                };
32                *self = Self::Parsed(raw.decode(decoder)?);
33                let Self::Parsed(v) = self else {
34                    unreachable!()
35                };
36                Ok(v)
37            }
38            Self::ParsingFailed => Err(MltError::PriorParseFailure),
39        }
40    }
41
42    /// Consume and return the parsed value, decoding if currently raw.
43    pub fn into_parsed(self, decoder: &mut Decoder) -> MltResult<Parsed> {
44        match self {
45            Self::Parsed(v) => Ok(v),
46            Self::Raw(raw) => raw.decode(decoder),
47            Self::ParsingFailed => Err(MltError::PriorParseFailure),
48        }
49    }
50
51    pub fn as_parsed(&self) -> MltResult<&Parsed> {
52        match self {
53            Self::Parsed(v) => Ok(v),
54            Self::Raw(_) => Err(MltError::NotDecoded("enc_dec value")), // TODO: I wonder if the str can be of the type name?
55            Self::ParsingFailed => Err(MltError::PriorParseFailure),
56        }
57    }
58}
59
60impl<Raw: Analyze, Parsed: Analyze> Analyze for EncDec<Raw, Parsed> {
61    fn collect_statistic(&self, stat: StatType) -> usize {
62        match self {
63            Self::Raw(encoded) => encoded.collect_statistic(stat),
64            Self::Parsed(decoded) => decoded.collect_statistic(stat),
65            Self::ParsingFailed => 0,
66        }
67    }
68
69    fn for_each_stream(&self, cb: &mut dyn FnMut(StreamMeta)) {
70        match self {
71            Self::Raw(encoded) => encoded.for_each_stream(cb),
72            Self::Parsed(decoded) => decoded.for_each_stream(cb),
73            Self::ParsingFailed => {}
74        }
75    }
76}