use clap::Parser;
use clap_verbosity_flag::{InfoLevel, Verbosity};
use clio::Input;
use derive_more::{Display, Error, From};
use hugr::extension::ExtensionRegistry;
use hugr::package::PackageValidationError;
use hugr::Hugr;
use std::{ffi::OsString, path::PathBuf};
pub mod extensions;
pub mod mermaid;
pub mod validate;
#[doc(inline)]
#[deprecated(since = "0.13.2", note = "Use `hugr::package::Package` instead.")]
pub use hugr::package::Package;
#[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, Display, Error, From)]
#[non_exhaustive]
pub enum CliError {
#[display("Error reading from path: {_0}")]
InputFile(std::io::Error),
#[display("Error parsing package: {_0}")]
Parse(serde_json::Error),
#[display("Error validating HUGR: {_0}")]
Validate(PackageValidationError),
}
#[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, PartialEq)]
pub enum PackageOrHugr {
Package(Package),
Hugr(Hugr),
}
impl PackageOrHugr {
pub fn into_hugrs(self) -> Vec<Hugr> {
match self {
PackageOrHugr::Package(pkg) => pkg.modules,
PackageOrHugr::Hugr(hugr) => vec![hugr],
}
}
pub fn update_validate(
&mut self,
reg: &mut ExtensionRegistry,
) -> Result<(), PackageValidationError> {
match self {
PackageOrHugr::Package(pkg) => pkg.update_validate(reg),
PackageOrHugr::Hugr(hugr) => hugr.update_validate(reg).map_err(Into::into),
}
}
}
impl AsRef<[Hugr]> for PackageOrHugr {
fn as_ref(&self) -> &[Hugr] {
match self {
PackageOrHugr::Package(pkg) => &pkg.modules,
PackageOrHugr::Hugr(hugr) => std::slice::from_ref(hugr),
}
}
}
impl HugrArgs {
pub fn get_package_or_hugr(&mut self) -> Result<PackageOrHugr, CliError> {
let val: serde_json::Value = serde_json::from_reader(&mut self.input)?;
if let Ok(hugr) = serde_json::from_value::<Hugr>(val.clone()) {
return Ok(PackageOrHugr::Hugr(hugr));
}
let pkg = serde_json::from_value::<Package>(val.clone())?;
Ok(PackageOrHugr::Package(pkg))
}
#[deprecated(
since = "0.13.2",
note = "Use `HugrArgs::get_package_or_hugr` instead."
)]
pub fn get_package(&mut self) -> Result<Package, CliError> {
let val: serde_json::Value = serde_json::from_reader(&mut self.input)?;
let pkg = serde_json::from_value::<Package>(val.clone())?;
Ok(pkg)
}
}