1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use super::parser::peek_hex;
use super::{MPQBlockTableEntry, MPQFileHeader, MPQHashTableEntry, MPQHashType, MPQUserData, MPQ};
use nom::IResult;
use std::collections::HashMap;
#[derive(Debug)]
pub struct MPQBuilder {
pub archive_header: Option<MPQFileHeader>,
pub user_data: Option<MPQUserData>,
pub hash_table_entries: Vec<MPQHashTableEntry>,
pub block_table_entries: Vec<MPQBlockTableEntry>,
pub encryption_table: HashMap<u32, u32>,
}
impl MPQBuilder {
pub fn new() -> Self {
Self {
archive_header: None,
user_data: None,
hash_table_entries: vec![],
block_table_entries: vec![],
encryption_table: MPQ::prepare_encryption_table(),
}
}
pub fn with_archive_header(mut self, archive_header: MPQFileHeader) -> Self {
self.archive_header = Some(archive_header);
self
}
pub fn with_user_data(mut self, user_data: Option<MPQUserData>) -> Self {
self.user_data = user_data;
self
}
pub fn with_hash_table(mut self, entries: Vec<MPQHashTableEntry>) -> Self {
self.hash_table_entries = entries;
self
}
pub fn with_block_table(mut self, entries: Vec<MPQBlockTableEntry>) -> Self {
self.block_table_entries = entries;
self
}
pub fn mpq_string_hash(&self, location: &str, hash_type: MPQHashType) -> u32 {
MPQ::mpq_string_hash(&self.encryption_table, location, hash_type)
}
#[tracing::instrument(level = "trace", skip(self, data))]
pub fn mpq_data_decrypt<'a>(&'a self, data: &'a [u8], key: u32) -> IResult<&'a [u8], Vec<u8>> {
tracing::trace!("Encrypted: {:?}", peek_hex(&data));
let (tail, res) = MPQ::mpq_data_decrypt(&self.encryption_table, data, key)?;
tracing::trace!("Decrypted: {:?}", peek_hex(&res));
Ok((tail, res))
}
pub fn build(self, _orig_input: &[u8]) -> Result<MPQ, String> {
let archive_header = self
.archive_header
.ok_or(String::from("Missing archive header"))?;
let user_data = self.user_data;
let hash_table_entries = self.hash_table_entries;
let block_table_entries = self.block_table_entries;
let encryption_table = self.encryption_table;
Ok(MPQ {
archive_header,
user_data,
hash_table_entries,
block_table_entries,
encryption_table,
})
}
}