Restructure footer and pak reading to make debugging custom serialization easier

This commit is contained in:
Truman Kilen 2023-09-17 16:57:21 -05:00
parent a749449f8c
commit ff3c9b265b
3 changed files with 79 additions and 69 deletions

View file

@ -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<Self, super::Error> {
// 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::<LE>()?;
let compressed = reader.read_u64::<LE>()?;
let uncompressed = reader.read_u64::<LE>()?;
@ -100,32 +100,26 @@ impl Entry {
0 => None,
n => Some(n - 1),
};
let timestamp = (ver == VersionMajor::Initial).then_try(|| reader.read_u64::<LE>())?;
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::<LE>())?
.unwrap_or(0);
Ok(Self {
offset,
compressed,
uncompressed,
compression,
timestamp: match version.version_major() == VersionMajor::Initial {
true => Some(reader.read_u64::<LE>()?),
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::<LE>()?,
false => 0,
},
timestamp,
hash,
blocks,
flags,
compression_block_size,
})
}

View file

@ -1,5 +1,15 @@
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
pub trait BoolExt<T, E, F: FnOnce() -> Result<T, E>> {
fn then_try(&self, f: F) -> Result<Option<T>, E>;
}
impl<T, E, F: FnOnce() -> Result<T, E>> BoolExt<T, E, F> for bool {
fn then_try(&self, f: F) -> Result<Option<T>, E> {
self.then(f).transpose()
}
}
pub trait ReadExt {
fn read_bool(&mut self) -> Result<bool, super::Error>;
fn read_guid(&mut self) -> Result<[u8; 20], super::Error>;

View file

@ -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,22 +20,18 @@ pub struct Footer {
impl Footer {
pub fn read<R: std::io::Read>(reader: &mut R, version: Version) -> Result<Self, super::Error> {
let footer = Self {
encryption_uuid: match version.version_major() >= VersionMajor::EncryptionKeyGuid {
true => Some(reader.read_u128::<LE>()?),
false => None,
},
encrypted: version.version_major() >= VersionMajor::IndexEncryption
&& reader.read_bool()?,
magic: reader.read_u32::<LE>()?,
version,
version_major: VersionMajor::from_repr(reader.read_u32::<LE>()?)
.unwrap_or(version.version_major()),
index_offset: reader.read_u64::<LE>()?,
index_size: reader.read_u64::<LE>()?,
hash: reader.read_guid()?,
frozen: version.version_major() == VersionMajor::FrozenIndex && reader.read_bool()?,
compression: {
let encryption_uuid = (version.version_major() >= VersionMajor::EncryptionKeyGuid)
.then_try(|| reader.read_u128::<LE>())?;
let encrypted =
version.version_major() >= VersionMajor::IndexEncryption && reader.read_bool()?;
let magic = reader.read_u32::<LE>()?;
let version_major =
VersionMajor::from_repr(reader.read_u32::<LE>()?).unwrap_or(version.version_major());
let index_offset = reader.read_u64::<LE>()?;
let index_size = reader.read_u64::<LE>()?;
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,
@ -60,18 +56,28 @@ impl Footer {
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<W: std::io::Write>(&self, writer: &mut W) -> Result<(), super::Error> {