From ff3c9b265bcfefcac8462eededebdb3b28fec6b3 Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Sun, 17 Sep 2023 16:57:21 -0500 Subject: [PATCH] Restructure footer and pak reading to make debugging custom serialization easier --- repak/src/entry.rs | 40 ++++++++---------- repak/src/ext.rs | 10 +++++ repak/src/footer.rs | 98 ++++++++++++++++++++++++--------------------- 3 files changed, 79 insertions(+), 69 deletions(-) diff --git a/repak/src/entry.rs b/repak/src/entry.rs index bf9e5ba..00b3dfb 100644 --- a/repak/src/entry.rs +++ b/repak/src/entry.rs @@ -1,4 +1,4 @@ -use super::{ext::ReadExt, Compression, Version, VersionMajor}; +use super::{ext::BoolExt, ext::ReadExt, Compression, Version, VersionMajor}; use byteorder::{ReadBytesExt, WriteBytesExt, LE}; use std::io; @@ -88,7 +88,7 @@ impl Entry { reader: &mut R, version: super::Version, ) -> Result { - // since i need the compression flags, i have to store these as variables which is mildly annoying + let ver = version.version_major(); let offset = reader.read_u64::()?; let compressed = reader.read_u64::()?; let uncompressed = reader.read_u64::()?; @@ -100,32 +100,26 @@ impl Entry { 0 => None, n => Some(n - 1), }; + let timestamp = (ver == VersionMajor::Initial).then_try(|| reader.read_u64::())?; + let hash = Some(reader.read_guid()?); + let blocks = (ver >= VersionMajor::CompressionEncryption && compression.is_some()) + .then_try(|| reader.read_array(Block::read))?; + let flags = (ver >= VersionMajor::CompressionEncryption) + .then_try(|| reader.read_u8())? + .unwrap_or(0); + let compression_block_size = (ver >= VersionMajor::CompressionEncryption) + .then_try(|| reader.read_u32::())? + .unwrap_or(0); Ok(Self { offset, compressed, uncompressed, compression, - timestamp: match version.version_major() == VersionMajor::Initial { - true => Some(reader.read_u64::()?), - false => None, - }, - hash: Some(reader.read_guid()?), - blocks: match version.version_major() >= VersionMajor::CompressionEncryption - && compression.is_some() - { - true => Some(reader.read_array(Block::read)?), - false => None, - }, - flags: match version.version_major() >= VersionMajor::CompressionEncryption { - true => reader.read_u8()?, - false => 0, - }, - compression_block_size: match version.version_major() - >= VersionMajor::CompressionEncryption - { - true => reader.read_u32::()?, - false => 0, - }, + timestamp, + hash, + blocks, + flags, + compression_block_size, }) } diff --git a/repak/src/ext.rs b/repak/src/ext.rs index ccd3340..67864d1 100644 --- a/repak/src/ext.rs +++ b/repak/src/ext.rs @@ -1,5 +1,15 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LE}; +pub trait BoolExt Result> { + fn then_try(&self, f: F) -> Result, E>; +} + +impl Result> BoolExt for bool { + fn then_try(&self, f: F) -> Result, E> { + self.then(f).transpose() + } +} + pub trait ReadExt { fn read_bool(&mut self) -> Result; fn read_guid(&mut self) -> Result<[u8; 20], super::Error>; diff --git a/repak/src/footer.rs b/repak/src/footer.rs index 7567209..b7bcb2d 100644 --- a/repak/src/footer.rs +++ b/repak/src/footer.rs @@ -1,4 +1,4 @@ -use crate::ext::WriteExt; +use crate::ext::{BoolExt, WriteExt}; use super::{ext::ReadExt, Compression, Version, VersionMajor}; use byteorder::{ReadBytesExt, WriteBytesExt, LE}; @@ -20,58 +20,64 @@ pub struct Footer { impl Footer { pub fn read(reader: &mut R, version: Version) -> Result { - let footer = Self { - encryption_uuid: match version.version_major() >= VersionMajor::EncryptionKeyGuid { - true => Some(reader.read_u128::()?), - false => None, - }, - encrypted: version.version_major() >= VersionMajor::IndexEncryption - && reader.read_bool()?, - magic: reader.read_u32::()?, - version, - version_major: VersionMajor::from_repr(reader.read_u32::()?) - .unwrap_or(version.version_major()), - index_offset: reader.read_u64::()?, - index_size: reader.read_u64::()?, - hash: reader.read_guid()?, - frozen: version.version_major() == VersionMajor::FrozenIndex && reader.read_bool()?, - compression: { - let mut compression = Vec::with_capacity(match version { - ver if ver < Version::V8A => 0, - ver if ver < Version::V8B => 4, - _ => 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(), + let encryption_uuid = (version.version_major() >= VersionMajor::EncryptionKeyGuid) + .then_try(|| reader.read_u128::())?; + let encrypted = + version.version_major() >= VersionMajor::IndexEncryption && reader.read_bool()?; + let magic = reader.read_u32::()?; + let version_major = + VersionMajor::from_repr(reader.read_u32::()?).unwrap_or(version.version_major()); + let index_offset = reader.read_u64::()?; + let index_size = reader.read_u64::()?; + let hash = reader.read_guid()?; + let frozen = version.version_major() == VersionMajor::FrozenIndex && reader.read_bool()?; + let compression = { + let mut compression = Vec::with_capacity(match version { + ver if ver < Version::V8A => 0, + ver if ver < Version::V8B => 4, + _ => 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::(), ) - } - if version < Version::V8A { - compression.push(Compression::Zlib); - compression.push(Compression::Gzip); - compression.push(Compression::Oodle); - } - compression - }, + .unwrap_or_default(), + ) + } + if version < Version::V8A { + compression.push(Compression::Zlib); + compression.push(Compression::Gzip); + compression.push(Compression::Oodle); + } + compression }; - if super::MAGIC != footer.magic { - return Err(super::Error::Magic(footer.magic)); + if super::MAGIC != magic { + return Err(super::Error::Magic(magic)); } - if version.version_major() != footer.version_major { + if version.version_major() != version_major { return Err(super::Error::Version { used: version.version_major(), - version: footer.version_major, + version: version_major, }); } - Ok(footer) + Ok(Self { + encryption_uuid, + encrypted, + magic, + version, + version_major, + index_offset, + index_size, + hash, + frozen, + compression, + }) } pub fn write(&self, writer: &mut W) -> Result<(), super::Error> {