mirror of
https://github.com/xavo95/repak.git
synced 2025-01-18 19:04:07 +00:00
WIP pak init refactor
This commit is contained in:
parent
0b5bded4b4
commit
461bc66c30
4 changed files with 54 additions and 60 deletions
|
@ -6,7 +6,7 @@ pub use {list::list, unpack::unpack, version::version};
|
||||||
fn load_pak(
|
fn load_pak(
|
||||||
path: String,
|
path: String,
|
||||||
key: Option<String>,
|
key: Option<String>,
|
||||||
) -> Result<unpak::Pak<std::io::BufReader<std::fs::File>>, unpak::Error> {
|
) -> Result<unpak::PakReader<std::io::BufReader<std::fs::File>>, unpak::Error> {
|
||||||
use aes::cipher::KeyInit;
|
use aes::cipher::KeyInit;
|
||||||
use base64::{engine::general_purpose, Engine as _};
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
let key = key
|
let key = key
|
||||||
|
@ -21,17 +21,5 @@ fn load_pak(
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
for ver in unpak::Version::iter() {
|
unpak::PakReader::new_any( std::io::BufReader::new(std::fs::OpenOptions::new().read(true).open(&path)?), key)
|
||||||
match unpak::Pak::new(
|
|
||||||
std::io::BufReader::new(std::fs::OpenOptions::new().read(true).open(&path)?),
|
|
||||||
ver,
|
|
||||||
key.clone(),
|
|
||||||
) {
|
|
||||||
Ok(pak) => {
|
|
||||||
return Ok(pak);
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(unpak::Error::Other("version unsupported"))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ pub enum Version {
|
||||||
|
|
||||||
// strum shouldn't need to be installed by users
|
// strum shouldn't need to be installed by users
|
||||||
impl Version {
|
impl Version {
|
||||||
pub fn iter() -> VersionIter {
|
pub fn iter() -> std::iter::Rev<VersionIter> {
|
||||||
<Version as strum::IntoEnumIterator>::iter()
|
<Version as strum::IntoEnumIterator>::iter().rev()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(self) -> i64 {
|
pub fn size(self) -> i64 {
|
||||||
|
|
47
src/pak.rs
47
src/pak.rs
|
@ -3,12 +3,16 @@ use hashbrown::HashMap;
|
||||||
use std::io::{self, Seek};
|
use std::io::{self, Seek};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Pak<R: io::Read + io::Seek> {
|
pub struct PakReader<R: io::Read + io::Seek> {
|
||||||
|
pak: Pak,
|
||||||
|
reader: R,
|
||||||
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Pak {
|
||||||
version: Version,
|
version: Version,
|
||||||
mount_point: String,
|
mount_point: String,
|
||||||
key: Option<aes::Aes256Dec>,
|
key: Option<aes::Aes256Dec>,
|
||||||
index: Index,
|
index: Index,
|
||||||
reader: R,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -52,12 +56,34 @@ fn decrypt(key: &Option<aes::Aes256Dec>, bytes: &mut [u8]) -> Result<(), super::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: io::Read + io::Seek> Pak<R> {
|
impl<R: io::Read + io::Seek> PakReader<R> {
|
||||||
|
pub fn new_any(
|
||||||
|
mut reader: R,
|
||||||
|
key: Option<aes::Aes256Dec>,
|
||||||
|
) -> Result<Self, super::Error> {
|
||||||
|
for ver in Version::iter() {
|
||||||
|
match PakReader::new(
|
||||||
|
&mut reader,
|
||||||
|
ver,
|
||||||
|
key.clone(),
|
||||||
|
) {
|
||||||
|
Ok(pak) => {
|
||||||
|
return Ok(PakReader {
|
||||||
|
pak,
|
||||||
|
reader,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(super::Error::Other("version unsupported"))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mut reader: R,
|
mut reader: R,
|
||||||
version: super::Version,
|
version: super::Version,
|
||||||
key: Option<aes::Aes256Dec>,
|
key: Option<aes::Aes256Dec>,
|
||||||
) -> Result<Self, super::Error> {
|
) -> Result<Pak, super::Error> {
|
||||||
use super::ext::ReadExt;
|
use super::ext::ReadExt;
|
||||||
use byteorder::{ReadBytesExt, LE};
|
use byteorder::{ReadBytesExt, LE};
|
||||||
// read footer to get index, encryption & compression info
|
// read footer to get index, encryption & compression info
|
||||||
|
@ -174,21 +200,20 @@ impl<R: io::Read + io::Seek> Pak<R> {
|
||||||
Index::V1(IndexV1 { entries })
|
Index::V1(IndexV1 { entries })
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Pak {
|
||||||
version,
|
version,
|
||||||
mount_point,
|
mount_point,
|
||||||
key,
|
key,
|
||||||
index,
|
index,
|
||||||
reader,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn version(&self) -> super::Version {
|
pub fn version(&self) -> super::Version {
|
||||||
self.version
|
self.pak.version
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mount_point(&self) -> &str {
|
pub fn mount_point(&self) -> &str {
|
||||||
&self.mount_point
|
&self.pak.mount_point
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&mut self, path: &str) -> Result<Vec<u8>, super::Error> {
|
pub fn get(&mut self, path: &str) -> Result<Vec<u8>, super::Error> {
|
||||||
|
@ -198,14 +223,14 @@ impl<R: io::Read + io::Seek> Pak<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<W: io::Write>(&mut self, path: &str, writer: &mut W) -> Result<(), super::Error> {
|
pub fn read<W: io::Write>(&mut self, path: &str, writer: &mut W) -> Result<(), super::Error> {
|
||||||
match self.index.entries().get(path) {
|
match self.pak.index.entries().get(path) {
|
||||||
Some(entry) => entry.read(&mut self.reader, self.version, self.key.as_ref(), writer),
|
Some(entry) => entry.read(&mut self.reader, self.pak.version, self.pak.key.as_ref(), writer),
|
||||||
None => Err(super::Error::Other("no file found at given path")),
|
None => Err(super::Error::Other("no file found at given path")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn files(&self) -> std::vec::IntoIter<String> {
|
pub fn files(&self) -> std::vec::IntoIter<String> {
|
||||||
self.index
|
self.pak.index
|
||||||
.entries()
|
.entries()
|
||||||
.keys()
|
.keys()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
|
|
@ -1,38 +1,7 @@
|
||||||
fn load_pak(
|
use paste::paste;
|
||||||
bytes: &[u8],
|
|
||||||
key: Option<String>,
|
|
||||||
) -> Result<unpak::Pak<std::io::Cursor<&[u8]>>, unpak::Error> {
|
|
||||||
use aes::cipher::KeyInit;
|
|
||||||
use base64::{engine::general_purpose, Engine as _};
|
|
||||||
let key = key
|
|
||||||
.map(|k| {
|
|
||||||
general_purpose::STANDARD
|
|
||||||
.decode(k)
|
|
||||||
.as_ref()
|
|
||||||
.map_err(|_| unpak::Error::Base64)
|
|
||||||
.and_then(|bytes| {
|
|
||||||
aes::Aes256Dec::new_from_slice(bytes).map_err(|_| unpak::Error::Aes)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.transpose()?;
|
|
||||||
|
|
||||||
for ver in unpak::Version::iter() {
|
|
||||||
match unpak::Pak::new(std::io::Cursor::new(bytes), ver, key.clone()) {
|
|
||||||
Ok(pak) => {
|
|
||||||
return Ok(pak);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(unpak::Error::Other("version unsupported"))
|
|
||||||
}
|
|
||||||
|
|
||||||
static AES_KEY: &str = "lNJbw660IOC+kU7cnVQ1oeqrXyhk4J6UAZrCBbcnp94=";
|
static AES_KEY: &str = "lNJbw660IOC+kU7cnVQ1oeqrXyhk4J6UAZrCBbcnp94=";
|
||||||
|
|
||||||
use paste::paste;
|
|
||||||
|
|
||||||
macro_rules! matrix_test {
|
macro_rules! matrix_test {
|
||||||
( ($($version:literal $exp_version:expr),* $(,)?), $compress:tt, $encrypt:tt, $encryptindex:tt ) => {
|
( ($($version:literal $exp_version:expr),* $(,)?), $compress:tt, $encrypt:tt, $encryptindex:tt ) => {
|
||||||
$( compress!($version, $exp_version, $compress, $encrypt, $encryptindex); )*
|
$( compress!($version, $exp_version, $compress, $encrypt, $encryptindex); )*
|
||||||
|
@ -57,7 +26,19 @@ macro_rules! encryptindex {
|
||||||
paste! {
|
paste! {
|
||||||
#[test]
|
#[test]
|
||||||
fn [< test_version_ $version $compress $encrypt $encryptindex >]() {
|
fn [< test_version_ $version $compress $encrypt $encryptindex >]() {
|
||||||
let mut pak = load_pak(include_bytes!(concat!("packs/pack_", $version, $compress, $encrypt, $encryptindex, ".pak")), Some(AES_KEY.to_string())).unwrap();
|
use aes::cipher::KeyInit;
|
||||||
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
|
let key = general_purpose::STANDARD
|
||||||
|
.decode(AES_KEY)
|
||||||
|
.as_ref()
|
||||||
|
.map_err(|_| unpak::Error::Base64)
|
||||||
|
.and_then(|bytes| {
|
||||||
|
aes::Aes256Dec::new_from_slice(bytes).map_err(|_| unpak::Error::Aes)
|
||||||
|
}).unwrap();
|
||||||
|
let mut pak = unpak::PakReader::new_any(
|
||||||
|
std::io::Cursor::new(include_bytes!(concat!("packs/pack_", $version, $compress, $encrypt, $encryptindex, ".pak"))),
|
||||||
|
Some(key),
|
||||||
|
).unwrap();
|
||||||
assert_eq!(pak.mount_point(), "../mount/point/root/");
|
assert_eq!(pak.mount_point(), "../mount/point/root/");
|
||||||
assert_eq!(pak.version(), $exp_version);
|
assert_eq!(pak.version(), $exp_version);
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
Loading…
Reference in a new issue