1#![forbid(unsafe_code)]
2
3use crate::error::DecompressError;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum BlockType {
7 Raw,
8 Rle,
9 Compressed,
10}
11
12#[derive(Debug, Clone, Copy)]
13pub struct BlockHeader {
14 pub last_block: bool,
15 pub block_type: BlockType,
16 pub block_size: u32,
17}
18
19pub fn parse_block_header(data: &[u8]) -> Result<BlockHeader, DecompressError> {
20 if data.len() < 3 {
21 return Err(DecompressError::InputExhausted);
22 }
23
24 let raw = u32::from_le_bytes([data[0], data[1], data[2], 0]);
25
26 let last_block = (raw & 1) != 0;
27 let block_type_bits = (raw >> 1) & 0x03;
28 let block_size = raw >> 3;
29
30 let block_type = match block_type_bits {
31 0 => BlockType::Raw,
32 1 => BlockType::Rle,
33 2 => BlockType::Compressed,
34 _ => return Err(DecompressError::BadBlockType),
35 };
36
37 Ok(BlockHeader {
38 last_block,
39 block_type,
40 block_size,
41 })
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn parse_raw_block() {
50 let data = [0x00, 0x00, 0x01];
51 let hdr = parse_block_header(&data).unwrap();
52 assert!(!hdr.last_block);
53 assert_eq!(hdr.block_type, BlockType::Raw);
54 assert_eq!(hdr.block_size, 0x0001_0000 >> 3);
55 }
56
57 #[test]
58 fn parse_last_compressed() {
59 let data = [0x05, 0x00, 0x00];
60 let hdr = parse_block_header(&data).unwrap();
61 assert!(hdr.last_block);
62 assert_eq!(hdr.block_type, BlockType::Compressed);
63 assert_eq!(hdr.block_size, 0);
64 }
65}