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