Make bff more resilient and add tests

This commit is contained in:
widberg 2023-06-29 18:44:41 -04:00
parent b4fe0e50d2
commit 6c2f0f34ef
6 changed files with 137 additions and 21 deletions

76
Cargo.lock generated
View file

@ -73,6 +73,7 @@ dependencies = [
"ascii",
"binrw",
"serde",
"test-generator",
]
[[package]]
@ -111,8 +112,8 @@ checksum = "d6b019a3efebe7f453612083202887b6f1ace59e20d010672e336eea4ed5be97"
dependencies = [
"either",
"owo-colors",
"proc-macro2",
"quote",
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 1.0.109",
]
@ -165,8 +166,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
dependencies = [
"heck",
"proc-macro2",
"quote",
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 2.0.15",
]
@ -209,6 +210,12 @@ dependencies = [
"libc",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "heck"
version = "0.4.1"
@ -274,6 +281,15 @@ version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid",
]
[[package]]
name = "proc-macro2"
version = "1.0.56"
@ -283,13 +299,22 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]]
name = "quote"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
"proc-macro2 1.0.56",
]
[[package]]
@ -327,8 +352,8 @@ version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 2.0.15",
]
@ -349,14 +374,25 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"unicode-xid",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"proc-macro2 1.0.56",
"quote 1.0.26",
"unicode-ident",
]
@ -366,17 +402,35 @@ version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
"proc-macro2 1.0.56",
"quote 1.0.26",
"unicode-ident",
]
[[package]]
name = "test-generator"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b23be2add79223226e1cb6446cb3e37506a5927089870687a0f1149bb7a073a"
dependencies = [
"glob",
"proc-macro2 0.4.30",
"quote 0.6.13",
"syn 0.15.44",
]
[[package]]
name = "unicode-ident"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "utf8parse"
version = "0.2.1"

View file

@ -7,12 +7,16 @@ use std::io;
use std::path::PathBuf;
use std::time::Instant;
pub fn info(bigfile: &PathBuf) -> Result<(), Box<dyn std::error::Error>> {
let f = File::open(bigfile)?;
pub fn info(bigfile_path: &PathBuf) -> Result<(), Box<dyn std::error::Error>> {
let endian = match bigfile_path.extension() {
Some(extension) => extension_to_endian(extension).unwrap_or(Endian::Little),
None => Endian::Little,
};
let f = File::open(bigfile_path)?;
let now = Instant::now();
let mut reader = BufReader::new(f);
let elapsed = now.elapsed();
let bigfile = BigFile::read_options(&mut reader, Endian::Little, ())?;
let bigfile = BigFile::read_options(&mut reader, endian, ())?;
to_writer_pretty(io::stdout().lock(), &bigfile)?;
println!("Time to parse: {:?}", elapsed);
Ok(())

View file

@ -8,3 +8,6 @@ edition = "2021"
ascii = { version = "1.1.0", features = ["serde"] }
binrw = "0.11.2"
serde = { version = "1.0.160", features = ["derive"] }
[dev-dependencies]
test-generator = "0.3.1"

View file

@ -1,3 +1,5 @@
use std::ffi::OsStr;
use crate::{block::Block, header::*, pool::Pool};
use binrw::*;
use serde::Serialize;
@ -18,5 +20,46 @@ pub struct BigFile {
header: Header,
#[br(parse_with = blocks_parser, args(header.block_descriptions()))]
blocks: Vec<Block>,
pool: Pool,
#[br(if(header.has_pool()))]
pool: Option<Pool>,
}
pub fn extension_to_endian(extension: &OsStr) -> Option<Endian> {
match extension.to_ascii_uppercase().to_str() {
Some("DPC") => Some(Endian::Little),
Some("DUA") => Some(Endian::Little),
Some("DMC") => Some(Endian::Little),
Some("DBM") => Some(Endian::Big),
Some("DPS") => Some(Endian::Little),
Some("DP3") => Some(Endian::Big),
Some("DPP") => Some(Endian::Little),
Some("DXB") => Some(Endian::Big),
Some("D36") => Some(Endian::Big),
Some("DGC") => Some(Endian::Big),
Some("DRV") => Some(Endian::Big),
Some("DNX") => Some(Endian::Little),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use binrw::io::BufReader;
use std::{fs::File, path::PathBuf};
use test_generator::test_resources;
#[test_resources("data/bigfiles/**/*.*")]
fn read(bigfile_path_str: &str) {
let mut bigfile_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
bigfile_path.pop();
bigfile_path.push(bigfile_path_str);
let endian = match bigfile_path.extension() {
Some(extension) => extension_to_endian(extension).unwrap_or(Endian::Little),
None => Endian::Little,
};
let f = File::open(bigfile_path).unwrap();
let mut reader = BufReader::new(f);
let _ = BigFile::read_options(&mut reader, endian, ()).unwrap();
}
}

View file

@ -47,6 +47,8 @@ pub struct Header {
block_descriptions: Vec<BlockDescription>,
#[br(temp)]
pool_manifest_padded_size: u32,
#[br(calc = pool_manifest_padded_size != u32::MAX && pool_manifest_padded_size != 0)]
has_pool: bool,
#[br(temp)]
pool_manifest_offset: u32,
pool_manifest_unused0: u32,
@ -60,12 +62,20 @@ pub struct Header {
pool_sector_padding_size: u32,
#[br(temp)]
file_size: u32,
#[brw(align_after = 2048)]
incredi_builder_string: FixedStringNULL<128>,
#[br(temp, restore_position)]
incredi_builder_string_char: u8,
#[brw(if(incredi_builder_string_char != u8::MAX))]
incredi_builder_string: Option<FixedStringNULL<128>>,
#[br(temp, align_after = 2048)]
padding: (),
}
impl Header {
pub fn block_descriptions(&self) -> &Vec<BlockDescription> {
&self.block_descriptions
}
pub fn has_pool(&self) -> bool {
self.has_pool
}
}

View file

@ -2,8 +2,9 @@ use binrw::{BinReaderExt, BinResult};
#[binrw::parser(reader, endian)]
pub fn decompress_body_parser(decompressed_size: u32, compressed_size: u32) -> BinResult<Vec<u8>> {
let read_decompressed_size = reader.read_type::<u32>(endian)?;
let read_compressed_size = reader.read_type::<u32>(endian)?;
// These fields are little endian even on big endian platforms.
let read_decompressed_size = reader.read_le::<u32>()?;
let read_compressed_size = reader.read_le::<u32>()?;
// Ensure the values from the object header match the values
// in the compressed data.
@ -17,8 +18,9 @@ pub fn decompress_body_parser(decompressed_size: u32, compressed_size: u32) -> B
#[binrw::parser(reader, endian)]
pub fn decompress_data_with_header_parser() -> BinResult<Vec<u8>> {
let decompressed_size = reader.read_type::<u32>(endian)?;
let compressed_size = reader.read_type::<u32>(endian)?;
// These fields are little endian even on big endian platforms.
let decompressed_size = reader.read_le::<u32>()?;
let compressed_size = reader.read_le::<u32>()?;
decompress_data_parser(reader, endian, (decompressed_size, compressed_size - 8))
}