diff --git a/CHANGELOG.md b/CHANGELOG.md index 684d57f..ef02d30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add support to the vpk0 format, courtesy of (tehzz)[https://github.com/tehzz/vpk0]. + ## [0.5.4] - 2024-12-15 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 450a9e2..eaa16cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "bitstream-io" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614aa3f2bac03707e62a84d18a48dd3d9ea6171313fd5e6a53b5054d8ae74601" + [[package]] name = "cfg-if" version = "1.0.3" @@ -136,6 +142,7 @@ dependencies = [ "pyo3", "rstest", "thiserror", + "vpk0", ] [[package]] @@ -271,6 +278,15 @@ version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.7.5" @@ -482,6 +498,23 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +[[package]] +name = "slice-deque" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" +dependencies = [ + "libc", + "mach", + "winapi", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "strsim" version = "0.11.1" @@ -543,6 +576,39 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "vpk0" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13013efd5acdb38fba304715f0a278d9347aa68f90c94e7545b53dbb14bdcd3a" +dependencies = [ + "bitstream-io", + "slice-deque", + "smallvec", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-link" version = "0.1.3" diff --git a/c_bindings/include/crunch64/error.h b/c_bindings/include/crunch64/error.h index ca23a3b..90b80b5 100644 --- a/c_bindings/include/crunch64/error.h +++ b/c_bindings/include/crunch64/error.h @@ -19,6 +19,7 @@ typedef enum Crunch64Error { Crunch64Error_OutOfBounds, Crunch64Error_NullPointer, Crunch64Error_InvalidCompressionLevel, + Crunch64Error_Vpk0, } Crunch64Error; #ifdef __cplusplus diff --git a/cli/src/main.rs b/cli/src/main.rs index 68dafcd..27c1c0e 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -19,6 +19,7 @@ enum CompressionType { Yaz0, Mio0, Gzip, + Vpk0, } #[derive(Parser, Debug)] @@ -46,6 +47,7 @@ fn compress(args: &Args, bytes: &[u8]) -> Result, Crunch64Error> { CompressionType::Yaz0 => crunch64::yaz0::compress(bytes), CompressionType::Mio0 => crunch64::mio0::compress(bytes), CompressionType::Gzip => crunch64::gzip::compress(bytes, args.level, args.small_mem), + CompressionType::Vpk0 => crunch64::vpk0::compress(bytes), // _ => Err(Crunch64Error::UnsupportedCompressionType), } } @@ -55,6 +57,7 @@ fn decompress(args: &Args, bytes: &[u8]) -> Result, Crunch64Error> { CompressionType::Yay0 => crunch64::yay0::decompress(bytes), CompressionType::Yaz0 => crunch64::yaz0::decompress(bytes), CompressionType::Mio0 => crunch64::mio0::decompress(bytes), + CompressionType::Vpk0 => crunch64::vpk0::decompress(bytes), _ => Err(Crunch64Error::UnsupportedCompressionType), } } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 3895fd7..fc347d4 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -17,6 +17,7 @@ crate-type = ["lib", "staticlib", "cdylib"] crc32fast = "1.4.2" pyo3 = { version="0.23.5", features = ["extension-module"], optional = true } thiserror = "1.0" +vpk0 = "0.8.2" [dev-dependencies] rstest = "0.18.2" diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 3f5036f..78e5a80 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,5 +1,6 @@ pub mod gzip; pub mod mio0; +pub mod vpk0; pub mod yay0; pub mod yaz0; @@ -14,7 +15,8 @@ use pyo3::prelude::*; /* This needs to be in sync with the C equivalent at `crunch64/error.h` */ #[cfg_attr(feature = "c_bindings", repr(u32))] -#[derive(Copy, Clone, Debug, Error, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "c_bindings", derive(Copy))] +#[derive(Clone, Debug, Error, PartialEq, Eq, Hash)] pub enum Crunch64Error { #[error("Not an error")] Okay, @@ -36,6 +38,8 @@ pub enum Crunch64Error { NullPointer, #[error("Invalid compression level")] InvalidCompressionLevel, + #[error("Failed to handle vpk0 data")] + Vpk0, } #[cfg(feature = "python_bindings")] diff --git a/lib/src/vpk0.rs b/lib/src/vpk0.rs new file mode 100644 index 0000000..db2f3ae --- /dev/null +++ b/lib/src/vpk0.rs @@ -0,0 +1,15 @@ +use crate::Crunch64Error; + +pub fn compress(bytes: &[u8]) -> Result, Crunch64Error> { + match vpk0::encode_bytes(bytes) { + Ok(bytes) => Ok(bytes.into_boxed_slice()), + Err(_) => Err(Crunch64Error::Vpk0), + } +} + +pub fn decompress(bytes: &[u8]) -> Result, Crunch64Error> { + match vpk0::decode_bytes(bytes) { + Ok(bytes) => Ok(bytes.into_boxed_slice()), + Err(_) => Err(Crunch64Error::Vpk0), + } +}