one-rust/one-rust/examples/onear.rs

99 lines
2.7 KiB
Rust

#[macro_use] extern crate argh;
extern crate binread;
extern crate one_rust;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
use binread::prelude::*;
use one_rust::JodOne;
/// Unpack .one archives from NiGHTS: Journey of Dreams
#[derive(FromArgs)]
struct Args {
#[argh(subcommand)]
action: Action,
}
#[derive(FromArgs)]
#[argh(subcommand)]
enum Action {
ExtractFile(ExtractFile),
CreateFile(CreateFile),
DescribeFile(DescribeFile),
}
/// Unpack and decompress the files inside a .one archive.
#[derive(FromArgs)]
#[argh(subcommand, name = "xf")]
struct ExtractFile {
/// path to the .one file
#[argh(positional)]
file: PathBuf,
}
/// Describe the metadata of a .one archive.
#[derive(FromArgs)]
#[argh(subcommand, name = "tf")]
struct DescribeFile {
/// path to the .one file
#[argh(positional)]
file: PathBuf,
}
/// Create a .one archive from the given files.
#[derive(FromArgs)]
#[argh(subcommand, name = "cf")]
struct CreateFile {
/// path of the .one file to create
#[argh(positional)]
file: PathBuf,
/// paths of the files to pack into the archive
#[argh(positional)]
contents: Vec<PathBuf>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Args = argh::from_env();
match args.action {
Action::ExtractFile(subcmd) => {
let mut infile = File::open(&subcmd.file)?;
let archive: JodOne = infile.read_le()?;
let entries = archive.unpack();
let dir = PathBuf::from(format!("{}.d", subcmd.file.to_string_lossy()));
for (name, data) in entries {
let full_path = dir.join(name);
if let Some(path) = full_path.parent() {
std::fs::create_dir_all(path)?;
}
File::create(full_path)?.write_all(&data)?;
}
}
Action::DescribeFile(subcmd) => {
let mut infile = File::open(&subcmd.file)?;
let archive: JodOne = infile.read_le()?;
println!("{:?}", archive);
for entry in archive.entries {
println!("{:?}", entry);
}
}
Action::CreateFile(subcmd) => {
if subcmd.file.exists() {
return Err(format!("{:?} already exists, refusing to overwrite", subcmd.file).into());
}
let mut entries = Vec::new();
for path in subcmd.contents {
let mut data = Vec::new();
File::open(&path)?.read_to_end(&mut data)?;
entries.push((path, data));
}
let archive = JodOne::pack(entries, None);
let outfile = File::create(&subcmd.file)?;
archive.write(outfile)?;
}
}
Ok(())
}