1use anyhow::Result;
3use clap::Parser;
4use clio::Output;
5use hugr::envelope::{EnvelopeConfig, EnvelopeFormat, ZstdConfig};
6
7use crate::CliError;
8use crate::hugr_io::HugrInputArgs;
9
10#[derive(Parser, Debug)]
12#[clap(version = "1.0", long_about = None)]
13#[clap(about = "Convert a HUGR between different envelope formats.")]
14#[group(id = "hugr")]
15#[non_exhaustive]
16pub struct ConvertArgs {
17 #[command(flatten)]
19 pub input_args: HugrInputArgs,
20
21 #[clap(short, long, value_parser, default_value = "-")]
23 pub output: Output,
24
25 #[clap(short, long, value_name = "FORMAT")]
27 pub format: Option<String>,
28
29 #[clap(long, conflicts_with_all = ["format", "binary"])]
32 pub text: bool,
33
34 #[clap(long, conflicts_with_all = ["format", "text"])]
37 pub binary: bool,
38
39 #[clap(long)]
41 pub compress: bool,
42
43 #[clap(long, value_name = "LEVEL", requires = "compress")]
46 pub compression_level: Option<u8>,
47}
48
49impl ConvertArgs {
50 pub fn run_convert(&mut self) -> Result<()> {
52 let (env_config, package) = self.input_args.get_envelope()?;
53
54 let mut config = if self.text {
56 EnvelopeConfig::text()
57 } else if self.binary {
58 EnvelopeConfig::binary()
59 } else {
60 let format = match &self.format {
62 Some(fmt) => match fmt.as_str() {
63 "json" => EnvelopeFormat::PackageJson,
64 "model" => EnvelopeFormat::Model,
65 "model-exts" => EnvelopeFormat::ModelWithExtensions,
66 "model-text" => EnvelopeFormat::ModelText,
67 "model-text-exts" => EnvelopeFormat::ModelTextWithExtensions,
68 _ => Err(CliError::InvalidFormat(fmt.clone()))?,
69 },
70 None => env_config.format, };
72 EnvelopeConfig::new(format)
73 };
74
75 if let Some(level) = self.compress.then_some(self.compression_level).flatten() {
77 config = config.with_zstd(ZstdConfig::new(level));
78 }
79
80 hugr::envelope::write_envelope(&mut self.output, &package, config)?;
82
83 Ok(())
84 }
85}