use clio::Input;
use hugr::envelope::description::PackageDesc;
use hugr::envelope::read_envelope;
use hugr::extension::ExtensionRegistry;
use hugr::extension::resolution::WeakExtensionRegistry;
use hugr::package::Package;
use hugr::{Extension, Hugr};
use std::io::{BufReader, Read};
use std::path::PathBuf;
use crate::CliError;
#[derive(Debug, clap::Args)]
pub struct HugrInputArgs {
#[arg(value_parser, default_value = "-", help_heading = "Input")]
pub input: Input,
#[arg(
long,
help_heading = "Input",
help = "Don't use standard extensions when validating hugrs. Prelude is still used."
)]
pub no_std: bool,
#[arg(
short,
long,
help_heading = "Input",
help = "Paths to additional serialised extensions needed to load the Hugr."
)]
pub extensions: Vec<PathBuf>,
}
impl HugrInputArgs {
pub fn get_package(&mut self) -> Result<Package, CliError> {
self.get_described_package().map(|(_, package)| package)
}
pub fn get_described_package(&mut self) -> Result<(PackageDesc, Package), CliError> {
self.get_described_package_with_reader::<&[u8]>(None)
}
pub fn get_described_package_with_reader<R: Read>(
&mut self,
reader: Option<R>,
) -> Result<(PackageDesc, Package), CliError> {
let extensions = self.load_extensions()?;
match reader {
Some(r) => {
let buffer = BufReader::new(r);
Ok(read_envelope(buffer, &extensions)?)
}
None => {
let buffer = BufReader::new(&mut self.input);
Ok(read_envelope(buffer, &extensions)?)
}
}
}
#[deprecated(since = "0.27.0")]
pub(crate) fn get_hugr_with_reader<R: Read>(
&mut self,
reader: Option<R>,
) -> Result<Hugr, CliError> {
let extensions = self.load_extensions()?;
const PREPEND: &str = r#"HUGRiHJv?@{"modules": ["#;
const APPEND: &str = r#"],"extensions": []}"#;
let mut envelope = PREPEND.to_string();
match reader {
Some(r) => {
let mut buffer = BufReader::new(r);
buffer.read_to_string(&mut envelope)?;
}
None => {
let mut buffer = BufReader::new(&mut self.input);
buffer.read_to_string(&mut envelope)?;
}
}
envelope.push_str(APPEND);
let hugr = Hugr::load_str(envelope, Some(&extensions))?;
Ok(hugr)
}
pub fn load_extensions(&self) -> Result<ExtensionRegistry, CliError> {
let mut reg = if self.no_std {
hugr::extension::PRELUDE_REGISTRY.to_owned()
} else {
hugr::std_extensions::STD_REG.to_owned()
};
let mut extensions: Vec<Extension> = Vec::with_capacity(self.extensions.len());
for ext in &self.extensions {
let f = std::fs::File::open(ext)?;
let ext: Extension = serde_json::from_reader(f)?;
extensions.push(ext);
}
let extra_extensions = ExtensionRegistry::new_with_extension_resolution(
extensions,
&WeakExtensionRegistry::from(®),
)?;
reg.extend(extra_extensions);
Ok(reg)
}
}