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
95
96
97
98
99
100
use std::io;
use crate::archive::{Archivable, ArchivableWith, Archive};
use crate::constants::*;
use crate::PakVersion;
pub const FLAG_ENCRYPTED: u8 = 0x01;
pub const FLAG_DELETED: u8 = 0x02;
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct PakEntry {
pub offset: u64,
pub size: u64,
pub uncompressed_size: u64,
pub hash: [u8; 20],
pub compression_blocks: Vec<PakCompressedBlock>,
pub compression_block_size: u32,
pub compression_method_index: u32,
pub flags: u8,
}
impl PakEntry {
pub fn is_encrypted(&self) -> bool {
(self.flags & FLAG_ENCRYPTED) == FLAG_ENCRYPTED
}
pub fn is_deleted(&self) -> bool {
(self.flags & FLAG_DELETED) == FLAG_DELETED
}
}
impl ArchivableWith<PakVersion> for PakEntry {
fn ser_de_with<A: Archive>(&mut self, ar: &mut A, version: PakVersion) -> io::Result<()> {
self.offset.ser_de(ar)?;
self.size.ser_de(ar)?;
self.uncompressed_size.ser_de(ar)?;
match version {
PakVersion::FNameBasedCompressionMethod422 => {
let mut idx = 0u8;
idx.ser_de(ar)?;
self.compression_method_index = From::from(idx);
}
ver if ver < PakVersion::FNameBasedCompressionMethod422 => {
let mut legacy_compression_method = 0;
legacy_compression_method.ser_de(ar)?;
self.compression_method_index = match legacy_compression_method {
x if x == COMPRESS_NONE => 0,
x if (x & COMPRESS_ZLIB) > 0 => 1,
x if (x & COMPRESS_GZIP) > 0 => 2,
x if (x & COMPRESS_CUSTOM) > 0 => 3,
_ => {
return Err(io::Error::new(
io::ErrorKind::Other,
"unknown legacy compression type",
))
}
};
}
_ => {
self.compression_method_index.ser_de(ar)?;
}
}
if version <= PakVersion::Initial {
let mut ticks = 0u64;
ticks.ser_de(ar)?;
}
self.hash.ser_de(ar)?;
if version >= PakVersion::CompressionEncryption {
if self.compression_method_index != 0 {
self.compression_blocks.ser_de(ar)?;
}
self.flags.ser_de(ar)?;
self.compression_block_size.ser_de(ar)?;
}
Ok(())
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct PakCompressedBlock {
pub compressed_start: u64,
pub compressed_end: u64,
}
impl Archivable for PakCompressedBlock {
fn ser_de<A: Archive>(&mut self, ar: &mut A) -> io::Result<()> {
self.compressed_start.ser_de(ar)?;
self.compressed_end.ser_de(ar)?;
Ok(())
}
}