egdata_manifests_parser/types/
header.rs1use hex;
2use log::debug;
3use serde::{Deserialize, Serialize};
4use std::io::{Read, Seek};
5
6use crate::parser::reader::ReadExt;
7use crate::{error::Error, types::flags::*};
8
9const MANIFEST_MAGIC: u32 = 0x44BEC00C;
10
11#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12pub struct ManifestHeader {
13 pub header_size: i32,
14 pub data_size_uncompressed: i32,
15 pub data_size_compressed: i32,
16 pub sha1_hash: String,
17 pub stored_as: u8,
18 pub version: i32,
19 pub guid: String,
20 pub rolling_hash: i64,
21 pub hash_type: u32,
22}
23
24impl ManifestHeader {
25 pub fn read<R: Read + Seek>(mut rdr: R) -> Result<Self, Error> {
26 let magic = rdr.u32()?;
28 if magic != MANIFEST_MAGIC {
29 return Err(Error::Invalid("invalid manifest magic number".to_string()));
30 }
31
32 let header_size = rdr.i32()?;
34 debug!(" Header size from file: {}", header_size);
35
36 let data_size_uncompressed = rdr.i32()?;
38 let data_size_compressed = rdr.i32()?;
39
40 let mut hash = [0u8; 20];
42 rdr.read_exact(&mut hash)?;
43 debug!("Raw SHA-1 bytes from file: {:02x?}", hash);
44
45 let stored_as = rdr.u8()?;
47
48 let version = if header_size > 37 {
50 rdr.i32()?
51 } else {
52 0 };
54
55 let current_pos = rdr.stream_position()?;
57 if current_pos < header_size as u64 {
58 rdr.seek(std::io::SeekFrom::Start(header_size as u64))?;
59 }
60
61 Ok(Self {
62 header_size,
63 data_size_uncompressed,
64 data_size_compressed,
65 sha1_hash: hex::encode(hash),
66 stored_as,
67 version,
68 guid: String::new(), rolling_hash: 0, hash_type: 0, })
72 }
73
74 pub fn is_compressed(&self) -> bool {
76 self.stored_as & STORED_COMPRESSED != 0
77 }
78 pub fn is_encrypted(&self) -> bool {
79 self.stored_as & STORED_ENCRYPTED != 0
80 }
81}