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#[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 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 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 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}