use std::{
fs::{read, write},
num::NonZeroUsize,
path::PathBuf,
process::ExitCode,
thread::available_parallelism,
};
use clap::Parser;
use ttf2woff2::{BrotliQuality, EncodeOptions, encode_with_options};
#[derive(Parser)]
#[command(about, version)]
struct Args {
input: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(short, long, default_value = "9")]
quality: u8,
#[arg(short, long, default_value = "1")]
threads: usize,
}
fn main() -> ExitCode {
let args = Args::parse();
let output = args.output.unwrap_or_else(|| args.input.with_extension("woff2"));
let quality = BrotliQuality::from(args.quality);
let threads = match args.threads {
0 => available_parallelism().ok(),
1 => None,
n => NonZeroUsize::new(n),
};
let options = EncodeOptions { quality, threads, ..EncodeOptions::default() };
let ttf_data = match read(&args.input) {
Ok(data) => data,
Err(e) => {
eprintln!("Error reading {}: {e}", args.input.display());
return ExitCode::FAILURE;
}
};
let woff2_data = match encode_with_options(&ttf_data, options) {
Ok(data) => data,
Err(e) => {
eprintln!("Error encoding: {e}");
return ExitCode::FAILURE;
}
};
if let Err(e) = write(&output, &woff2_data) {
eprintln!("Error writing {}: {e}", output.display());
return ExitCode::FAILURE;
}
let compression = (1.0 - woff2_data.len() as f64 / ttf_data.len() as f64) * 100.0;
println!(
"{} -> {} ({} -> {} bytes, {compression:.1}% compression)",
args.input.display(),
output.display(),
ttf_data.len(),
woff2_data.len()
);
ExitCode::SUCCESS
}