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