From 95d2862c8db89a693911e244ca04819ea0098d56 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Wed, 6 Dec 2023 22:58:01 +0900 Subject: [PATCH] cleanup --- .vscode/settings.json | 5 +- Cargo.lock | 179 --------------------- Cargo.toml | 3 +- crunch64-cli/.gitignore | 1 + crunch64-cli/Cargo.lock | 251 ++++++++++++++++++++++++++++++ crunch64-cli/Cargo.toml | 15 ++ {src => crunch64-cli/src}/main.rs | 47 +++++- src/lib.rs | 18 ++- src/utils.rs | 21 ++- src/yay0.rs | 40 ++--- src/yaz0.rs | 29 ++-- 11 files changed, 382 insertions(+), 227 deletions(-) create mode 100644 crunch64-cli/.gitignore create mode 100644 crunch64-cli/Cargo.lock create mode 100644 crunch64-cli/Cargo.toml rename {src => crunch64-cli/src}/main.rs (51%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 23fd35f..f313523 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,6 @@ { - "editor.formatOnSave": true + "editor.formatOnSave": true, + "rust-analyzer.linkedProjects": [ + "./crunch64-cli/Cargo.toml" + ] } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2b86917..ffd0c4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,54 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "anstream" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" - -[[package]] -name = "anstyle-parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" -dependencies = [ - "anstyle", - "windows-sys", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -71,57 +23,10 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "clap" -version = "4.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "crunch64" version = "0.1.0" dependencies = [ - "clap", "rstest", "thiserror", ] @@ -227,12 +132,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "memchr" version = "2.6.4" @@ -357,12 +256,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "syn" version = "2.0.39" @@ -399,75 +292,3 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index bca1d75..2bb51bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,7 @@ repository = "https://github.com/ethteck/crunch64" license = "MIT" [dependencies] -clap = { version = "4.4.11", features = ["derive"] } thiserror = "1.0" [dev-dependencies] -rstest = "0.18.2" \ No newline at end of file +rstest = "0.18.2" diff --git a/crunch64-cli/.gitignore b/crunch64-cli/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/crunch64-cli/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/crunch64-cli/Cargo.lock b/crunch64-cli/Cargo.lock new file mode 100644 index 0000000..806330a --- /dev/null +++ b/crunch64-cli/Cargo.lock @@ -0,0 +1,251 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a318f1f38d2418400f8209655bfd825785afd25aa30bb7ba6cc792e4596748" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "crunch64" +version = "0.1.0" +dependencies = [ + "thiserror", +] + +[[package]] +name = "crunch64-cli" +version = "0.1.0" +dependencies = [ + "clap", + "crunch64", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/crunch64-cli/Cargo.toml b/crunch64-cli/Cargo.toml new file mode 100644 index 0000000..e5ed05b --- /dev/null +++ b/crunch64-cli/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "crunch64-cli" +version = "0.1.0" +edition = "2021" +description = "A utility for compressing/decompressing files with common n64 formats" +repository = "https://github.com/ethteck/crunch64" +license = "MIT" + +[[bin]] +name = "crunch64" +path = "src/main.rs" + +[dependencies] +crunch64 = { path = ".." } +clap = { version = "4.4.11", features = ["derive"] } \ No newline at end of file diff --git a/src/main.rs b/crunch64-cli/src/main.rs similarity index 51% rename from src/main.rs rename to crunch64-cli/src/main.rs index e79617c..fee64ad 100644 --- a/src/main.rs +++ b/crunch64-cli/src/main.rs @@ -1,14 +1,24 @@ -use clap::Parser; -use crunch64::Crunch64Error; +use clap::{error::ErrorKind, CommandFactory, Parser, ValueEnum}; +use crunch64::{CompressionType, Crunch64Error}; use std::{ fs::File, io::{BufReader, BufWriter, Read, Write}, path::PathBuf, }; +#[derive(ValueEnum, Copy, Clone, Debug, PartialEq, Eq)] +enum Command { + Compress, + Decompress, +} + #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { + #[arg()] + command: Command, + #[arg()] + format: String, #[arg()] in_path: String, #[arg()] @@ -26,16 +36,37 @@ fn main() { } }; - let file_magic: &[u8] = &file_bytes[0..4]; - - let out_bytes = match file_magic { - b"Yay0" => crunch64::CompressionType::Yay0.decompress(file_bytes.as_slice()), - b"Yaz0" => crunch64::CompressionType::Yaz0.decompress(file_bytes.as_slice()), + let compression_format = match args.format.as_str() { + "Yay0" | "yay0" => CompressionType::Yay0, + "Yaz0" | "yaz0" => CompressionType::Yaz0, + "Mio0" | "mio0" => CompressionType::Mio0, _ => { - panic!("File format not recognized - magic: {:?}", file_magic) + let mut cmd = Args::command(); + cmd.error( + ErrorKind::InvalidValue, + format!("File format {} not supported", args.format), + ) + .exit() } }; + let out_bytes = match args.command { + Command::Compress => match compression_format.compress(file_bytes.as_slice()) { + Ok(bytes) => bytes, + Err(error) => { + println!("{:?}", error); + return; + } + }, + Command::Decompress => match compression_format.decompress(file_bytes.as_slice()) { + Ok(bytes) => bytes, + Err(error) => { + println!("{:?}", error); + return; + } + }, + }; + let mut buf_writer = match File::create(args.out_path) { Ok(file) => BufWriter::new(file), Err(_error) => { diff --git a/src/lib.rs b/src/lib.rs index 591c74b..7321f86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,16 @@ pub enum Crunch64Error { ReadFile, #[error("Failed to write file")] WriteFile, + #[error("File does not begin with Yay0 bytes")] + InvalidYay0Header, + #[error("File does not begin with Yaz0 bytes")] + InvalidYaz0Header, + #[error("File does not begin with Mio0 bytes")] + InvalidMio0Header, + #[error("Unsupported compression type")] + UnsupportedCompressionType, + #[error("Unaligned read")] + UnalignedRead, } #[repr(u8)] @@ -26,19 +36,19 @@ pub enum CompressionType { } impl CompressionType { - pub fn decompress(self: CompressionType, bytes: &[u8]) -> Box<[u8]> { + pub fn decompress(self: CompressionType, bytes: &[u8]) -> Result, Crunch64Error> { match self { CompressionType::Yay0 => decompress_yay0(bytes), CompressionType::Yaz0 => decompress_yaz0(bytes), - _ => panic!("Unsupported compression type: {:?}", self), + _ => Err(Crunch64Error::UnsupportedCompressionType), } } - pub fn compress(self: CompressionType, bytes: &[u8]) -> Box<[u8]> { + pub fn compress(self: CompressionType, bytes: &[u8]) -> Result, Crunch64Error> { match self { CompressionType::Yay0 => compress_yay0(bytes), CompressionType::Yaz0 => compress_yaz0(bytes), - _ => panic!("Unsupported compression type: {:?}", self), + _ => Err(Crunch64Error::UnsupportedCompressionType), } } } diff --git a/src/utils.rs b/src/utils.rs index 39d5b54..86cc36a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,11 +1,25 @@ use std::cmp; -pub fn read_u32(bytes: &[u8], offset: usize) -> u32 { +use crate::Crunch64Error; + +pub fn read_u16(bytes: &[u8], offset: usize) -> Result { + if offset % 2 != 0 { + return Err(Crunch64Error::UnalignedRead); + } + + Ok(u16::from_be_bytes( + bytes[offset..offset + 2].try_into().unwrap(), + )) +} + +pub fn read_u32(bytes: &[u8], offset: usize) -> Result { if offset % 4 != 0 { - panic!("Unaligned offset"); + return Err(Crunch64Error::UnalignedRead); } - u32::from_be_bytes(bytes[offset..offset + 4].try_into().unwrap()) + Ok(u32::from_be_bytes( + bytes[offset..offset + 4].try_into().unwrap(), + )) } pub(crate) fn search( @@ -66,7 +80,6 @@ pub(crate) fn search( fn mischarsearch(pattern: &[u8], pattern_len: usize, data: &[u8], data_len: usize) -> usize { let mut skip_table = [0u16; 256]; let mut i: isize; - //let mut k: usize; let mut v6: isize; let mut j: isize; diff --git a/src/yay0.rs b/src/yay0.rs index d2f8680..19ef359 100644 --- a/src/yay0.rs +++ b/src/yay0.rs @@ -1,9 +1,13 @@ -use crate::utils; +use crate::{utils, Crunch64Error}; -pub fn decompress_yay0(bytes: &[u8]) -> Box<[u8]> { - let decompressed_size = u32::from_be_bytes(bytes[4..8].try_into().unwrap()); - let link_table_offset = u32::from_be_bytes(bytes[8..12].try_into().unwrap()); - let chunk_offset = u32::from_be_bytes(bytes[12..16].try_into().unwrap()); +pub fn decompress_yay0(bytes: &[u8]) -> Result, Crunch64Error> { + if &bytes[0..4] != b"Yay0" { + return Err(Crunch64Error::InvalidYay0Header); + } + + let decompressed_size = utils::read_u32(bytes, 4).unwrap(); + let link_table_offset = utils::read_u32(bytes, 8).unwrap(); + let chunk_offset = utils::read_u32(bytes, 12).unwrap(); let mut link_table_idx = link_table_offset as usize; let mut chunk_idx = chunk_offset as usize; @@ -19,7 +23,7 @@ pub fn decompress_yay0(bytes: &[u8]) -> Box<[u8]> { while idx < decompressed_size as usize { // If we're out of bits, get the next mask if mask_bit_counter == 0 { - current_mask = u32::from_be_bytes(bytes[other_idx..other_idx + 4].try_into().unwrap()); + current_mask = utils::read_u32(bytes, other_idx).unwrap(); other_idx += 4; mask_bit_counter = 32; } @@ -29,11 +33,7 @@ pub fn decompress_yay0(bytes: &[u8]) -> Box<[u8]> { idx += 1; chunk_idx += 1; } else { - let link = u16::from_be_bytes( - bytes[link_table_idx..link_table_idx + 2] - .try_into() - .unwrap(), - ); + let link = utils::read_u16(bytes, link_table_idx).unwrap(); link_table_idx += 2; let offset = idx as isize - (link as isize & 0xFFF); @@ -58,10 +58,10 @@ pub fn decompress_yay0(bytes: &[u8]) -> Box<[u8]> { mask_bit_counter -= 1; } - ret.into_boxed_slice() + Ok(ret.into_boxed_slice()) } -pub fn compress_yay0(bytes: &[u8]) -> Box<[u8]> { +pub fn compress_yay0(bytes: &[u8]) -> Result, Crunch64Error> { let input_size = bytes.len(); let mut output: Vec = vec![]; @@ -177,7 +177,7 @@ pub fn compress_yay0(bytes: &[u8]) -> Box<[u8]> { output.extend(&def); - output.into_boxed_slice() + Ok(output.into_boxed_slice()) } #[cfg(test)] @@ -211,7 +211,7 @@ mod tests { let compressed_file = &read_test_file(path.clone()); let decompressed_file = &read_test_file(path.with_extension("")); - let decompressed: Box<[u8]> = super::decompress_yay0(compressed_file); + let decompressed: Box<[u8]> = super::decompress_yay0(compressed_file).unwrap(); assert_eq!(decompressed_file, decompressed.as_ref()); } @@ -220,7 +220,7 @@ mod tests { let compressed_file = &read_test_file(path.clone()); let decompressed_file = &read_test_file(path.with_extension("")); - let compressed = super::compress_yay0(decompressed_file.as_slice()); + let compressed = super::compress_yay0(decompressed_file.as_slice()).unwrap(); assert_eq!(compressed_file, compressed.as_ref()); } @@ -230,7 +230,9 @@ mod tests { assert_eq!( decompressed_file, - super::decompress_yay0(&super::compress_yay0(decompressed_file.as_ref())).as_ref() + super::decompress_yay0(&super::compress_yay0(decompressed_file.as_ref()).unwrap()) + .unwrap() + .as_ref() ); } @@ -240,7 +242,9 @@ mod tests { assert_eq!( compressed_file, - super::compress_yay0(&super::decompress_yay0(compressed_file.as_ref())).as_ref() + super::compress_yay0(&super::decompress_yay0(compressed_file.as_ref()).unwrap()) + .unwrap() + .as_ref() ); } } diff --git a/src/yaz0.rs b/src/yaz0.rs index 5a8d4b8..8c0a56a 100644 --- a/src/yaz0.rs +++ b/src/yaz0.rs @@ -1,17 +1,20 @@ // Based on https://gist.github.com/Mr-Wiseguy/6cca110d74b32b5bb19b76cfa2d7ab4f -use crate::utils::{self}; +use crate::{ + utils::{self}, + Crunch64Error, +}; -pub fn decompress_yaz0(bytes: &[u8]) -> Box<[u8]> { +pub fn decompress_yaz0(bytes: &[u8]) -> Result, Crunch64Error> { if &bytes[0..4] != b"Yaz0" { - panic!("not Yaz0 data"); + return Err(Crunch64Error::InvalidYaz0Header); } // Skip the header let mut index_src = 0x10; let mut index_dst = 0; - let uncompressed_size = utils::read_u32(bytes, 4) as usize; + let uncompressed_size = utils::read_u32(bytes, 4).unwrap() as usize; let mut ret = vec![0u8; uncompressed_size]; while index_src < bytes.len() { @@ -57,14 +60,14 @@ pub fn decompress_yaz0(bytes: &[u8]) -> Box<[u8]> { } } - ret.into_boxed_slice() + Ok(ret.into_boxed_slice()) } fn divide_round_up(a: usize, b: usize) -> usize { (a + b - 1) / b } -pub fn compress_yaz0(bytes: &[u8]) -> Box<[u8]> { +pub fn compress_yaz0(bytes: &[u8]) -> Result, Crunch64Error> { let input_size = bytes.len(); // Worst-case size for output is zero compression on the input, meaning the input size plus the number of layout bytes plus the Yaz0 header. // There would be one layout byte for every 8 input bytes, so the worst-case size is: @@ -173,7 +176,7 @@ pub fn compress_yaz0(bytes: &[u8]) -> Box<[u8]> { } } - output.into_boxed_slice() + Ok(output.into_boxed_slice()) } #[cfg(test)] @@ -207,7 +210,7 @@ mod tests { let compressed_file = &read_test_file(path.clone()); let decompressed_file = &read_test_file(path.with_extension("")); - let decompressed: Box<[u8]> = super::decompress_yaz0(compressed_file); + let decompressed: Box<[u8]> = super::decompress_yaz0(compressed_file).unwrap(); assert_eq!(decompressed_file, decompressed.as_ref()); } @@ -216,7 +219,7 @@ mod tests { let compressed_file = &read_test_file(path.clone()); let decompressed_file = &read_test_file(path.with_extension("")); - let compressed = super::compress_yaz0(decompressed_file.as_slice()); + let compressed = super::compress_yaz0(decompressed_file.as_slice()).unwrap(); assert_eq!(compressed_file, compressed.as_ref()); } @@ -226,7 +229,9 @@ mod tests { assert_eq!( decompressed_file, - super::decompress_yaz0(&super::compress_yaz0(decompressed_file.as_ref())).as_ref() + super::decompress_yaz0(&super::compress_yaz0(decompressed_file.as_ref()).unwrap()) + .unwrap() + .as_ref() ); } @@ -236,7 +241,9 @@ mod tests { assert_eq!( compressed_file, - super::compress_yaz0(&super::decompress_yaz0(compressed_file.as_ref())).as_ref() + super::compress_yaz0(&super::decompress_yaz0(compressed_file.as_ref()).unwrap()) + .unwrap() + .as_ref() ); } }