Added LZ77 decompression, added corresponding CLI command

This commit is contained in:
2025-04-03 23:06:56 -04:00
parent c2169f84c4
commit e1190e1e58
6 changed files with 166 additions and 25 deletions

View File

@@ -0,0 +1,51 @@
// archive/lz77.rs from rustii (c) 2025 NinjaCheetah & Contributors
// https://github.com/NinjaCheetah/rustii
//
// Code for the LZ77 compression/decompression commands in the rustii CLI.
use std::{str, fs};
use std::path::{Path, PathBuf};
use anyhow::{bail, Context, Result};
use clap::Subcommand;
use rustii::archive::lz77;
#[derive(Subcommand)]
#[command(arg_required_else_help = true)]
pub enum Commands {
/// Compress a file with LZ77 compression (NOT IMPLEMENTED)
Compress {
/// The path to the file to compress
input: String,
/// An optional output name; defaults to <input name>.lz77
#[arg(short, long)]
output: Option<String>,
},
/// Decompress an LZ77-compressed file
Decompress {
/// The path to the file to decompress
input: String,
/// An optional output name; defaults to <input name>.out
#[arg(short, long)]
output: Option<String>,
}
}
pub fn compress_lz77(_input: &str, _output: &Option<String>) -> Result<()> {
bail!("compression is not yet implemented");
}
pub fn decompress_lz77(input: &str, output: &Option<String>) -> Result<()> {
let in_path = Path::new(input);
if !in_path.exists() {
bail!("Compressed file \"{}\" could not be found.", in_path.display());
}
let compressed = fs::read(in_path)?;
let decompressed = lz77::decompress_lz77(&compressed).with_context(|| "An unknown error occurred while decompressing the data.")?;
let out_path = if output.is_some() {
PathBuf::from(output.clone().unwrap())
} else {
PathBuf::from(in_path).with_extension("out")
};
fs::write(out_path, decompressed)?;
Ok(())
}

View File

@@ -0,0 +1,4 @@
// archive/mod.rs from rustii (c) 2025 NinjaCheetah & Contributors
// https://github.com/NinjaCheetah/rustii
pub mod lz77;

View File

@@ -3,13 +3,13 @@
//
// Base for the rustii CLI that handles argument parsing and directs execution to the proper module.
mod archive;
mod title;
mod filetypes;
mod info;
use anyhow::Result;
use clap::{Subcommand, Parser};
use title::{wad, fakesign};
#[derive(Parser)]
#[command(version, about, long_about = None)]
@@ -21,11 +21,6 @@ struct Cli {
#[derive(Subcommand)]
#[command(arg_required_else_help = true)]
enum Commands {
/// Pack/unpack/edit a WAD file
Wad {
#[command(subcommand)]
command: Option<wad::Commands>,
},
/// Fakesign a TMD, Ticket, or WAD (trucha bug)
Fakesign {
/// The path to a TMD, Ticket, or WAD
@@ -38,34 +33,53 @@ enum Commands {
Info {
/// The path to a TMD, Ticket, or WAD
input: String,
}
},
/// Compress/decompress data using LZ77 compression
Lz77 {
#[command(subcommand)]
command: archive::lz77::Commands
},
/// Pack/unpack/edit a WAD file
Wad {
#[command(subcommand)]
command: title::wad::Commands,
},
}
fn main() -> Result<()> {
let cli = Cli::parse();
match &cli.command {
Some(Commands::Wad { command }) => {
match command {
Some(wad::Commands::Convert { input, target, output }) => {
wad::convert_wad(input, target, output)?
},
Some(wad::Commands::Pack { input, output}) => {
wad::pack_wad(input, output)?
},
Some(wad::Commands::Unpack { input, output }) => {
wad::unpack_wad(input, output)?
},
&None => { /* This is for me handled by clap */}
}
},
Some(Commands::Fakesign { input, output }) => {
fakesign::fakesign(input, output)?
title::fakesign::fakesign(input, output)?
},
Some(Commands::Lz77 { command }) => {
match command {
archive::lz77::Commands::Compress { input, output } => {
archive::lz77::compress_lz77(input, output)?
},
archive::lz77::Commands::Decompress { input, output } => {
archive::lz77::decompress_lz77(input, output)?
}
}
},
Some(Commands::Info { input }) => {
info::info(input)?
}
None => {}
},
Some(Commands::Wad { command }) => {
match command {
title::wad::Commands::Convert { input, target, output } => {
title::wad::convert_wad(input, target, output)?
},
title::wad::Commands::Pack { input, output} => {
title::wad::pack_wad(input, output)?
},
title::wad::Commands::Unpack { input, output } => {
title::wad::unpack_wad(input, output)?
}
}
},
None => { /* Clap handles no passed command by itself */}
}
Ok(())
}

View File

@@ -18,7 +18,7 @@ pub enum Commands {
Convert {
/// The path to the WAD to convert
input: String,
/// An (optional) WAD name; defaults to <input name>_<new type>.wad
/// An optional WAD name; defaults to <input name>_<new type>.wad
#[arg(short, long)]
output: Option<String>,
#[command(flatten)]