From 461bc66c306a6acc2305e46a7c36ff91fd92cddf Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Thu, 19 Jan 2023 21:53:13 -0600 Subject: [PATCH] WIP pak init refactor --- examples/subcommands/mod.rs | 16 ++----------- src/lib.rs | 4 ++-- src/pak.rs | 47 ++++++++++++++++++++++++++++--------- tests/test.rs | 47 +++++++++++-------------------------- 4 files changed, 54 insertions(+), 60 deletions(-) diff --git a/examples/subcommands/mod.rs b/examples/subcommands/mod.rs index 7aeb140..5748bf9 100644 --- a/examples/subcommands/mod.rs +++ b/examples/subcommands/mod.rs @@ -6,7 +6,7 @@ pub use {list::list, unpack::unpack, version::version}; fn load_pak( path: String, key: Option, -) -> Result>, unpak::Error> { +) -> Result>, unpak::Error> { use aes::cipher::KeyInit; use base64::{engine::general_purpose, Engine as _}; let key = key @@ -21,17 +21,5 @@ fn load_pak( }) .transpose()?; - for ver in unpak::Version::iter() { - 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")) + unpak::PakReader::new_any( std::io::BufReader::new(std::fs::OpenOptions::new().read(true).open(&path)?), key) } diff --git a/src/lib.rs b/src/lib.rs index 91ad64e..f13c4f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,8 +31,8 @@ pub enum Version { // strum shouldn't need to be installed by users impl Version { - pub fn iter() -> VersionIter { - ::iter() + pub fn iter() -> std::iter::Rev { + ::iter().rev() } pub fn size(self) -> i64 { diff --git a/src/pak.rs b/src/pak.rs index 9b5c79e..cd92382 100644 --- a/src/pak.rs +++ b/src/pak.rs @@ -3,12 +3,16 @@ use hashbrown::HashMap; use std::io::{self, Seek}; #[derive(Debug)] -pub struct Pak { +pub struct PakReader { + pak: Pak, + reader: R, +} +#[derive(Debug)] +pub struct Pak { version: Version, mount_point: String, key: Option, index: Index, - reader: R, } #[derive(Debug)] @@ -52,12 +56,34 @@ fn decrypt(key: &Option, bytes: &mut [u8]) -> Result<(), super:: } } -impl Pak { +impl PakReader { + pub fn new_any( + mut reader: R, + key: Option, + ) -> Result { + 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( mut reader: R, version: super::Version, key: Option, - ) -> Result { + ) -> Result { use super::ext::ReadExt; use byteorder::{ReadBytesExt, LE}; // read footer to get index, encryption & compression info @@ -174,21 +200,20 @@ impl Pak { Index::V1(IndexV1 { entries }) }; - Ok(Self { + Ok(Pak { version, mount_point, key, index, - reader, }) } pub fn version(&self) -> super::Version { - self.version + self.pak.version } pub fn mount_point(&self) -> &str { - &self.mount_point + &self.pak.mount_point } pub fn get(&mut self, path: &str) -> Result, super::Error> { @@ -198,14 +223,14 @@ impl Pak { } pub fn read(&mut self, path: &str, writer: &mut W) -> Result<(), super::Error> { - match self.index.entries().get(path) { - Some(entry) => entry.read(&mut self.reader, self.version, self.key.as_ref(), writer), + match self.pak.index.entries().get(path) { + 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")), } } pub fn files(&self) -> std::vec::IntoIter { - self.index + self.pak.index .entries() .keys() .cloned() diff --git a/tests/test.rs b/tests/test.rs index 28fc018..f1d6aa5 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,38 +1,7 @@ -fn load_pak( - bytes: &[u8], - key: Option, -) -> Result>, 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")) -} +use paste::paste; static AES_KEY: &str = "lNJbw660IOC+kU7cnVQ1oeqrXyhk4J6UAZrCBbcnp94="; -use paste::paste; - macro_rules! matrix_test { ( ($($version:literal $exp_version:expr),* $(,)?), $compress:tt, $encrypt:tt, $encryptindex:tt ) => { $( compress!($version, $exp_version, $compress, $encrypt, $encryptindex); )* @@ -57,7 +26,19 @@ macro_rules! encryptindex { paste! { #[test] 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.version(), $exp_version); use std::collections::HashSet;