Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions hugr-cli/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub struct ConvertArgs {
impl ConvertArgs {
/// Convert a HUGR between different envelope formats
pub fn run_convert(&mut self) -> Result<()> {
let (env_config, package) = self.input_args.get_envelope()?;
let (env_config, package) = self.input_args.get_described_package()?;

// Handle text and binary format flags, which override the format option
let mut config = if self.text {
Expand All @@ -67,7 +67,7 @@ impl ConvertArgs {
"model-text-exts" => EnvelopeFormat::ModelTextWithExtensions,
_ => Err(CliError::InvalidFormat(fmt.clone()))?,
},
None => env_config.format, // Use input format if not specified
None => env_config.header.config().format, // Use input format if not specified
};
EnvelopeConfig::new(format)
};
Expand Down
26 changes: 19 additions & 7 deletions hugr-cli/src/hugr_io.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Input/output arguments for the HUGR CLI.

use clio::Input;
use hugr::envelope::{EnvelopeConfig, EnvelopeError, read_envelope};
use hugr::envelope::description::PackageDesc;
use hugr::envelope::{EnvelopeConfig, read_described_envelope};
use hugr::extension::ExtensionRegistry;
use hugr::package::Package;
use hugr::{Extension, Hugr};
Expand Down Expand Up @@ -29,7 +30,7 @@ pub struct HugrInputArgs {
short,
long,
help_heading = "Input",
help = "Paths to serialised extensions to validate against."
help = "Paths to additional serialised extensions needed to load the Hugr."
)]
pub extensions: Vec<PathBuf>,
/// Read the input as a HUGR JSON file instead of an envelope.
Expand All @@ -48,7 +49,7 @@ impl HugrInputArgs {
/// If [`HugrInputArgs::hugr_json`] is `true`, [`HugrInputArgs::get_hugr`] should be called instead as
/// reading the input as a package will fail.
pub fn get_package(&mut self) -> Result<Package, CliError> {
self.get_envelope().map(|(_, package)| package)
self.get_described_package().map(|(_, package)| package)
}

/// Read a hugr envelope from the input and return the envelope
Expand All @@ -58,13 +59,24 @@ impl HugrInputArgs {
///
/// If [`HugrInputArgs::hugr_json`] is `true`, [`HugrInputArgs::get_hugr`] should be called instead as
/// reading the input as a package will fail.
#[deprecated(since = "0.24.1", note = "Use get_described_envelope instead")]
pub fn get_envelope(&mut self) -> Result<(EnvelopeConfig, Package), CliError> {
let (desc, package) = self.get_described_package()?;
Ok((desc.header.config(), package))
}

/// Read a hugr envelope from the input and return the envelope
/// description and the decoded package.
///
/// # Errors
///
/// If [`HugrInputArgs::hugr_json`] is `true`, [`HugrInputArgs::get_hugr`] should be called instead as
/// reading the input as a package will fail.
pub fn get_described_package(&mut self) -> Result<(PackageDesc, Package), CliError> {
let extensions = self.load_extensions()?;
let buffer = BufReader::new(&mut self.input);
read_envelope(buffer, &extensions).map_err(|e| match e {
EnvelopeError::MagicNumber { .. } => CliError::NotAnEnvelope,
_ => CliError::Envelope(e),
})

Ok(read_described_envelope(buffer, &extensions)?)
}
/// Read a hugr JSON file from the input.
///
Expand Down
3 changes: 3 additions & 0 deletions hugr-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ pub enum CliError {
/// The generator of the HUGR.
generator: Box<String>,
},
#[error("Error reading envelope.")]
/// Errors produced when reading an envelope.
ReadEnvelope(#[from] hugr::envelope::ReadError),
}

impl CliError {
Expand Down
5 changes: 2 additions & 3 deletions hugr-cli/src/mermaid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ impl MermaidArgs {

/// Write the mermaid diagram for a HUGR envelope.
pub fn run_print_envelope(&mut self) -> Result<()> {
let package = self.input_args.get_package()?;
let generator = hugr::envelope::get_generator(&package.modules);

let (desc, package) = self.input_args.get_described_package()?;
let generator = desc.generator();
if self.validate {
package
.validate()
Expand Down
5 changes: 3 additions & 2 deletions hugr-cli/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ impl ValArgs {
if self.input_args.hugr_json {
#[allow(deprecated)]
let hugr = self.input_args.get_hugr()?;
#[allow(deprecated)]
let generator = hugr::envelope::get_generator(&[&hugr]);

hugr.validate()
.map_err(PackageValidationError::Validation)
.map_err(|val_err| CliError::validation(generator, val_err))?;
} else {
let package = self.input_args.get_package()?;
let generator = hugr::envelope::get_generator(&package.modules);
let (desc, package) = self.input_args.get_described_package()?;
let generator = desc.generator();
package
.validate()
.map_err(|val_err| CliError::validation(generator, val_err))?;
Expand Down
27 changes: 18 additions & 9 deletions hugr-cli/tests/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use assert_cmd::Command;
use assert_fs::{NamedTempFile, fixture::FileWriteStr};
use hugr::builder::{DataflowSubContainer, ModuleBuilder};
use hugr::envelope::{EnvelopeConfig, EnvelopeFormat, read_envelope};
use hugr::envelope::{EnvelopeConfig, EnvelopeFormat, read_described_envelope};
use hugr::package::Package;
use hugr::types::Type;
use hugr::{
Expand Down Expand Up @@ -77,7 +77,9 @@ fn test_convert_to_json(test_envelope_file: NamedTempFile, mut convert_cmd: Comm
let output_content = std::fs::read(output_file.path()).expect("Failed to read output file");
let reader = BufReader::new(output_content.as_slice());
let registry = ExtensionRegistry::default();
let (config, _) = read_envelope(reader, &registry).expect("Failed to read output envelope");
let (desc, _) =
read_described_envelope(reader, &registry).expect("Failed to read output envelope");
let config = desc.header.config();

// Verify the format is correct
assert_eq!(config.format, EnvelopeFormat::PackageJson);
Expand All @@ -102,8 +104,9 @@ fn test_convert_to_model(test_envelope_file: NamedTempFile, mut convert_cmd: Com
let output_content = std::fs::read(output_file.path()).expect("Failed to read output file");
let reader = BufReader::new(output_content.as_slice());
let registry = ExtensionRegistry::default();
let (config, _) = read_envelope(reader, &registry).expect("Failed to read output envelope");

let (desc, _) =
read_described_envelope(reader, &registry).expect("Failed to read output envelope");
let config = desc.header.config();
// Verify the format is correct
assert_eq!(config.format, EnvelopeFormat::Model);
}
Expand Down Expand Up @@ -174,7 +177,9 @@ fn test_convert_model_text_format(test_envelope_file: NamedTempFile, mut convert
let output_content = std::fs::read(output_file.path()).expect("Failed to read output file");
let reader = BufReader::new(output_content.as_slice());
let registry = ExtensionRegistry::default();
let (config, _) = read_envelope(reader, &registry).expect("Failed to read output envelope");
let (desc, _) =
read_described_envelope(reader, &registry).expect("Failed to read output envelope");
let config = desc.header.config();

// Verify the format is correct
assert_eq!(config.format, EnvelopeFormat::ModelText);
Expand All @@ -192,14 +197,14 @@ fn test_format_roundtrip(test_package: Package) {
let config_model = EnvelopeConfig::new(EnvelopeFormat::Model);
let reader = BufReader::new(json_data.as_slice());
let registry = ExtensionRegistry::default();
let (_, package) = read_envelope(reader, &registry).unwrap();
let (_, package) = read_described_envelope(reader, &registry).unwrap();

let mut model_data = Vec::new();
hugr::envelope::write_envelope(&mut model_data, &package, config_model).unwrap();

// Convert back to JSON
let reader = BufReader::new(model_data.as_slice());
let (_, package_back) = read_envelope(reader, &registry).unwrap();
let (_, package_back) = read_described_envelope(reader, &registry).unwrap();

// Package should be the same after roundtrip conversion
assert_eq!(test_package, package_back);
Expand All @@ -215,7 +220,9 @@ fn test_convert_text_flag(test_envelope_text: (String, Package), mut convert_cmd

let reader = BufReader::new(stdout.as_slice());
let registry = ExtensionRegistry::default();
let (config, _) = read_envelope(reader, &registry).expect("Failed to read output envelope");
let (desc, _) =
read_described_envelope(reader, &registry).expect("Failed to read output envelope");
let config = desc.header.config();

// Verify it's a text-based format
assert!(config.format.ascii_printable());
Expand All @@ -231,7 +238,9 @@ fn test_convert_binary_flag(test_envelope_text: (String, Package), mut convert_c

let reader = BufReader::new(stdout.as_slice());
let registry = ExtensionRegistry::default();
let (config, _) = read_envelope(reader, &registry).expect("Failed to read output envelope");
let (desc, _) =
read_described_envelope(reader, &registry).expect("Failed to read output envelope");
let config = desc.header.config();

// Verify it's a binary format (not ASCII printable)
assert!(!config.format.ascii_printable());
Expand Down
2 changes: 1 addition & 1 deletion hugr-cli/tests/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ fn test_bad_json(mut val_cmd: Command) {
val_cmd
.assert()
.failure()
.stderr(contains("Error decoding HUGR envelope"))
.stderr(contains("Error reading package payload in envelope"))
.stderr(contains("missing field"));
}

Expand Down
Loading
Loading