blackbox_log/frame/slow/
def.rs

1use alloc::vec::Vec;
2
3use tracing::instrument;
4
5use super::{RawSlowFrame, SlowUnit};
6use crate::frame::{self, DataFrameKind, DataFrameProperty, FieldDef, FieldDefDetails, FrameDef};
7use crate::headers::{ParseError, ParseResult};
8use crate::parser::{Encoding, InternalResult};
9use crate::predictor::{Predictor, PredictorContext};
10use crate::{Headers, Reader, Unit};
11
12/// The parsed frame definition for slow frames.
13#[derive(Debug, Clone)]
14pub struct SlowFrameDef<'data> {
15    pub(super) fields: Vec<SlowFieldDef<'data>>,
16}
17
18impl frame::seal::Sealed for SlowFrameDef<'_> {}
19
20impl<'data> FrameDef<'data> for SlowFrameDef<'data> {
21    type Unit = SlowUnit;
22
23    #[inline]
24    fn len(&self) -> usize {
25        self.fields.len()
26    }
27
28    fn get<'a>(&'a self, index: usize) -> Option<FieldDef<'data, Self::Unit>>
29    where
30        'data: 'a,
31    {
32        self.fields.get(index).map(
33            |&SlowFieldDef {
34                 name, unit, signed, ..
35             }| FieldDef { name, unit, signed },
36        )
37    }
38}
39
40impl<'data> SlowFrameDef<'data> {
41    pub(crate) fn builder() -> SlowFrameDefBuilder<'data> {
42        SlowFrameDefBuilder::default()
43    }
44
45    pub(crate) fn validate(
46        &self,
47        check_predictor: impl Fn(DataFrameKind, &'data str, Predictor, usize) -> ParseResult<()>,
48        check_unit: impl Fn(DataFrameKind, &'data str, Unit) -> ParseResult<()>,
49    ) -> ParseResult<()> {
50        for (
51            i,
52            SlowFieldDef {
53                name,
54                predictor,
55                unit,
56                ..
57            },
58        ) in self.fields.iter().enumerate()
59        {
60            check_predictor(DataFrameKind::Slow, name, *predictor, i)?;
61            check_unit(DataFrameKind::Slow, name, Unit::from(*unit))?;
62        }
63
64        Ok(())
65    }
66
67    #[instrument(level = "trace", name = "SlowFrameDef::parse", skip_all)]
68    pub(crate) fn parse(
69        &self,
70        data: &mut Reader,
71        headers: &Headers,
72    ) -> InternalResult<RawSlowFrame> {
73        let values = frame::parse_impl(
74            PredictorContext::new(headers),
75            &frame::read_field_values(data, &self.fields, |f| f.encoding)?,
76            self.fields.iter(),
77            |_, _| {},
78        );
79
80        Ok(RawSlowFrame(values))
81    }
82}
83
84#[derive(Debug, Clone)]
85pub(crate) struct SlowFieldDef<'data> {
86    pub(crate) name: &'data str,
87    pub(crate) predictor: Predictor,
88    pub(crate) encoding: Encoding,
89    pub(crate) unit: SlowUnit,
90    pub(crate) signed: bool,
91}
92
93impl<'data> FieldDefDetails<'data> for &SlowFieldDef<'data> {
94    fn name(&self) -> &'data str {
95        self.name
96    }
97
98    fn predictor(&self) -> Predictor {
99        self.predictor
100    }
101
102    fn encoding(&self) -> Encoding {
103        self.encoding
104    }
105
106    fn signed(&self) -> bool {
107        self.signed
108    }
109}
110
111#[derive(Debug, Default)]
112pub(crate) struct SlowFrameDefBuilder<'data> {
113    names: Option<&'data str>,
114    predictors: Option<&'data str>,
115    encodings: Option<&'data str>,
116    signs: Option<&'data str>,
117}
118
119impl<'data> SlowFrameDefBuilder<'data> {
120    pub(crate) fn update(&mut self, property: DataFrameProperty, value: &'data str) {
121        let value = Some(value);
122
123        match property {
124            DataFrameProperty::Name => self.names = value,
125            DataFrameProperty::Predictor => self.predictors = value,
126            DataFrameProperty::Encoding => self.encodings = value,
127            DataFrameProperty::Signed => self.signs = value,
128        }
129    }
130
131    pub(crate) fn parse(self) -> ParseResult<SlowFrameDef<'data>> {
132        let kind = DataFrameKind::Slow;
133
134        let mut names = frame::parse_names(kind, self.names)?;
135        let mut predictors = frame::parse_predictors(kind, self.predictors)?;
136        let mut encodings = frame::parse_encodings(kind, self.encodings)?;
137        let mut signs = frame::parse_signs(kind, self.signs)?;
138
139        let fields = (names.by_ref().zip(signs.by_ref()))
140            .zip(predictors.by_ref().zip(encodings.by_ref()))
141            .map(|((name, signed), (predictor, encoding))| {
142                Ok(SlowFieldDef {
143                    name,
144                    predictor: predictor?,
145                    encoding: encoding?,
146                    unit: unit_from_name(name),
147                    signed,
148                })
149            })
150            .collect::<Result<Vec<_>, _>>()?;
151
152        if names.next().is_some()
153            || predictors.next().is_some()
154            || encodings.next().is_some()
155            || signs.next().is_some()
156        {
157            tracing::error!("not all slow definition headers are of equal length");
158            return Err(ParseError::MalformedFrameDef(DataFrameKind::Slow));
159        }
160
161        Ok(SlowFrameDef { fields })
162    }
163}
164
165fn unit_from_name(name: &str) -> SlowUnit {
166    match name {
167        "flightModeFlags" => SlowUnit::FlightMode,
168        "stateFlags" => SlowUnit::State,
169        "failsafePhase" => SlowUnit::FailsafePhase,
170        "rxSignalReceived" | "rxFlightChannelsValid" => SlowUnit::Boolean,
171        _ => SlowUnit::Unitless,
172    }
173}