#[allow(unreachable_code)]
fn main() {
#[cfg(feature = "cli")]
{
return cli::extract(clap::Parser::parse()).unwrap();
}
println!(env!("CARGO_PKG_VERSION"))
}
#[cfg(feature = "cli")]
mod cli {
use bytes::Buf;
use clap::Parser;
use oozextract::{Extractor, OozError};
use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;
#[derive(Parser)]
#[command(version, about, long_about = None)]
pub struct Args {
file: PathBuf,
#[arg(short, long, value_name = "FILE")]
output: Option<PathBuf>,
#[arg(long, value_name = "FILE")]
verify: Option<PathBuf>,
#[arg(long)]
stdout: bool,
#[arg(long, value_name = "BYTES")]
length: Option<usize>,
#[arg(long, value_name = "BYTES")]
header: Option<usize>,
#[arg(short, long)]
verbose: bool,
}
#[cfg(feature = "cli")]
pub fn extract(
Args {
file,
length,
header,
output,
verify,
stdout,
verbose,
}: Args,
) -> Result<(), OozError> {
let mut input = if let Some(len) = length {
Vec::with_capacity(len)
} else {
Vec::new()
};
File::open(file)?.read_to_end(&mut input)?;
let mut input = input.as_slice();
if verbose {
println!("Read {} bytes", input.len());
}
let len = if let Some(length) = length {
if let Some(header) = header {
input = &input[header..];
}
length
} else if input[4] == 0x8C {
if verbose {
println!("Oodle header found at position 4, using bytes 0..3 as length header");
}
input.get_u32_le() as usize
} else {
if verbose {
println!("Oodle header not found at position 4, Assuming 8-byte length header");
}
input.get_u64_le() as usize
};
if verbose {
println!("Expected output: {} bytes", len);
}
let mut extracted = vec![0; len];
let actual_len = Extractor::new().read_from_slice(input, &mut extracted)?;
if verbose {
println!("Extracted {} bytes", actual_len);
}
if let Some(output) = output {
if verbose {
if let Some(outfile) = output.as_os_str().to_str() {
println!("Writing to {}", outfile)
}
}
File::create(output)?.write_all(&extracted)?;
}
if let Some(verify) = verify {
if verbose {
if let Some(filename) = verify.as_os_str().to_str() {
println!("Comparing to {}", filename)
}
}
let mut verify = File::open(verify)?;
assert_eq!(verify.metadata()?.len() as usize, extracted.len());
let mut expect = Vec::with_capacity(extracted.len());
verify.read_to_end(&mut expect)?;
for (i, (actual, expected)) in extracted.iter().zip(expect.iter()).enumerate() {
assert_eq!(actual, expected, "bad data at byte {}", i);
}
if verbose {
println!("Verified {} bytes", expect.len());
}
}
if stdout {
println!("{}", std::str::from_utf8(&extracted).unwrap());
}
Ok(())
}
}