blackbox_log/frame/main/
def.rs

1use alloc::borrow::ToOwned as _;
2use alloc::vec::Vec;
3
4use tracing::instrument;
5
6use super::{MainUnit, RawMainFrame};
7use crate::frame::{self, DataFrameKind, DataFrameProperty, FieldDef, FieldDefDetails, FrameDef};
8use crate::headers::{ParseError, ParseResult};
9use crate::parser::{decode, Encoding, InternalResult};
10use crate::predictor::{self, Predictor, PredictorContext};
11use crate::utils::to_base_field;
12use crate::{Headers, Reader, Unit};
13
14/// The parsed frame definition for main frames.
15#[derive(Debug, Clone)]
16pub struct MainFrameDef<'data> {
17    iteration: MainFieldDef<'data>,
18    pub(super) fields: Vec<MainFieldDef<'data>>,
19    pub(crate) index_motor_0: Option<usize>,
20}
21
22impl frame::seal::Sealed for MainFrameDef<'_> {}
23
24impl<'data> FrameDef<'data> for MainFrameDef<'data> {
25    type Unit = MainUnit;
26
27    #[inline]
28    fn len(&self) -> usize {
29        // Plus loopIteration
30        self.fields.len() + 1
31    }
32
33    fn get<'a>(&'a self, index: usize) -> Option<FieldDef<'data, Self::Unit>>
34    where
35        'data: 'a,
36    {
37        let field = if index == 0 {
38            Some(&self.iteration)
39        } else {
40            self.fields.get(index - 1)
41        };
42
43        field.map(
44            |&MainFieldDef {
45                 name, signed, unit, ..
46             }| FieldDef { name, unit, signed },
47        )
48    }
49}
50
51impl<'data> MainFrameDef<'data> {
52    pub(crate) fn builder() -> MainFrameDefBuilder<'data> {
53        MainFrameDefBuilder::default()
54    }
55
56    /// # Panics
57    ///
58    /// Panics if there is no `motor[0]` field in the frame
59    pub(crate) fn get_motor_0_from(&self, frame: &[u32]) -> u32 {
60        frame[self.index_motor_0.unwrap()]
61    }
62
63    pub(crate) fn validate(
64        &self,
65        check_predictor: impl Fn(DataFrameKind, &'data str, Predictor, usize) -> ParseResult<()>,
66        check_unit: impl Fn(DataFrameKind, &'data str, Unit) -> ParseResult<()>,
67    ) -> ParseResult<()> {
68        for (
69            i,
70            MainFieldDef {
71                name,
72                predictor_intra,
73                predictor_inter,
74                unit,
75                ..
76            },
77        ) in self.fields.iter().enumerate()
78        {
79            check_predictor(DataFrameKind::Intra, name, *predictor_intra, i)?;
80            check_predictor(DataFrameKind::Inter, name, *predictor_inter, i)?;
81            check_unit(DataFrameKind::Intra, name, Unit::from(*unit))?;
82        }
83
84        Ok(())
85    }
86
87    #[instrument(level = "trace", skip_all)]
88    pub(crate) fn parse_intra(
89        &self,
90        data: &mut Reader,
91        headers: &Headers,
92        last: Option<&RawMainFrame>,
93    ) -> InternalResult<RawMainFrame> {
94        fn get_update_ctx(
95            last: Option<&'_ RawMainFrame>,
96        ) -> impl Fn(&mut PredictorContext, usize) + '_ {
97            move |ctx, i| ctx.set_last(last.map(|l| l.values[i]))
98        }
99
100        let iteration = decode::variable(data)?;
101        tracing::trace!(iteration);
102        let time = decode::variable(data)?.into();
103        tracing::trace!(time);
104
105        let values = frame::parse_impl(
106            PredictorContext::new(headers),
107            &frame::read_field_values(data, &self.fields, |f| f.encoding_intra)?,
108            self.fields.iter().map(IntraFieldDef),
109            get_update_ctx(last),
110        );
111
112        Ok(RawMainFrame {
113            intra: true,
114            iteration,
115            time,
116            values,
117        })
118    }
119
120    #[instrument(level = "trace", skip_all)]
121    pub(crate) fn parse_inter(
122        &self,
123        data: &mut Reader,
124        headers: &Headers,
125        last: Option<&RawMainFrame>,
126        last_last: Option<&RawMainFrame>,
127        skipped_frames: u32,
128    ) -> InternalResult<RawMainFrame> {
129        fn get_update_ctx<'a>(
130            last: Option<&'a RawMainFrame>,
131            last_last: Option<&'a RawMainFrame>,
132        ) -> impl Fn(&mut PredictorContext<'_, '_>, usize) + 'a {
133            move |ctx, i| {
134                ctx.set_last_2(last.map(|l| l.values[i]), last_last.map(|l| l.values[i]));
135            }
136        }
137
138        let iteration = 1 + last.map_or(0, |f| f.iteration) + skipped_frames;
139        tracing::trace!(iteration);
140
141        let time = {
142            // Get the time from last_last if last was an interframe
143            let last_last = last
144                .filter(|f| !f.intra)
145                .and_then(|_| last_last.map(|f| f.time));
146
147            let time = predictor::straight_line(last.map(|f| f.time), last_last);
148            let offset = decode::variable_signed(data)?;
149            let time = time.saturating_add_signed(offset.into());
150
151            tracing::trace!(time, offset);
152            time
153        };
154
155        let values = frame::parse_impl(
156            PredictorContext::with_skipped(headers, skipped_frames),
157            &frame::read_field_values(data, &self.fields, |f| f.encoding_inter)?,
158            self.fields.iter().map(InterFieldDef),
159            get_update_ctx(last, last_last),
160        );
161
162        Ok(RawMainFrame {
163            intra: false,
164            iteration,
165            time,
166            values,
167        })
168    }
169}
170
171#[derive(Debug, Clone)]
172pub(crate) struct MainFieldDef<'data> {
173    pub(crate) name: &'data str,
174    predictor_intra: Predictor,
175    predictor_inter: Predictor,
176    encoding_intra: Encoding,
177    encoding_inter: Encoding,
178    pub(crate) signed: bool,
179    pub(crate) unit: MainUnit,
180}
181
182#[derive(Debug)]
183struct InterFieldDef<'a, 'data>(&'a MainFieldDef<'data>);
184
185impl<'data> FieldDefDetails<'data> for InterFieldDef<'_, 'data> {
186    fn name(&self) -> &'data str {
187        self.0.name
188    }
189
190    fn predictor(&self) -> Predictor {
191        self.0.predictor_inter
192    }
193
194    fn encoding(&self) -> Encoding {
195        self.0.encoding_inter
196    }
197
198    fn signed(&self) -> bool {
199        self.0.signed
200    }
201}
202
203#[derive(Debug)]
204struct IntraFieldDef<'a, 'data>(&'a MainFieldDef<'data>);
205
206impl<'data> FieldDefDetails<'data> for IntraFieldDef<'_, 'data> {
207    fn name(&self) -> &'data str {
208        self.0.name
209    }
210
211    fn predictor(&self) -> Predictor {
212        self.0.predictor_intra
213    }
214
215    fn encoding(&self) -> Encoding {
216        self.0.encoding_intra
217    }
218
219    fn signed(&self) -> bool {
220        self.0.signed
221    }
222}
223
224#[derive(Debug, Default)]
225pub(crate) struct MainFrameDefBuilder<'data> {
226    names: Option<&'data str>,
227    predictors_intra: Option<&'data str>,
228    predictors_inter: Option<&'data str>,
229    encodings_intra: Option<&'data str>,
230    encodings_inter: Option<&'data str>,
231    signs: Option<&'data str>,
232}
233
234impl<'data> MainFrameDefBuilder<'data> {
235    pub(crate) fn update(
236        &mut self,
237        kind: DataFrameKind,
238        property: DataFrameProperty,
239        value: &'data str,
240    ) {
241        let value = Some(value);
242
243        match (kind, property) {
244            (_, DataFrameProperty::Name) => self.names = value,
245            (_, DataFrameProperty::Signed) => self.signs = value,
246
247            (DataFrameKind::Intra, DataFrameProperty::Predictor) => self.predictors_intra = value,
248            (DataFrameKind::Inter, DataFrameProperty::Predictor) => self.predictors_inter = value,
249
250            (DataFrameKind::Intra, DataFrameProperty::Encoding) => self.encodings_intra = value,
251            (DataFrameKind::Inter, DataFrameProperty::Encoding) => self.encodings_inter = value,
252            _ => unreachable!(),
253        }
254    }
255
256    pub(crate) fn parse(self) -> ParseResult<MainFrameDef<'data>> {
257        let kind_intra = DataFrameKind::Intra;
258        let kind_inter = DataFrameKind::Inter;
259
260        let mut names = frame::parse_names(kind_intra, self.names)?;
261        let mut predictors_intra = frame::parse_predictors(kind_intra, self.predictors_intra)?;
262        let mut predictors_inter = frame::parse_predictors(kind_inter, self.predictors_inter)?;
263        let mut encodings_intra = frame::parse_encodings(kind_intra, self.encodings_intra)?;
264        let mut encodings_inter = frame::parse_encodings(kind_inter, self.encodings_inter)?;
265        let mut signs = frame::parse_signs(kind_intra, self.signs)?;
266
267        let mut fields = (names.by_ref().zip(signs.by_ref()))
268            .zip(predictors_intra.by_ref().zip(predictors_inter.by_ref()))
269            .zip(encodings_intra.by_ref().zip(encodings_inter.by_ref()))
270            .map(
271                |(
272                    ((name, signed), (predictor_intra, predictor_inter)),
273                    (encoding_intra, encoding_inter),
274                )| {
275                    Ok(MainFieldDef {
276                        name,
277                        predictor_intra: predictor_intra?,
278                        predictor_inter: predictor_inter?,
279                        encoding_intra: encoding_intra?,
280                        encoding_inter: encoding_inter?,
281                        signed,
282                        unit: unit_from_name(name),
283                    })
284                },
285            );
286
287        let Some(
288            iteration @ MainFieldDef {
289                name: "loopIteration",
290                predictor_intra: Predictor::Zero,
291                predictor_inter: Predictor::Increment,
292                encoding_intra: Encoding::Variable,
293                encoding_inter: Encoding::Null,
294                ..
295            },
296        ) = fields.next().transpose()?
297        else {
298            return Err(ParseError::MissingField {
299                frame: DataFrameKind::Intra,
300                field: "loopIteration".to_owned(),
301            });
302        };
303
304        if !matches!(
305            fields.next().transpose()?,
306            Some(MainFieldDef {
307                name: "time",
308                predictor_intra: Predictor::Zero,
309                predictor_inter: Predictor::StraightLine,
310                encoding_intra: Encoding::Variable,
311                encoding_inter: Encoding::VariableSigned,
312                ..
313            })
314        ) {
315            return Err(ParseError::MissingField {
316                frame: DataFrameKind::Intra,
317                field: "time".to_owned(),
318            });
319        }
320
321        let fields = fields.collect::<Result<Vec<_>, _>>()?;
322
323        if names.next().is_some()
324            || predictors_intra.next().is_some()
325            || encodings_intra.next().is_some()
326            || signs.next().is_some()
327        {
328            tracing::error!("not all intraframe definition headers are of equal length");
329            return Err(ParseError::MalformedFrameDef(DataFrameKind::Intra));
330        }
331
332        if predictors_inter.next().is_some() || encodings_inter.next().is_some() {
333            tracing::error!("not all interframe definition headers are of equal length");
334            return Err(ParseError::MalformedFrameDef(DataFrameKind::Inter));
335        }
336
337        let index_motor_0 = fields.iter().position(|f| f.name == "motor[0]");
338
339        Ok(MainFrameDef {
340            iteration,
341            fields,
342            index_motor_0,
343        })
344    }
345}
346
347fn unit_from_name(name: &str) -> MainUnit {
348    match to_base_field(name) {
349        "vbat" | "vbatLatest" => MainUnit::Voltage,
350        "amperageLatest" => MainUnit::Amperage,
351        "accSmooth" => MainUnit::Acceleration,
352        "gyroADC" => MainUnit::Rotation,
353        _ => MainUnit::Unitless,
354    }
355}