From 778b87570a940bc9e125ba7bc1ee7a5fe3d9e723 Mon Sep 17 00:00:00 2001 From: spuds <71292624+bananaturtlesandwich@users.noreply.github.com> Date: Sat, 7 Jan 2023 21:10:11 +0000 Subject: [PATCH] eager evaluation was the first problem --- examples/read.rs | 20 ++++----------- src/entry.rs | 6 ++--- src/error.rs | 6 ++--- src/ext.rs | 5 ++-- src/footer.rs | 67 ++++++++++++++++++++++++++++-------------------- src/index.rs | 6 ++--- src/lib.rs | 16 +++--------- src/pak.rs | 4 +-- 8 files changed, 60 insertions(+), 70 deletions(-) diff --git a/examples/read.rs b/examples/read.rs index adc695b..f542895 100644 --- a/examples/read.rs +++ b/examples/read.rs @@ -1,18 +1,8 @@ fn main() -> Result<(), un_pak::Error> { - let path = std::env::args().nth(1).unwrap_or_default(); - for version in un_pak::Version::iter() { - print!("{version} - "); - match un_pak::Pak::new( - version, - std::io::BufReader::new(std::fs::OpenOptions::new().read(true).open(&path)?), - ) { - Ok(pak) => { - print!("{:#?}", pak); - println!("parsed successfully!"); - } - Err(e) => println!("{e}"), - } - } - std::thread::sleep_ms(10000); + let pak = un_pak::Pak::new( + un_pak::Version::CompressionEncryption, + std::io::Cursor::new(include_bytes!("rando_p.pak")), + )?; + print!("{:#?}", pak); Ok(()) } diff --git a/src/entry.rs b/src/entry.rs index 1507110..9712d6f 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -17,7 +17,7 @@ pub struct Entry { impl Entry { pub fn new( reader: &mut R, - version: &super::Version, + version: super::Version, ) -> Result { let name = reader.read_string()?; let offset = reader.read_u64::()?; @@ -35,9 +35,9 @@ impl Entry { compressed, uncompressed, compression_method, - timestamp: (version == &Version::Initial).then_some(reader.read_u64::()?), + timestamp: (version == Version::Initial).then_some(reader.read_u64::()?), hash: reader.read_guid()?, - compression_blocks: (version >= &Version::CompressionEncryption + compression_blocks: (version >= Version::CompressionEncryption && compression_method != Compression::None) .then_some(reader.read_array(Block::new)?), }) diff --git a/src/error.rs b/src/error.rs index 320bce8..13b60db 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,11 +1,9 @@ #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("illegal file magic of {0}")] + #[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)] WrongMagic(u32), #[error("used version {0} but pak is version {1}")] WrongVersion(super::Version, super::Version), - #[error("couldn't convert {0} to boolean")] - BoolConv(u8), #[error("io error: {0}")] IoError(#[from] std::io::Error), #[error("enum conversion: {0}")] @@ -14,6 +12,8 @@ pub enum Error { Utf8Conv(#[from] std::string::FromUtf8Error), #[error("utf16 conversion: {0}")] Utf16Conv(#[from] std::string::FromUtf16Error), + #[error("got {0}, which is not a boolean")] + BoolConv(u8), #[error("{0}")] Other(String), } diff --git a/src/ext.rs b/src/ext.rs index c0589e1..afc7c78 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -39,7 +39,6 @@ impl ReadExt for R { fn read_string(&mut self) -> Result { Ok(match self.read_i32::()? { - size if size.is_positive() => String::from_utf8(self.read_len(size as usize)?)?, size if size.is_negative() => { let mut buf = Vec::with_capacity(-size as usize); for _ in 0..buf.capacity() { @@ -47,12 +46,12 @@ impl ReadExt for R { } String::from_utf16(&buf)? } - _ => String::new(), + size => String::from_utf8(self.read_len(size as usize)?)?, }) } fn read_len(&mut self, len: usize) -> Result, super::Error> { - let mut buf = Vec::with_capacity(len); + let mut buf = vec![0; len]; self.read_exact(&mut buf)?; Ok(buf) } diff --git a/src/footer.rs b/src/footer.rs index efe2ce9..b491a65 100644 --- a/src/footer.rs +++ b/src/footer.rs @@ -18,44 +18,55 @@ pub struct Footer { } impl Footer { - pub fn new(reader: &mut R, version: &Version) -> Result { - let footer = Footer { - encryption_uuid: (version >= &Version::EncryptionKeyGuid) - .then_some(reader.read_u128::()?), - encrypted: (version >= &Version::CompressionEncryption).then_some(reader.read_bool()?), + pub fn new(reader: &mut R, version: Version) -> Result { + let footer = Self { + encryption_uuid: match version >= Version::EncryptionKeyGuid { + true => Some(reader.read_u128::()?), + false => None, + }, + encrypted: match version >= Version::IndexEncryption { + true => Some(reader.read_bool()?), + false => None, + }, magic: reader.read_u32::()?, - version: Version::from_repr(reader.read_u32::()?).unwrap_or_default(), + version: Version::from_repr(reader.read_u32::()?).unwrap_or(version), offset: reader.read_u64::()?, size: reader.read_u64::()?, hash: reader.read_guid()?, - frozen: (version == &Version::FrozenIndex).then_some(reader.read_bool()?), - compression: (version >= &Version::FNameBasedCompression).then_some({ - let mut compression = - Vec::with_capacity(match version == &Version::FNameBasedCompression { - true => 4, - false => 5, - }); - for _ in 0..compression.capacity() { - compression.push( - Compression::from_str( - &reader - .read_len(32)? - .iter() - // filter out whitespace and convert to char - .filter_map(|&ch| (ch != 0).then_some(ch as char)) - .collect::(), + frozen: match version == Version::FrozenIndex { + true => Some(reader.read_bool()?), + false => None, + }, + compression: match version >= Version::FNameBasedCompression { + true => { + let mut compression = + Vec::with_capacity(match version == Version::FNameBasedCompression { + true => 4, + false => 5, + }); + for _ in 0..compression.capacity() { + compression.push( + Compression::from_str( + &reader + .read_len(32)? + .iter() + // filter out whitespace and convert to char + .filter_map(|&ch| (ch != 0).then_some(ch as char)) + .collect::(), + ) + .unwrap_or_default(), ) - .unwrap_or_default(), - ) + } + Some(compression) } - compression - }), + false => None, + }, }; if super::MAGIC != footer.magic { return Err(super::Error::WrongMagic(footer.magic)); } - if version != &footer.version { - return Err(super::Error::WrongVersion(*version, footer.version)); + if version != footer.version { + return Err(super::Error::WrongVersion(version, footer.version)); } Ok(footer) } diff --git a/src/index.rs b/src/index.rs index 92f2ffe..4404bae 100644 --- a/src/index.rs +++ b/src/index.rs @@ -7,8 +7,8 @@ pub enum Index { } impl Index { - pub fn new(reader: &mut R, version: &Version) -> Result { - Ok(match version < &Version::PathHashIndex { + pub fn new(reader: &mut R, version: Version) -> Result { + Ok(match version < Version::PathHashIndex { true => Index::WithoutPathHash(IndexV1::new(reader, version)?), false => Index::WithPathHash, }) @@ -24,7 +24,7 @@ pub struct IndexV1 { impl IndexV1 { pub fn new( reader: &mut R, - version: &super::Version, + version: super::Version, ) -> Result { Ok(Self { mount_point: reader.read_string()?, diff --git a/src/lib.rs b/src/lib.rs index b49f359..c486864 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,19 +12,10 @@ pub const MAGIC: u32 = 0x5A6F12E1; #[repr(u32)] #[derive( - Default, - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Debug, - strum::Display, - strum::FromRepr, - strum::EnumIter, + Clone, Copy, PartialEq, Eq, PartialOrd, Debug, strum::Display, strum::FromRepr, strum::EnumIter, )] pub enum Version { - Unknown, // unknown (mostly just for padding :p) + Unknown, // unknown (mostly just for padding) Initial, // initial specification NoTimestamps, // timestamps removed CompressionEncryption, // compression and encryption support @@ -34,8 +25,7 @@ pub enum Version { EncryptionKeyGuid, // include key GUID FNameBasedCompression, // compression names included FrozenIndex, // frozen index byte included - #[default] - PathHashIndex, // more compression methods + PathHashIndex, // more compression methods } // strum shouldn't need to be installed by users diff --git a/src/pak.rs b/src/pak.rs index 62d6ac0..69e06f4 100644 --- a/src/pak.rs +++ b/src/pak.rs @@ -15,9 +15,9 @@ impl Pak { mut reader: R, ) -> Result { reader.seek(io::SeekFrom::End(-footer_size(&version)))?; - let footer = super::Footer::new(&mut reader, &version)?; + let footer = super::Footer::new(&mut reader, version)?; reader.seek(io::SeekFrom::Start(footer.offset))?; - let index = super::Index::new(&mut reader, &version)?; + let index = super::Index::new(&mut reader, version)?; Ok(Self { version, footer,