Skip to main content

xz_rs/block/
header.rs

1use std::io::{Cursor, Read};
2
3use crate::block::BlockDecodeError;
4use crate::checksum::{Checksum, Crc32};
5use crate::decode::{Decode, DecodeError, RecordedReader};
6use crate::encode::Encode;
7
8use super::{BlockFlags, Filter, VarLengthInt};
9
10#[derive(Debug, Clone)]
11pub struct BlockHeader {
12    pub flags: BlockFlags,
13    pub compressed_size: Option<u64>,
14    pub uncompressed_size: Option<u64>,
15    pub filters: Vec<Filter>,
16}
17
18impl Encode for BlockHeader {
19    fn encoding(&self) -> Vec<u8> {
20        let mut bytes = self.flags.encoding();
21
22        for filter in &self.filters {
23            bytes.extend_from_slice(&filter.encoding());
24        }
25
26        if let Some(compressed_size) = self.compressed_size {
27            bytes.extend_from_slice(&VarLengthInt(compressed_size).encoding());
28        }
29
30        if let Some(uncompressed_size) = self.uncompressed_size {
31            bytes.extend_from_slice(&VarLengthInt(uncompressed_size).encoding());
32        }
33
34        let header_size = bytes.len();
35        let padding_needed = (4 - ((header_size + 4) % 4)) % 4;
36        bytes.extend_from_slice(&vec![0u8; padding_needed]);
37
38        let mut crc32 = Crc32::new();
39        crc32.process_words(&bytes);
40        bytes.extend_from_slice(&crc32.result().to_le_bytes());
41
42        bytes
43    }
44}
45
46impl Decode for BlockHeader {
47    fn decode<R: Read>(mut src: &mut R) -> Result<Self, DecodeError> {
48        let mut src = RecordedReader::new(&mut src);
49
50        let err = Err(DecodeError::BlockError(BlockDecodeError::InvalidHeader));
51
52        let read_bytes =
53            |n: usize, src: &mut RecordedReader<&mut R>| -> Result<Vec<u8>, DecodeError> {
54                let mut buf = vec![0u8; n];
55                src.read_exact(&mut buf)?;
56                Ok(buf)
57            };
58
59        let header_size = read_bytes(1, &mut src)?[0];
60        if header_size == 0 {
61            return err;
62        }
63        let header_size = ((header_size as usize) + 1) * 4;
64
65        let flag_byte = read_bytes(1, &mut src)?;
66        let flags = BlockFlags::decode(&mut Cursor::new(&flag_byte))?;
67
68        let compressed_size = if flags.has_compressed_size {
69            let size = VarLengthInt::decode(&mut src)?.0;
70            if size == 0 {
71                return err;
72            }
73            Some(size)
74        } else {
75            None
76        };
77
78        let uncompressed_size = if flags.has_compressed_size {
79            let size = VarLengthInt::decode(&mut src)?.0;
80            if size == 0 {
81                return err;
82            }
83            Some(size)
84        } else {
85            None
86        };
87
88        let mut filters = Vec::with_capacity(flags.filter_count as usize);
89        for _ in 0..flags.filter_count {
90            let filter = Filter::decode(&mut src)?;
91            filters.push(filter);
92        }
93
94        let padding_size = header_size - src.recording.len() - 4;
95        if read_bytes(padding_size, &mut src)?.iter().any(|&b| b != 0) {
96            return err;
97        }
98
99        let actual_crc32 = src.crc32();
100        let mut crc32_bytes = [0u8; 4];
101        src.read_exact(&mut crc32_bytes)?;
102        let expected_crc32 = u32::from_le_bytes(crc32_bytes);
103        if actual_crc32 != expected_crc32 {
104            return err;
105        }
106
107        Ok(BlockHeader {
108            flags,
109            compressed_size,
110            uncompressed_size,
111            filters,
112        })
113    }
114}