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
use crate::blocks::block::BlockType;
use alloc::vec::Vec;
#[derive(Debug)]
pub struct BlockHeader {
/// Signals if this block is the last one.
/// The frame will end after this block.
pub last_block: bool,
/// Influences the meaning of `block_size`.
pub block_type: BlockType,
/// - For `Raw` blocks, this is the size of the block's
/// content in bytes.
/// - For `RLE` blocks, there will be a single byte follwing
/// the header, repeated `block_size` times.
/// - For `Compressed` blocks, this is the length of
/// the compressed data.
///
/// **This value must not be greater than 21 bits in length.**
pub block_size: u32,
}
impl BlockHeader {
/// Write encoded binary representation of this header into the provided buffer.
pub fn serialize(self, output: &mut Vec<u8>) {
vprintln!("Serializing block with the header: {self:?}");
output.extend_from_slice(&self.to_le_bytes());
}
/// The fixed 3-byte little-endian block header. Block headers are always
/// exactly 3 bytes (RFC 8878 §3.1.1.2), so callers that reserved space
/// up front can backfill the header in place via this array without a
/// `Vec` round-trip (the compress-into-output emit path relies on this).
#[inline]
pub fn to_le_bytes(&self) -> [u8; 3] {
let encoded_block_type = match self.block_type {
BlockType::Raw => 0u32,
BlockType::RLE => 1,
BlockType::Compressed => 2,
BlockType::Reserved => panic!("You cannot use a reserved block type"),
};
let mut block_header = self.block_size << 3;
block_header |= encoded_block_type << 1;
block_header |= self.last_block as u32;
let le = block_header.to_le_bytes();
[le[0], le[1], le[2]]
}
}
#[cfg(test)]
mod tests {
use super::BlockHeader;
use crate::{blocks::block::BlockType, decoding::block_decoder};
use alloc::vec::Vec;
#[test]
fn block_header_serialize() {
let header = BlockHeader {
last_block: true,
block_type: super::BlockType::Compressed,
block_size: 69,
};
let mut serialized_header = Vec::new();
header.serialize(&mut serialized_header);
let mut decoder = block_decoder::new();
let parsed_header = decoder
.read_block_header(serialized_header.as_slice())
.unwrap()
.0;
assert!(parsed_header.last_block);
assert_eq!(parsed_header.block_type, BlockType::Compressed);
assert_eq!(parsed_header.content_size, 69);
}
}