Skip to main content

defmt_decoder/
decoder.rs

1use std::{
2    convert::{TryFrom, TryInto},
3    ops::Range,
4};
5
6use crate::{Arg, DecodeError, FormatSliceElement, Table};
7use byteorder::{ReadBytesExt, LE};
8use defmt_parser::{get_max_bitfield_range, Fragment, Parameter, Type};
9
10pub(crate) struct Decoder<'t, 'b> {
11    table: &'t Table,
12    pub bytes: &'b [u8],
13}
14
15impl<'t, 'b> Decoder<'t, 'b> {
16    pub fn new(table: &'t Table, bytes: &'b [u8]) -> Self {
17        Self { table, bytes }
18    }
19
20    /// Sort and deduplicate `params` so that they can be interpreted correctly during decoding
21    fn prepare_params(&self, params: &mut Vec<Parameter>) {
22        // deduplicate bitfields by merging them by index
23        merge_bitfields(params);
24
25        // sort & dedup to ensure that format string args can be addressed by index too
26        params.sort_by(|a, b| a.index.cmp(&b.index));
27        params.dedup_by(|a, b| a.index == b.index);
28    }
29
30    /// Gets a format string from `bytes` and `table`
31    fn get_format(&mut self) -> Result<&'t str, DecodeError> {
32        let index = self.bytes.read_u16::<LE>()? as usize;
33        let format = self
34            .table
35            .get_without_level(index)
36            .map_err(|_| DecodeError::Malformed)?;
37
38        Ok(format)
39    }
40
41    fn get_variant(&mut self, format: &'t str) -> Result<&'t str, DecodeError> {
42        assert!(format.contains('|'));
43        // NOTE nesting of enums, like "A|B(C|D)" is not possible; indirection is
44        // required: "A|B({:?})" where "{:?}" -> "C|D"
45        let num_variants = format.chars().filter(|c| *c == '|').count();
46
47        let discriminant: usize = if u8::try_from(num_variants).is_ok() {
48            self.bytes.read_u8()?.into()
49        } else if u16::try_from(num_variants).is_ok() {
50            self.bytes.read_u16::<LE>()?.into()
51        } else if u32::try_from(num_variants).is_ok() {
52            self.bytes
53                .read_u32::<LE>()?
54                .try_into()
55                .map_err(|_| DecodeError::Malformed)?
56        } else if u64::try_from(num_variants).is_ok() {
57            self.bytes
58                .read_u64::<LE>()?
59                .try_into()
60                .map_err(|_| DecodeError::Malformed)?
61        } else {
62            return Err(DecodeError::Malformed);
63        };
64
65        format
66            .split('|')
67            .nth(discriminant)
68            .ok_or(DecodeError::Malformed)
69    }
70
71    fn decode_format_slice(
72        &mut self,
73        num_elements: usize,
74    ) -> Result<Vec<FormatSliceElement<'t>>, DecodeError> {
75        let format = self.get_format()?;
76        let is_enum = format.contains('|');
77
78        let mut elements = Vec::with_capacity(num_elements);
79        for _i in 0..num_elements {
80            let format = if is_enum {
81                self.get_variant(format)?
82            } else {
83                format
84            };
85            let args = self.decode_format(format)?;
86            elements.push(FormatSliceElement { format, args });
87        }
88
89        Ok(elements)
90    }
91
92    /// Decodes arguments from the stream, according to `format`.
93    pub fn decode_format(&mut self, format: &str) -> Result<Vec<Arg<'t>>, DecodeError> {
94        let mut args = vec![]; // will contain the deserialized arguments on return
95        let mut params = defmt_parser::parse(format, defmt_parser::ParserMode::ForwardsCompatible)
96            .map_err(|_| DecodeError::Malformed)?
97            .iter()
98            .filter_map(|frag| match frag {
99                Fragment::Parameter(param) => Some(param.clone()),
100                Fragment::Literal(_) => None,
101            })
102            .collect::<Vec<_>>();
103
104        self.prepare_params(&mut params);
105
106        for param in &params {
107            match &param.ty {
108                Type::I8 => args.push(Arg::Ixx(self.bytes.read_i8()? as i128)),
109                Type::I16 => args.push(Arg::Ixx(self.bytes.read_i16::<LE>()? as i128)),
110                Type::I32 => args.push(Arg::Ixx(self.bytes.read_i32::<LE>()? as i128)),
111                Type::I64 => args.push(Arg::Ixx(self.bytes.read_i64::<LE>()? as i128)),
112                Type::I128 => args.push(Arg::Ixx(self.bytes.read_i128::<LE>()?)),
113                Type::Isize => args.push(Arg::Ixx(self.bytes.read_i32::<LE>()? as i128)),
114                Type::U8 => args.push(Arg::Uxx(self.bytes.read_u8()? as u128)),
115                Type::U16 => args.push(Arg::Uxx(self.bytes.read_u16::<LE>()? as u128)),
116                Type::U32 => args.push(Arg::Uxx(self.bytes.read_u32::<LE>()? as u128)),
117                Type::U64 => args.push(Arg::Uxx(self.bytes.read_u64::<LE>()? as u128)),
118                Type::U128 => args.push(Arg::Uxx(self.bytes.read_u128::<LE>()?)),
119                Type::Usize => args.push(Arg::Uxx(self.bytes.read_u32::<LE>()? as u128)),
120                Type::F32 => args.push(Arg::F32(f32::from_bits(self.bytes.read_u32::<LE>()?))),
121                Type::F64 => args.push(Arg::F64(f64::from_bits(self.bytes.read_u64::<LE>()?))),
122                Type::Bool => args.push(Arg::Bool(match self.bytes.read_u8()? {
123                    0 => false,
124                    1 => true,
125                    _ => return Err(DecodeError::Malformed),
126                })),
127                Type::FormatSlice => {
128                    let num_elements = self.bytes.read_u32::<LE>()? as usize;
129                    let elements = self.decode_format_slice(num_elements)?;
130                    args.push(Arg::FormatSlice { elements });
131                }
132                Type::Format => {
133                    let format = self.get_format()?;
134
135                    if format.contains('|') {
136                        // enum
137                        let variant = self.get_variant(format)?;
138                        let inner_args = self.decode_format(variant)?;
139                        args.push(Arg::Format {
140                            format: variant,
141                            args: inner_args,
142                        });
143                    } else {
144                        let inner_args = self.decode_format(format)?;
145                        args.push(Arg::Format {
146                            format,
147                            args: inner_args,
148                        });
149                    }
150                }
151                Type::BitField(range) => {
152                    let lowest_byte = range.start / 8;
153                    let highest_byte = (range.end - 1) / 8; // -1, because `range` is range-exclusive
154                    let size_after_truncation = highest_byte - lowest_byte + 1; // in octets
155
156                    let mut data = match size_after_truncation {
157                        1 => self.bytes.read_u8()? as u128,
158                        2 => self.bytes.read_u16::<LE>()? as u128,
159                        3..=4 => self.bytes.read_u32::<LE>()? as u128,
160                        5..=8 => self.bytes.read_u64::<LE>()? as u128,
161                        9..=16 => self.bytes.read_u128::<LE>()?,
162                        _ => unreachable!(),
163                    };
164
165                    data <<= lowest_byte * 8;
166
167                    args.push(Arg::Uxx(data));
168                }
169                Type::Str => {
170                    let str_len = self.bytes.read_u32::<LE>()? as usize;
171                    let mut arg_str_bytes = vec![];
172
173                    // note: went for the suboptimal but simple solution; optimize if necessary
174                    for _ in 0..str_len {
175                        arg_str_bytes.push(self.bytes.read_u8()?);
176                    }
177
178                    // convert to utf8 (no copy)
179                    let arg_str =
180                        String::from_utf8(arg_str_bytes).map_err(|_| DecodeError::Malformed)?;
181
182                    args.push(Arg::Str(arg_str));
183                }
184                Type::IStr => {
185                    let str_index = self.bytes.read_u16::<LE>()? as usize;
186
187                    let string = self
188                        .table
189                        .get_without_level(str_index)
190                        .map_err(|_| DecodeError::Malformed)?;
191
192                    args.push(Arg::IStr(string));
193                }
194                Type::U8Slice => {
195                    // only supports byte slices
196                    let num_elements = self.bytes.read_u32::<LE>()? as usize;
197                    let mut arg_slice = vec![];
198
199                    // note: went for the suboptimal but simple solution; optimize if necessary
200                    for _ in 0..num_elements {
201                        arg_slice.push(self.bytes.read_u8()?);
202                    }
203                    args.push(Arg::Slice(arg_slice.to_vec()));
204                }
205                Type::U8Array(len) => {
206                    let mut arg_slice = vec![];
207                    // note: went for the suboptimal but simple solution; optimize if necessary
208                    for _ in 0..*len {
209                        arg_slice.push(self.bytes.read_u8()?);
210                    }
211                    args.push(Arg::Slice(arg_slice.to_vec()));
212                }
213                Type::FormatArray(len) => {
214                    let elements = self.decode_format_slice(*len)?;
215                    args.push(Arg::FormatSlice { elements });
216                }
217                Type::Char => {
218                    let data = self.bytes.read_u32::<LE>()?;
219                    let c = std::char::from_u32(data).ok_or(DecodeError::Malformed)?;
220                    args.push(Arg::Char(c));
221                }
222                Type::Debug | Type::Display => {
223                    // UTF-8 stream without a prefix length, terminated with `0xFF`.
224
225                    let end = self
226                        .bytes
227                        .iter()
228                        .position(|b| *b == 0xff)
229                        .ok_or(DecodeError::UnexpectedEof)?;
230                    let data = core::str::from_utf8(&self.bytes[..end])
231                        .map_err(|_| DecodeError::Malformed)?;
232                    self.bytes = &self.bytes[end + 1..];
233
234                    args.push(Arg::Preformatted(data.into()));
235                }
236                Type::FormatSequence => {
237                    let mut seq_args = Vec::new();
238                    loop {
239                        let index = self.bytes.read_u16::<LE>()? as usize;
240                        if index == 0 {
241                            break;
242                        }
243
244                        let format = self
245                            .table
246                            .get_without_level(index)
247                            .map_err(|_| DecodeError::Malformed)?;
248
249                        let inner_args = self.decode_format(format)?;
250                        seq_args.push(Arg::Format {
251                            format,
252                            args: inner_args,
253                        });
254                    }
255                    args.push(Arg::FormatSequence { args: seq_args })
256                }
257            }
258        }
259
260        Ok(args)
261    }
262}
263
264/// Note that this will not change the Bitfield params in place, i.e. if `params` was sorted before
265/// a call to this function, it won't be afterwards.
266fn merge_bitfields(params: &mut Vec<Parameter>) {
267    if params.is_empty() {
268        return;
269    }
270
271    let mut merged_bitfields = Vec::new();
272
273    let max_index: usize = *params.iter().map(|param| &param.index).max().unwrap();
274
275    for index in 0..=max_index {
276        let mut bitfields_with_index = params
277            .iter()
278            .filter(
279                |param| matches!((param.index, &param.ty), (i, Type::BitField(_)) if i == index),
280            )
281            .peekable();
282
283        if bitfields_with_index.peek().is_some() {
284            let (smallest, largest) = get_max_bitfield_range(bitfields_with_index).unwrap();
285
286            // create new merged bitfield for this index
287            merged_bitfields.push(Parameter {
288                index,
289                ty: Type::BitField(Range {
290                    start: smallest,
291                    end: largest,
292                }),
293                hint: None, // don't care
294            });
295
296            // remove old bitfields with this index
297            // TODO refactor when `drain_filter()` is stable
298            let mut i = 0;
299            while i != params.len() {
300                match &params[i].ty {
301                    Type::BitField(_) => {
302                        if params[i].index == index {
303                            params.remove(i);
304                        } else {
305                            i += 1; // we haven't removed a bitfield -> move i forward
306                        }
307                    }
308                    _ => {
309                        i += 1; // we haven't removed a bitfield -> move i forward
310                    }
311                }
312            }
313        }
314    }
315
316    // add merged bitfields to unsorted params
317    params.append(&mut merged_bitfields);
318}
319
320#[cfg(test)]
321mod tests {
322    use super::*;
323
324    #[test]
325    fn merge_bitfields_simple() {
326        let mut params = vec![
327            Parameter {
328                index: 0,
329                ty: Type::BitField(0..3),
330                hint: None,
331            },
332            Parameter {
333                index: 0,
334                ty: Type::BitField(4..7),
335                hint: None,
336            },
337        ];
338
339        merge_bitfields(&mut params);
340        assert_eq!(
341            params,
342            vec![Parameter {
343                index: 0,
344                ty: Type::BitField(0..7),
345                hint: None,
346            }]
347        );
348    }
349
350    #[test]
351    fn merge_bitfields_overlap() {
352        let mut params = vec![
353            Parameter {
354                index: 0,
355                ty: Type::BitField(1..3),
356                hint: None,
357            },
358            Parameter {
359                index: 0,
360                ty: Type::BitField(2..5),
361                hint: None,
362            },
363        ];
364
365        merge_bitfields(&mut params);
366        assert_eq!(
367            params,
368            vec![Parameter {
369                index: 0,
370                ty: Type::BitField(1..5),
371                hint: None,
372            }]
373        );
374    }
375
376    #[test]
377    fn merge_bitfields_multiple_indices() {
378        let mut params = vec![
379            Parameter {
380                index: 0,
381                ty: Type::BitField(0..3),
382                hint: None,
383            },
384            Parameter {
385                index: 1,
386                ty: Type::BitField(1..3),
387                hint: None,
388            },
389            Parameter {
390                index: 1,
391                ty: Type::BitField(4..5),
392                hint: None,
393            },
394        ];
395
396        merge_bitfields(&mut params);
397        assert_eq!(
398            params,
399            vec![
400                Parameter {
401                    index: 0,
402                    ty: Type::BitField(0..3),
403                    hint: None,
404                },
405                Parameter {
406                    index: 1,
407                    ty: Type::BitField(1..5),
408                    hint: None,
409                }
410            ]
411        );
412    }
413
414    #[test]
415    fn merge_bitfields_overlap_non_consecutive_indices() {
416        let mut params = vec![
417            Parameter {
418                index: 0,
419                ty: Type::BitField(0..3),
420                hint: None,
421            },
422            Parameter {
423                index: 1,
424                ty: Type::U8,
425                hint: None,
426            },
427            Parameter {
428                index: 2,
429                ty: Type::BitField(1..4),
430                hint: None,
431            },
432            Parameter {
433                index: 2,
434                ty: Type::BitField(4..5),
435                hint: None,
436            },
437        ];
438
439        merge_bitfields(&mut params);
440        // note: current implementation appends merged bitfields to the end. this is not a must
441        assert_eq!(
442            params,
443            vec![
444                Parameter {
445                    index: 1,
446                    ty: Type::U8,
447                    hint: None,
448                },
449                Parameter {
450                    index: 0,
451                    ty: Type::BitField(0..3),
452                    hint: None,
453                },
454                Parameter {
455                    index: 2,
456                    ty: Type::BitField(1..5),
457                    hint: None,
458                }
459            ]
460        );
461    }
462}