lzma_rs/xz/
header.rs
1use crate::decode::util;
4use crate::error;
5use crate::xz::crc::CRC32;
6use crate::xz::StreamFlags;
7use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
8
9pub(crate) const XZ_MAGIC: &[u8] = &[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00];
11
12#[derive(Clone, Copy, Debug)]
14pub(crate) struct StreamHeader {
15 pub(crate) stream_flags: StreamFlags,
16}
17
18impl StreamHeader {
19 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}