egs_api/api/types/
chunk.rs

1use flate2::read::ZlibDecoder;
2use log::{debug, error};
3use std::io::Read;
4
5/// Struct holding data for downloaded chunks
6#[derive(Default, Debug, Clone, PartialEq)]
7pub struct Chunk {
8    header_version: u32,
9    header_size: u32,
10    compressed_size: u32,
11    /// Guid of the chunk
12    pub guid: String,
13    /// Chunk Hash
14    pub hash: u64,
15    compressed: bool,
16    /// Chunk sha hash
17    pub sha_hash: Option<Vec<u8>>,
18    /// 1 = rolling hash, 2 = sha hash, 3 = both
19    pub hash_type: Option<u8>,
20    /// Total chunk size
21    pub uncompressed_size: Option<u32>,
22    /// Chunk data
23    pub data: Vec<u8>,
24}
25
26impl Chunk {
27    /// Parse chunk from binary vector
28    pub fn from_vec(buffer: Vec<u8>) -> Option<Chunk> {
29        let mut position: usize = 0;
30        let magic = crate::api::utils::read_le(&buffer, &mut position);
31        if magic != 2986228386 {
32            error!("No header magic");
33            return None;
34        }
35        let mut res = Chunk {
36            header_version: crate::api::utils::read_le(&buffer, &mut position),
37            header_size: crate::api::utils::read_le(&buffer, &mut position),
38            compressed_size: crate::api::utils::read_le(&buffer, &mut position),
39            guid: format!(
40                "{:08x}{:08x}{:08x}{:08x}",
41                crate::api::utils::read_le(&buffer, &mut position),
42                crate::api::utils::read_le(&buffer, &mut position),
43                crate::api::utils::read_le(&buffer, &mut position),
44                crate::api::utils::read_le(&buffer, &mut position)
45            ),
46            hash: crate::api::utils::read_le_64(&buffer, &mut position),
47            compressed: !matches!(buffer[position], 0),
48            sha_hash: None,
49            hash_type: None,
50            uncompressed_size: None,
51            data: vec![],
52        };
53        position += 1;
54
55        if res.header_version >= 2 {
56            position += 20;
57            res.sha_hash = Some(buffer[position - 20..position].into());
58            res.hash_type = Some(buffer[position]);
59            position += 1;
60        }
61        if res.header_version >= 3 {
62            res.uncompressed_size = Some(crate::api::utils::read_le(&buffer, &mut position));
63        }
64        debug!("Got chunk: {:?}", res);
65        res.data = if res.compressed {
66            let mut z = ZlibDecoder::new(&buffer[position..]);
67            let mut data: Vec<u8> = Vec::new();
68            z.read_to_end(&mut data).unwrap();
69            data
70        } else {
71            buffer[position..].to_vec()
72        };
73        Some(res)
74    }
75}