use std::env;
use std::fs::{self, File};
use std::io::{BufWriter, Write};
use std::path::Path;
use std::process;
use openusd::{Error, Result, sdf};
const USAGE: &str = "usage: cargo run -p openusd --example convert -- [--from <id>] [--to <id>] <input> <output>";
fn main() -> Result<()> {
let mut arguments = env::args().skip(1);
let mut paths = Vec::new();
let mut from = None;
let mut to = None;
let mut malformed = false;
while let Some(argument) = arguments.next() {
match argument.as_str() {
"--from" => {
from = arguments.next();
malformed |= from.is_none();
}
"--to" => {
to = arguments.next();
malformed |= to.is_none();
}
_ => paths.push(argument),
}
}
if malformed {
eprintln!("{USAGE}");
process::exit(2);
}
let [input, output] = paths.as_slice() else {
eprintln!("{USAGE}");
process::exit(2);
};
let opened;
let forced;
let data: &dyn sdf::AbstractData = match &from {
None => {
opened = sdf::Layer::open(input)?;
opened.data()
}
Some(id) => {
forced = format_named(id)?.read_bytes(fs::read(input)?.into(), input)?;
&*forced
}
};
let target = match &to {
Some(id) => format_named(id)?,
None => format_claiming(output)?,
};
if !target.caps().can_write() {
return Err(Error::UnsupportedFormat(target.format_id().to_string()));
}
let mut sink = BufWriter::new(File::create(output)?);
target.write(data, &mut sink)?;
sink.flush()?;
println!("{input} -> {output} ({})", target.format_id());
Ok(())
}
fn format_named(id: &str) -> Result<&'static dyn sdf::FileFormat> {
sdf::LayerRegistry::find_by_id(id).ok_or_else(|| Error::UnsupportedFormat(id.to_owned()))
}
fn format_claiming(path: &str) -> Result<&'static dyn sdf::FileFormat> {
Path::new(path)
.extension()
.and_then(|extension| extension.to_str())
.and_then(sdf::LayerRegistry::find_by_extension)
.ok_or_else(|| Error::UnsupportedFormat(path.to_owned()))
}