diff --git a/Cargo.lock b/Cargo.lock index 94537ce..1fcd04a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,7 +62,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", - "libz-sys", "miniz_oxide", ] @@ -107,17 +106,6 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" -[[package]] -name = "libz-sys" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - [[package]] name = "log" version = "0.4.20" @@ -205,12 +193,6 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - [[package]] name = "proc-macro2" version = "1.0.69" @@ -394,12 +376,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "winapi" version = "0.3.9" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index c6c14d1..3dd44f4 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -flate2 = { version = "1.0.28", features = ["zlib"] } +flate2 = "1.0.28" loom = { version = "0.7.1", optional = true } nom = "7.1.3" diff --git a/lib/src/packfile/mod.rs b/lib/src/packfile/mod.rs index 6cae093..f5a6ee9 100644 --- a/lib/src/packfile/mod.rs +++ b/lib/src/packfile/mod.rs @@ -2,11 +2,22 @@ mod nom; +use flate2::read::ZlibDecoder; #[allow(clippy::wildcard_imports)] use nom::*; +use std::io::Read; #[derive(Debug, PartialEq)] -enum EntryKind {} +enum EntryKind { + // TODO(nenikitov): Add more kinds + Unknown, +} + +#[derive(Debug, PartialEq)] +struct EntryHeader { + offset: u32, + size: u32, +} #[derive(Debug, PartialEq)] pub struct EntryData { @@ -20,17 +31,11 @@ pub struct PackFile { entries: Vec, } -#[derive(Debug, PartialEq)] -struct EntryHeader { - offset: u32, - size: u32, -} - impl PackFile { const HEADER: &'static str = "PMAN"; const COPYRIGHT_LENGTH: usize = 56; - pub fn new(bytes: &[u8]) -> Result { + pub fn new(input: &[u8]) -> Result { todo!() } @@ -47,8 +52,8 @@ impl PackFile { Ok((input, (copyright, total_entries))) } - fn entries(input: &[u8], total_entries: u32) -> Result> { - fn entry(input: &[u8]) -> Result { + fn entry_headers(input: &[u8], total_entries: u32) -> Result> { + fn entry_header(input: &[u8]) -> Result { // TODO(nenikitov): add check for `asset_kind == 0` let (input, asset_kind) = number::le_u32(input)?; @@ -62,7 +67,40 @@ impl PackFile { Ok((input, EntryHeader { offset, size })) } - multi::count(entry, total_entries as usize)(input) + multi::count(entry_header, total_entries as usize)(input) + } + + #[allow(clippy::unnecessary_wraps)] // TODO(Unavailable): Rewrite using nom + fn entries<'a>( + input: &'a [u8], + entry_headers: &'_ [EntryHeader], + ) -> Result<'a, Vec> { + fn entry(input: &[u8], entry_header: &EntryHeader) -> EntryData { + let bytes = &input[entry_header.offset as usize..][..entry_header.size as usize]; + let bytes = if let [b'Z', b'L', s1, s2, s3, bytes @ ..] = bytes { + let size = u32::from_le_bytes([*s1, *s2, *s3, 0]); + + let mut decoder = ZlibDecoder::new(bytes); + let mut data = Vec::with_capacity(size as usize); + decoder + .read_to_end(&mut data) + .expect("Data should be a valid zlib stream"); + // TODO(nenikitov): Check if `data.len() == size` + + data + } else { + bytes.to_vec() + }; + + EntryData { + bytes, + kind: EntryKind::Unknown, + } + } + + let entries = entry_headers.iter().map(|h| entry(input, h)).collect(); + + Ok((&[], entries)) } } @@ -83,7 +121,7 @@ mod tests { #[test] fn packfile_entries_works() -> eyre::Result<()> { #[rustfmt::skip] - let (_, entries) = PackFile::entries( + let (_, entries) = PackFile::entry_headers( &[ // File 1 0x00, 0x00, 0x00, 0x00, @@ -115,4 +153,43 @@ mod tests { Ok(()) } + + #[test] + fn packfile_entry_data_works() -> eyre::Result<()> { + #[rustfmt::skip] + let (_, entries) = PackFile::entries( + &[ + // File 1 + b'A', b's', b'h', b'e', b'n', + // File 2 + b'Z', b'L', // Asset Zlib signature + 0x06, 0x00, 0x00, // Stream size + 0x78, 0xDA, // Actual Zlib signature + 0x73, 0x2C, 0xCE, 0x48, 0xCD, 0xE3, 0x02, 0x00, 0x07, 0x80, 0x01, 0xFA, + ], + &[ + EntryHeader { offset: 0, size: 5 }, + EntryHeader { + offset: 5, + size: 19, + }, + ], + )?; + + assert_eq!( + entries, + [ + EntryData { + bytes: b"Ashen".to_vec(), + kind: EntryKind::Unknown + }, + EntryData { + bytes: b"Ashen\n".to_vec(), + kind: EntryKind::Unknown + } + ] + ); + + Ok(()) + } }