gcd_rs/record/
firmware.rs

1//! Composed of two records, the record descriptor type and descryptor values
2//! are separated in two record, for some reason.
3//!
4//! A descriptor id have the format 0xABBB, A is the kind, B is the id. The
5//! kind could be:
6//! 0..4 => , with "1 >> kind" is the data size.
7//!
8//! 4 => A variable data size, the next 2 bytes after the descritod type is the
9//! size. But this need more investigation.
10//!
11//! 5 => End of the list, possibly only ID 0x003 is valid.
12//!
13//!
14//! The order or descriptors seems to be irrelevant.
15
16//TODO doc this
17
18use byteorder::ByteOrder;
19use serde::{Deserialize, Serialize};
20use std::fmt::{Display, Formatter};
21use std::io::Result;
22
23use crate::RecordHeader;
24
25#[derive(Debug, PartialEq, Hash, Eq, Clone, Serialize, Deserialize)]
26pub enum FirmwareRecord {
27    /// Empty firmware chunk. Some files include this if firmware_len = 0.
28    EmptyChunk { id: u16 },
29    /// Chunk of firmware data.
30    Chunk { id: u16, data: Vec<u8> },
31}
32
33impl Display for FirmwareRecord {
34    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35        match self {
36            FirmwareRecord::EmptyChunk { id } => {
37                write!(f, "FirmwareRecord::EmptyChunk {{ id: {} }}", id)
38            }
39            FirmwareRecord::Chunk { id, data } => write!(
40                f,
41                "FirmwareRecord::Chunk {{ id: {}, len: {} }}",
42                id,
43                data.len()
44            ),
45        }
46    }
47}
48
49impl FirmwareRecord {
50    pub fn new(data: Vec<u8>, id: u16) -> Self {
51        if data.len() == 0 {
52            FirmwareRecord::EmptyChunk { id }
53        } else {
54            FirmwareRecord::Chunk { id, data }
55        }
56    }
57    pub fn len(&self) -> u16 {
58        match self {
59            FirmwareRecord::EmptyChunk { .. } => 0,
60            FirmwareRecord::Chunk { data, .. } => data.len() as u16,
61        }
62    }
63    pub const fn id(&self) -> u16 {
64        match self {
65            FirmwareRecord::EmptyChunk { id }
66            | FirmwareRecord::Chunk { id, .. } => *id,
67        }
68    }
69    pub fn data(&self) -> &[u8] {
70        match self {
71            FirmwareRecord::EmptyChunk { .. } => &[],
72            FirmwareRecord::Chunk { data, .. } => data,
73        }
74    }
75    pub fn record_to_raw<B: ByteOrder>(&self, data: &mut [u8]) -> Result<()> {
76        //write header
77        let next = RecordHeader::Unknown {
78            id: self.id(),
79            len: self.len(),
80        }
81        .to_raw::<B>(data)?;
82
83        //write record body
84        next[..self.len() as usize].copy_from_slice(self.data());
85
86        Ok(())
87    }
88}