blkar_lib/sbx_block/
header.rs1use 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 buffer[0..3].copy_from_slice(SBX_SIGNATURE);
34 }
35 {
36 buffer[3] = sbx_specs::ver_to_usize(self.version) as u8;
38 }
39 {
40 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 buffer[6..12].copy_from_slice(&self.uid);
47 }
48 {
49 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}