1use clio::Input;
4use hugr::envelope::{EnvelopeConfig, EnvelopeError, read_envelope};
5use hugr::extension::ExtensionRegistry;
6use hugr::package::Package;
7use hugr::{Extension, Hugr};
8use std::io::{BufReader, Read};
9use std::path::PathBuf;
10
11use crate::CliError;
12
13#[derive(Debug, clap::Args)]
15pub struct HugrInputArgs {
16 #[arg(value_parser, default_value = "-", help_heading = "Input")]
18 pub input: Input,
19
20 #[arg(
22 long,
23 help_heading = "Input",
24 help = "Don't use standard extensions when validating hugrs. Prelude is still used."
25 )]
26 pub no_std: bool,
27 #[arg(
29 short,
30 long,
31 help_heading = "Input",
32 help = "Paths to serialised extensions to validate against."
33 )]
34 pub extensions: Vec<PathBuf>,
35 #[clap(long, help_heading = "Input")]
39 pub hugr_json: bool,
40}
41
42impl HugrInputArgs {
43 pub fn get_package(&mut self) -> Result<Package, CliError> {
51 self.get_envelope().map(|(_, package)| package)
52 }
53
54 pub fn get_envelope(&mut self) -> Result<(EnvelopeConfig, Package), CliError> {
62 let extensions = self.load_extensions()?;
63 let buffer = BufReader::new(&mut self.input);
64 read_envelope(buffer, &extensions).map_err(|e| match e {
65 EnvelopeError::MagicNumber { .. } => CliError::NotAnEnvelope,
66 _ => CliError::Envelope(e),
67 })
68 }
69 #[deprecated(note = "Use `HugrInputArgs::get_package` instead.", since = "0.22.2")]
76 pub fn get_hugr(&mut self) -> Result<Hugr, CliError> {
77 let extensions = self.load_extensions()?;
78 let mut buffer = BufReader::new(&mut self.input);
79
80 const PREPEND: &str = r#"HUGRiHJv?@{"modules": ["#;
82 const APPEND: &str = r#"],"extensions": []}"#;
83
84 let mut envelope = PREPEND.to_string();
85 buffer.read_to_string(&mut envelope)?;
86 envelope.push_str(APPEND);
87
88 let hugr = Hugr::load_str(envelope, Some(&extensions))?;
89 Ok(hugr)
90 }
91
92 pub fn load_extensions(&self) -> Result<ExtensionRegistry, CliError> {
97 let mut reg = if self.no_std {
98 hugr::extension::PRELUDE_REGISTRY.to_owned()
99 } else {
100 hugr::std_extensions::STD_REG.to_owned()
101 };
102
103 for ext in &self.extensions {
104 let f = std::fs::File::open(ext)?;
105 let ext: Extension = serde_json::from_reader(f)?;
106 reg.register_updated(ext);
107 }
108
109 Ok(reg)
110 }
111}