mirror of
https://github.com/xavo95/repak.git
synced 2025-01-18 19:04:07 +00:00
eager evaluation was the first problem
This commit is contained in:
parent
39ea548d57
commit
778b87570a
8 changed files with 60 additions and 70 deletions
|
@ -1,18 +1,8 @@
|
||||||
fn main() -> Result<(), un_pak::Error> {
|
fn main() -> Result<(), un_pak::Error> {
|
||||||
let path = std::env::args().nth(1).unwrap_or_default();
|
let pak = un_pak::Pak::new(
|
||||||
for version in un_pak::Version::iter() {
|
un_pak::Version::CompressionEncryption,
|
||||||
print!("{version} - ");
|
std::io::Cursor::new(include_bytes!("rando_p.pak")),
|
||||||
match un_pak::Pak::new(
|
)?;
|
||||||
version,
|
print!("{:#?}", pak);
|
||||||
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);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct Entry {
|
||||||
impl Entry {
|
impl Entry {
|
||||||
pub fn new<R: std::io::Read>(
|
pub fn new<R: std::io::Read>(
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
version: &super::Version,
|
version: super::Version,
|
||||||
) -> Result<Self, super::Error> {
|
) -> Result<Self, super::Error> {
|
||||||
let name = reader.read_string()?;
|
let name = reader.read_string()?;
|
||||||
let offset = reader.read_u64::<LE>()?;
|
let offset = reader.read_u64::<LE>()?;
|
||||||
|
@ -35,9 +35,9 @@ impl Entry {
|
||||||
compressed,
|
compressed,
|
||||||
uncompressed,
|
uncompressed,
|
||||||
compression_method,
|
compression_method,
|
||||||
timestamp: (version == &Version::Initial).then_some(reader.read_u64::<LE>()?),
|
timestamp: (version == Version::Initial).then_some(reader.read_u64::<LE>()?),
|
||||||
hash: reader.read_guid()?,
|
hash: reader.read_guid()?,
|
||||||
compression_blocks: (version >= &Version::CompressionEncryption
|
compression_blocks: (version >= Version::CompressionEncryption
|
||||||
&& compression_method != Compression::None)
|
&& compression_method != Compression::None)
|
||||||
.then_some(reader.read_array(Block::new)?),
|
.then_some(reader.read_array(Block::new)?),
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("illegal file magic of {0}")]
|
#[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)]
|
||||||
WrongMagic(u32),
|
WrongMagic(u32),
|
||||||
#[error("used version {0} but pak is version {1}")]
|
#[error("used version {0} but pak is version {1}")]
|
||||||
WrongVersion(super::Version, super::Version),
|
WrongVersion(super::Version, super::Version),
|
||||||
#[error("couldn't convert {0} to boolean")]
|
|
||||||
BoolConv(u8),
|
|
||||||
#[error("io error: {0}")]
|
#[error("io error: {0}")]
|
||||||
IoError(#[from] std::io::Error),
|
IoError(#[from] std::io::Error),
|
||||||
#[error("enum conversion: {0}")]
|
#[error("enum conversion: {0}")]
|
||||||
|
@ -14,6 +12,8 @@ pub enum Error {
|
||||||
Utf8Conv(#[from] std::string::FromUtf8Error),
|
Utf8Conv(#[from] std::string::FromUtf8Error),
|
||||||
#[error("utf16 conversion: {0}")]
|
#[error("utf16 conversion: {0}")]
|
||||||
Utf16Conv(#[from] std::string::FromUtf16Error),
|
Utf16Conv(#[from] std::string::FromUtf16Error),
|
||||||
|
#[error("got {0}, which is not a boolean")]
|
||||||
|
BoolConv(u8),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ impl<R: std::io::Read> ReadExt for R {
|
||||||
|
|
||||||
fn read_string(&mut self) -> Result<String, crate::Error> {
|
fn read_string(&mut self) -> Result<String, crate::Error> {
|
||||||
Ok(match self.read_i32::<LE>()? {
|
Ok(match self.read_i32::<LE>()? {
|
||||||
size if size.is_positive() => String::from_utf8(self.read_len(size as usize)?)?,
|
|
||||||
size if size.is_negative() => {
|
size if size.is_negative() => {
|
||||||
let mut buf = Vec::with_capacity(-size as usize);
|
let mut buf = Vec::with_capacity(-size as usize);
|
||||||
for _ in 0..buf.capacity() {
|
for _ in 0..buf.capacity() {
|
||||||
|
@ -47,12 +46,12 @@ impl<R: std::io::Read> ReadExt for R {
|
||||||
}
|
}
|
||||||
String::from_utf16(&buf)?
|
String::from_utf16(&buf)?
|
||||||
}
|
}
|
||||||
_ => String::new(),
|
size => String::from_utf8(self.read_len(size as usize)?)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_len(&mut self, len: usize) -> Result<Vec<u8>, super::Error> {
|
fn read_len(&mut self, len: usize) -> Result<Vec<u8>, super::Error> {
|
||||||
let mut buf = Vec::with_capacity(len);
|
let mut buf = vec![0; len];
|
||||||
self.read_exact(&mut buf)?;
|
self.read_exact(&mut buf)?;
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,44 +18,55 @@ pub struct Footer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Footer {
|
impl Footer {
|
||||||
pub fn new<R: std::io::Read>(reader: &mut R, version: &Version) -> Result<Self, super::Error> {
|
pub fn new<R: std::io::Read>(reader: &mut R, version: Version) -> Result<Self, super::Error> {
|
||||||
let footer = Footer {
|
let footer = Self {
|
||||||
encryption_uuid: (version >= &Version::EncryptionKeyGuid)
|
encryption_uuid: match version >= Version::EncryptionKeyGuid {
|
||||||
.then_some(reader.read_u128::<LE>()?),
|
true => Some(reader.read_u128::<LE>()?),
|
||||||
encrypted: (version >= &Version::CompressionEncryption).then_some(reader.read_bool()?),
|
false => None,
|
||||||
|
},
|
||||||
|
encrypted: match version >= Version::IndexEncryption {
|
||||||
|
true => Some(reader.read_bool()?),
|
||||||
|
false => None,
|
||||||
|
},
|
||||||
magic: reader.read_u32::<LE>()?,
|
magic: reader.read_u32::<LE>()?,
|
||||||
version: Version::from_repr(reader.read_u32::<LE>()?).unwrap_or_default(),
|
version: Version::from_repr(reader.read_u32::<LE>()?).unwrap_or(version),
|
||||||
offset: reader.read_u64::<LE>()?,
|
offset: reader.read_u64::<LE>()?,
|
||||||
size: reader.read_u64::<LE>()?,
|
size: reader.read_u64::<LE>()?,
|
||||||
hash: reader.read_guid()?,
|
hash: reader.read_guid()?,
|
||||||
frozen: (version == &Version::FrozenIndex).then_some(reader.read_bool()?),
|
frozen: match version == Version::FrozenIndex {
|
||||||
compression: (version >= &Version::FNameBasedCompression).then_some({
|
true => Some(reader.read_bool()?),
|
||||||
let mut compression =
|
false => None,
|
||||||
Vec::with_capacity(match version == &Version::FNameBasedCompression {
|
},
|
||||||
true => 4,
|
compression: match version >= Version::FNameBasedCompression {
|
||||||
false => 5,
|
true => {
|
||||||
});
|
let mut compression =
|
||||||
for _ in 0..compression.capacity() {
|
Vec::with_capacity(match version == Version::FNameBasedCompression {
|
||||||
compression.push(
|
true => 4,
|
||||||
Compression::from_str(
|
false => 5,
|
||||||
&reader
|
});
|
||||||
.read_len(32)?
|
for _ in 0..compression.capacity() {
|
||||||
.iter()
|
compression.push(
|
||||||
// filter out whitespace and convert to char
|
Compression::from_str(
|
||||||
.filter_map(|&ch| (ch != 0).then_some(ch as char))
|
&reader
|
||||||
.collect::<String>(),
|
.read_len(32)?
|
||||||
|
.iter()
|
||||||
|
// filter out whitespace and convert to char
|
||||||
|
.filter_map(|&ch| (ch != 0).then_some(ch as char))
|
||||||
|
.collect::<String>(),
|
||||||
|
)
|
||||||
|
.unwrap_or_default(),
|
||||||
)
|
)
|
||||||
.unwrap_or_default(),
|
}
|
||||||
)
|
Some(compression)
|
||||||
}
|
}
|
||||||
compression
|
false => None,
|
||||||
}),
|
},
|
||||||
};
|
};
|
||||||
if super::MAGIC != footer.magic {
|
if super::MAGIC != footer.magic {
|
||||||
return Err(super::Error::WrongMagic(footer.magic));
|
return Err(super::Error::WrongMagic(footer.magic));
|
||||||
}
|
}
|
||||||
if version != &footer.version {
|
if version != footer.version {
|
||||||
return Err(super::Error::WrongVersion(*version, footer.version));
|
return Err(super::Error::WrongVersion(version, footer.version));
|
||||||
}
|
}
|
||||||
Ok(footer)
|
Ok(footer)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ pub enum Index {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index {
|
impl Index {
|
||||||
pub fn new<R: std::io::Read>(reader: &mut R, version: &Version) -> Result<Self, super::Error> {
|
pub fn new<R: std::io::Read>(reader: &mut R, version: Version) -> Result<Self, super::Error> {
|
||||||
Ok(match version < &Version::PathHashIndex {
|
Ok(match version < Version::PathHashIndex {
|
||||||
true => Index::WithoutPathHash(IndexV1::new(reader, version)?),
|
true => Index::WithoutPathHash(IndexV1::new(reader, version)?),
|
||||||
false => Index::WithPathHash,
|
false => Index::WithPathHash,
|
||||||
})
|
})
|
||||||
|
@ -24,7 +24,7 @@ pub struct IndexV1 {
|
||||||
impl IndexV1 {
|
impl IndexV1 {
|
||||||
pub fn new<R: std::io::Read>(
|
pub fn new<R: std::io::Read>(
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
version: &super::Version,
|
version: super::Version,
|
||||||
) -> Result<Self, super::Error> {
|
) -> Result<Self, super::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
mount_point: reader.read_string()?,
|
mount_point: reader.read_string()?,
|
||||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -12,19 +12,10 @@ pub const MAGIC: u32 = 0x5A6F12E1;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(
|
#[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 {
|
pub enum Version {
|
||||||
Unknown, // unknown (mostly just for padding :p)
|
Unknown, // unknown (mostly just for padding)
|
||||||
Initial, // initial specification
|
Initial, // initial specification
|
||||||
NoTimestamps, // timestamps removed
|
NoTimestamps, // timestamps removed
|
||||||
CompressionEncryption, // compression and encryption support
|
CompressionEncryption, // compression and encryption support
|
||||||
|
@ -34,8 +25,7 @@ pub enum Version {
|
||||||
EncryptionKeyGuid, // include key GUID
|
EncryptionKeyGuid, // include key GUID
|
||||||
FNameBasedCompression, // compression names included
|
FNameBasedCompression, // compression names included
|
||||||
FrozenIndex, // frozen index byte included
|
FrozenIndex, // frozen index byte included
|
||||||
#[default]
|
PathHashIndex, // more compression methods
|
||||||
PathHashIndex, // more compression methods
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// strum shouldn't need to be installed by users
|
// strum shouldn't need to be installed by users
|
||||||
|
|
|
@ -15,9 +15,9 @@ impl Pak {
|
||||||
mut reader: R,
|
mut reader: R,
|
||||||
) -> Result<Self, super::Error> {
|
) -> Result<Self, super::Error> {
|
||||||
reader.seek(io::SeekFrom::End(-footer_size(&version)))?;
|
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))?;
|
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 {
|
Ok(Self {
|
||||||
version,
|
version,
|
||||||
footer,
|
footer,
|
||||||
|
|
Loading…
Reference in a new issue