1#![allow(dead_code)]
2mod entry;
3mod error;
4mod ext;
5mod footer;
6mod pak;
7
8pub use {error::*, pak::*};
9
10pub const MAGIC: u32 = 0x5A6F12E1;
12
13#[derive(Default, Clone, Copy, PartialEq, Eq, Debug, strum::EnumString)]
15pub enum Compression {
16 #[default]
17 None,
18 Zlib,
19 Gzip,
20 Oodle,
21}
22
23#[repr(u32)]
25#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug, strum::Display, strum::EnumIter)]
26pub enum Version {
27 Initial,
29 NoTimestamps,
31 CompressionEncryption,
33 IndexEncryption,
35 RelativeChunkOffsets,
37 DeleteRecords,
39 EncryptionKeyUuid,
41 FNameBasedCompression,
43 FNameBasedCompression2,
45 FrozenIndex,
47 PathHashIndex,
49 Fnv64BugFix,
51}
52
53impl Version {
54 pub fn iter() -> VersionIter {
56 <Version as strum::IntoEnumIterator>::iter()
57 }
58
59 fn as_u32(self) -> u32 {
60 match self {
61 Version::Initial => 1,
62 Version::NoTimestamps => 2,
63 Version::CompressionEncryption => 3,
64 Version::IndexEncryption => 4,
65 Version::RelativeChunkOffsets => 5,
66 Version::DeleteRecords => 6,
67 Version::EncryptionKeyUuid => 7,
68 Version::FNameBasedCompression => 8,
69 Version::FNameBasedCompression2 => 8,
70 Version::FrozenIndex => 9,
71 Version::PathHashIndex => 10,
72 Version::Fnv64BugFix => 11,
73 }
74 }
75
76 fn footer_size(self) -> i64 {
77 let mut size = 4 + 4 + 8 + 8 + 20;
79 if self >= Version::EncryptionKeyUuid {
80 size += 16;
82 }
83 if self >= Version::IndexEncryption {
84 size += 1;
86 }
87 if self == Version::FrozenIndex {
88 size += 1;
90 }
91 if self >= Version::FNameBasedCompression {
92 size += 32 * 4;
94 }
95 if self >= Version::FNameBasedCompression2 {
96 size += 32
98 }
99 size
100 }
101}
102
103#[cfg(feature = "encryption")]
104fn decrypt(key: Option<&aes::Aes256Dec>, bytes: &mut [u8]) -> Result<(), Error> {
105 match key {
106 Some(key) => {
107 use aes::cipher::BlockDecrypt;
108 for chunk in bytes.chunks_mut(16) {
109 key.decrypt_block(aes::Block::from_mut_slice(chunk))
110 }
111 Ok(())
112 }
113 None => Err(Error::Encrypted),
114 }
115}