Skip to main content

xz_rs/block/
index.rs

1use std::io::Read;
2
3use crate::checksum::{Checksum, Crc32};
4use crate::decode::{Decode, DecodeError, RecordedReader};
5use crate::encode::Encode;
6
7use super::{BlockDecodeError, VarLengthInt};
8
9#[derive(Debug, Clone)]
10pub struct IndexRecord {
11    pub uncompressed_size: u64,
12    pub unpadded_size: u64,
13}
14
15#[derive(Debug, Clone)]
16pub struct BlockIndex {
17    pub records: Vec<IndexRecord>,
18}
19
20impl Decode for BlockIndex {
21    fn decode<R: std::io::Read>(src: &mut R) -> Result<Self, DecodeError> {
22        let err = Err(DecodeError::BlockError(BlockDecodeError::InvalidIndex));
23        let mut src = RecordedReader::new(src);
24
25        let mut bytes = [0u8];
26        src.read_exact(&mut bytes)?;
27        if bytes[0] != 0 {
28            return err;
29        }
30
31        let num_records = VarLengthInt::decode(&mut src)?.0 as usize;
32
33        let mut records = Vec::with_capacity(num_records);
34        for _ in 0..num_records {
35            let uncompressed_size = VarLengthInt::decode(&mut src)?.0;
36
37            let unpadded_size = VarLengthInt::decode(&mut src)?.0;
38
39            records.push(IndexRecord {
40                uncompressed_size,
41                unpadded_size,
42            });
43        }
44
45        let padding_size = (4 - ((src.len() + 4) % 4)) % 4;
46        let mut padding = vec![0u8; padding_size];
47        src.read_exact(&mut padding)?;
48
49        if padding.iter().any(|&b| b != 0) {
50            return err;
51        }
52
53        let actual_crc32 = src.crc32();
54        let mut crc32_bytes = [0u8; 4];
55        src.read_exact(&mut crc32_bytes)?;
56        let expected_crc32 = u32::from_le_bytes(crc32_bytes);
57
58        if actual_crc32 != expected_crc32 {
59            return err;
60        }
61
62        Ok(BlockIndex { records })
63    }
64}
65
66impl Encode for BlockIndex {
67    fn encoding(&self) -> Vec<u8> {
68        let mut bytes = vec![0];
69
70        bytes.extend_from_slice(&VarLengthInt(self.records.len() as u64).encoding());
71
72        for record in &self.records {
73            bytes.extend_from_slice(&VarLengthInt(record.uncompressed_size).encoding());
74            bytes.extend_from_slice(&VarLengthInt(record.unpadded_size).encoding());
75        }
76
77        let padding_needed = (4 - ((bytes.len() + 4) % 4)) % 4;
78        bytes.extend_from_slice(&vec![0u8; padding_needed]);
79
80        let mut crc32 = Crc32::new();
81        crc32.process_words(&bytes);
82        bytes.extend_from_slice(&crc32.result().to_le_bytes());
83
84        bytes
85    }
86}