hugr_core/envelope/
package_json.rs1use derive_more::{Display, Error, From};
3use itertools::Itertools;
4use std::io;
5
6use super::WithGenerator;
7use crate::extension::ExtensionRegistry;
8use crate::extension::resolution::ExtensionResolutionError;
9use crate::package::Package;
10use crate::{Extension, Hugr};
11
12pub(super) fn from_json_reader(
16 reader: impl io::Read,
17 extension_registry: &ExtensionRegistry,
18) -> Result<Package, PackageEncodingError> {
19 let val: serde_json::Value = serde_json::from_reader(reader)?;
20
21 let PackageDeser {
22 modules,
23 extensions: pkg_extensions,
24 } = serde_json::from_value::<PackageDeser>(val.clone())?;
25 let mut modules = modules.into_iter().map(|h| h.0).collect_vec();
26 let pkg_extensions = ExtensionRegistry::new_with_extension_resolution(
27 pkg_extensions,
28 &extension_registry.into(),
29 )
30 .map_err(|err| WithGenerator::new(err, &modules))?;
31
32 let mut combined_registry = extension_registry.clone();
34 combined_registry.extend(&pkg_extensions);
35
36 modules
37 .iter_mut()
38 .try_for_each(|module| module.resolve_extension_defs(&combined_registry))
39 .map_err(|err| WithGenerator::new(err, &modules))?;
40
41 Ok(Package {
42 modules,
43 extensions: pkg_extensions,
44 })
45}
46
47pub(super) fn to_json_writer<'h>(
49 hugrs: impl IntoIterator<Item = &'h Hugr>,
50 extensions: &ExtensionRegistry,
51 writer: impl io::Write,
52) -> Result<(), PackageEncodingError> {
53 let pkg_ser = PackageSer {
54 modules: hugrs.into_iter().map(HugrSer).collect(),
55 extensions: extensions.iter().map(std::convert::AsRef::as_ref).collect(),
56 };
57
58 #[cfg(all(test, not(miri)))]
63 if std::env::var("HUGR_TEST_SCHEMA").is_ok_and(|x| !x.is_empty()) {
64 use crate::hugr::serialize::test::check_hugr_serialization_schema;
65
66 for hugr in &pkg_ser.modules {
67 check_hugr_serialization_schema(hugr.0);
68 }
69 }
70
71 serde_json::to_writer(writer, &pkg_ser)?;
72 Ok(())
73}
74
75#[derive(Debug, Display, Error, From)]
77#[non_exhaustive]
78#[display("Error reading or writing a package in JSON format.")]
79pub enum PackageEncodingError {
80 JsonEncoding(#[from] serde_json::Error),
82 IOError(#[from] io::Error),
84 ExtensionResolution(#[from] WithGenerator<ExtensionResolutionError>),
86}
87
88#[derive(Debug, serde::Serialize)]
93struct PackageSer<'h> {
94 pub modules: Vec<HugrSer<'h>>,
95 pub extensions: Vec<&'h Extension>,
96}
97#[derive(Debug, serde::Serialize)]
98#[serde(transparent)]
99struct HugrSer<'h>(#[serde(serialize_with = "Hugr::serde_serialize")] pub &'h Hugr);
100
101#[derive(Debug, serde::Deserialize)]
106struct PackageDeser {
107 pub modules: Vec<HugrDeser>,
108 pub extensions: Vec<Extension>,
109}
110#[derive(Debug, serde::Deserialize)]
111#[serde(transparent)]
112struct HugrDeser(#[serde(deserialize_with = "Hugr::serde_deserialize")] pub Hugr);