use clap::Parser;
use clap_verbosity_flag::{InfoLevel, Verbosity};
use clio::Input;
use hugr_core::{Extension, Hugr};
use std::{ffi::OsString, path::PathBuf};
use thiserror::Error;
pub mod extensions;
pub mod mermaid;
pub mod validate;
#[derive(Parser, Debug)]
#[clap(version = "1.0", long_about = None)]
#[clap(about = "HUGR CLI tools.")]
#[group(id = "hugr")]
#[non_exhaustive]
pub enum CliArgs {
Validate(validate::ValArgs),
GenExtensions(extensions::ExtArgs),
Mermaid(mermaid::MermaidArgs),
#[command(external_subcommand)]
External(Vec<OsString>),
}
#[derive(Debug, Error)]
#[error(transparent)]
#[non_exhaustive]
pub enum CliError {
#[error("Error reading from path: {0}")]
InputFile(#[from] std::io::Error),
#[error("Error parsing input: {0}")]
Parse(#[from] serde_json::Error),
Validate(#[from] validate::ValError),
}
#[derive(Parser, Debug)]
pub struct HugrArgs {
#[clap(value_parser, default_value = "-")]
pub input: Input,
#[command(flatten)]
pub verbose: Verbosity<InfoLevel>,
#[arg(
long,
help = "Don't use standard extensions when validating. Prelude is still used."
)]
pub no_std: bool,
#[arg(
short,
long,
help = "Paths to serialised extensions to validate against."
)]
pub extensions: Vec<PathBuf>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Package {
pub modules: Vec<Hugr>,
pub extensions: Vec<Extension>,
}
impl Package {
pub fn new(modules: Vec<Hugr>, extensions: Vec<Extension>) -> Self {
Self {
modules,
extensions,
}
}
}
impl HugrArgs {
pub fn get_package(&mut self) -> Result<Package, CliError> {
let val: serde_json::Value = serde_json::from_reader(&mut self.input)?;
if let Ok(p) = serde_json::from_value::<Package>(val.clone()) {
Ok(p)
} else {
let hugr: Hugr = serde_json::from_value(val)?;
Ok(Package::new(vec![hugr], vec![]))
}
}
}