use std::path::PathBuf;
use std::process::ExitCode;
use fhir::codegen::{self, Version};
struct Options {
version: Version,
out: PathBuf,
}
fn main() -> ExitCode {
let args: Vec<String> = std::env::args().skip(1).collect();
let options = match parse_args(&args) {
Ok(options) => options,
Err(message) => {
eprintln!("{message}\n\n{USAGE}");
return ExitCode::FAILURE;
}
};
println!("Generating {} into {}", options.version.label(), options.out.display());
match codegen::generate_into(options.version, &options.out) {
Ok(summary) => {
println!("{summary}");
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("generation failed: {e}");
ExitCode::FAILURE
}
}
}
const USAGE: &str = "\
Usage: cargo run -- <release> [--out <dir>]
<release> r3, r4, or r5
--out <dir> where to write the model (default: src/<release>)
R5 has no default output directory: the shipped src/r5 modules carry
hand-written documentation that regeneration would overwrite, so an explicit
--out is required for it.";
fn parse_args(args: &[String]) -> Result<Options, String> {
let mut version = None;
let mut out = None;
let mut rest = args.iter();
while let Some(arg) = rest.next() {
match arg.as_str() {
"--out" => {
let dir = rest.next().ok_or("--out needs a directory")?;
out = Some(PathBuf::from(dir));
}
"-h" | "--help" => return Err("Showing usage.".to_string()),
other => {
version = Some(
Version::parse(other).ok_or_else(|| format!("unknown release {other:?}"))?,
);
}
}
}
let version = version.ok_or("no release given")?;
let out = match (out, version) {
(Some(dir), _) => dir,
(None, Version::R5) => {
return Err(
"refusing to regenerate over src/r5, which is hand-documented; \
pass --out to write elsewhere"
.to_string(),
)
}
(None, _) => version.source_dir(),
};
Ok(Options { version, out })
}