blkar_lib/sbx_block/
header.rs

1use super::crc::*;
2use super::BlockType;
3use super::Error;
4use crate::sbx_specs;
5use crate::sbx_specs::{Version, SBX_FILE_UID_LEN, SBX_FIRST_DATA_SEQ_NUM, SBX_SIGNATURE};
6use std;
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct Header {
10    pub version: Version,
11    pub crc: u16,
12    pub uid: [u8; SBX_FILE_UID_LEN],
13    pub seq_num: u32,
14}
15
16impl Header {
17    pub fn new(version: Version, uid: [u8; SBX_FILE_UID_LEN], seq_num: u32) -> Header {
18        Header {
19            version,
20            crc: 0,
21            uid,
22            seq_num,
23        }
24    }
25
26    pub fn to_bytes(&self, buffer: &mut [u8]) {
27        if buffer.len() != 16 {
28            panic!("Incorrect buffer size");
29        }
30
31        {
32            // signature
33            buffer[0..3].copy_from_slice(SBX_SIGNATURE);
34        }
35        {
36            // version byte
37            buffer[3] = sbx_specs::ver_to_usize(self.version) as u8;
38        }
39        {
40            // crc ccitt
41            let crc: [u8; 2] = unsafe { std::mem::transmute::<u16, [u8; 2]>(self.crc.to_be()) };
42            buffer[4..6].copy_from_slice(&crc);
43        }
44        {
45            // file uid
46            buffer[6..12].copy_from_slice(&self.uid);
47        }
48        {
49            // seq num
50            let seq_num: [u8; 4] =
51                unsafe { std::mem::transmute::<u32, [u8; 4]>(self.seq_num.to_be()) };
52            buffer[12..16].copy_from_slice(&seq_num);
53        }
54    }
55
56    pub fn from_bytes(&mut self, buffer: &[u8]) -> Result<(), Error> {
57        if buffer.len() != 16 {
58            return Err(Error::IncorrectBufferSize);
59        }
60
61        match parsers::header_p(buffer) {
62            Ok((_, header)) => {
63                *self = header;
64                Ok(())
65            }
66            _ => Err(Error::ParseError),
67        }
68    }
69
70    pub fn calc_crc(&self) -> u16 {
71        let crc = sbx_crc_ccitt(self.version, &self.uid);
72        let seq_num: [u8; 4] = unsafe { std::mem::transmute::<u32, [u8; 4]>(self.seq_num.to_be()) };
73        crc_ccitt_generic(crc, &seq_num)
74    }
75
76    pub fn header_type(&self) -> BlockType {
77        if self.seq_num < SBX_FIRST_DATA_SEQ_NUM as u32 {
78            BlockType::Meta
79        } else {
80            BlockType::Data
81        }
82    }
83}
84
85mod parsers {
86    use super::Header;
87    use super::Version;
88    use nom::number::complete::{be_u16, be_u32};
89
90    named!(sig_p, tag!(b"SBx"));
91
92    named!(
93        ver_p<Version>,
94        alt!(
95            complete!(do_parse!(_v: tag!(&[1]) >> (Version::V1)))
96                | complete!(do_parse!(_v: tag!(&[2]) >> (Version::V2)))
97                | complete!(do_parse!(_v: tag!(&[3]) >> (Version::V3)))
98                | complete!(do_parse!(_v: tag!(&[17]) >> (Version::V17)))
99                | complete!(do_parse!(_v: tag!(&[18]) >> (Version::V18)))
100                | complete!(do_parse!(_v: tag!(&[19]) >> (Version::V19)))
101        )
102    );
103
104    named!(uid_p, take!(6));
105
106    named!(pub header_p <Header>,
107           do_parse!(
108               _sig : sig_p >>
109                   version : ver_p >>
110                   crc     : be_u16 >>
111                   uid_raw : uid_p >>
112                   seq_num : be_u32 >>
113                   ({
114                       let mut uid : [u8; 6] = [0; 6];
115                       uid.copy_from_slice(uid_raw);
116                       Header {
117                           version,
118                           crc,
119                           uid,
120                           seq_num
121                       }
122                   })
123           )
124    );
125}