lzma_rs/xz/
header.rs

1//! XZ header.
2
3use crate::decode::util;
4use crate::error;
5use crate::xz::crc::CRC32;
6use crate::xz::StreamFlags;
7use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
8
9/// File format magic header signature, see sect. 2.1.1.1.
10pub(crate) const XZ_MAGIC: &[u8] = &[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00];
11
12/// Stream Header, see sect. 2.1.1.
13#[derive(Clone, Copy, Debug)]
14pub(crate) struct StreamHeader {
15    pub(crate) stream_flags: StreamFlags,
16}
17
18impl StreamHeader {
19    /// Parse a Stream Header from a buffered reader.
20    pub(crate) fn parse<BR>(input: &mut BR) -> error::Result<Self>
21    where
22        BR: std::io::BufRead,
23    {
24        if !util::read_tag(input, XZ_MAGIC)? {
25            return Err(error::Error::XzError(format!(
26                "Invalid XZ magic, expected {:?}",
27                XZ_MAGIC
28            )));
29        }
30
31        let (flags, digested) = {
32            let mut digest = CRC32.digest();
33            let mut digest_rd = util::CrcDigestRead::new(input, &mut digest);
34            let flags = digest_rd.read_u16::<BigEndian>()?;
35            (flags, digest.finalize())
36        };
37
38        let crc32 = input.read_u32::<LittleEndian>()?;
39        if crc32 != digested {
40            return Err(error::Error::XzError(format!(
41                "Invalid header CRC32: expected 0x{:08x} but got 0x{:08x}",
42                crc32, digested
43            )));
44        }
45
46        let stream_flags = StreamFlags::parse(flags)?;
47        let header = Self { stream_flags };
48
49        lzma_info!("XZ check method: {:?}", header.stream_flags.check_method);
50        Ok(header)
51    }
52}