hugr_core/envelope/
package_json.rs

1#![allow(deprecated)] // remove when WithGenerator is removed, cannot place on enum
2
3//! Encoding / decoding of Package json, used in the `PackageJson` envelope format.
4use derive_more::{Display, Error, From};
5use std::io;
6
7use crate::extension::ExtensionRegistry;
8use crate::extension::resolution::ExtensionResolutionError;
9
10use crate::{Extension, Hugr};
11
12/// Write the Package in json format into an io writer.
13pub(super) fn to_json_writer<'h>(
14    hugrs: impl IntoIterator<Item = &'h Hugr>,
15    extensions: &ExtensionRegistry,
16    writer: impl io::Write,
17) -> Result<(), PackageEncodingError> {
18    let pkg_ser = PackageSer {
19        modules: hugrs.into_iter().map(HugrSer).collect(),
20        extensions: extensions.iter().map(std::convert::AsRef::as_ref).collect(),
21    };
22
23    // Validate the hugr serializations against the schema.
24    //
25    // NOTE: The schema definition is currently broken, so this check always succeeds.
26    // See <https://github.com/CQCL/hugr/issues/2401>
27    #[cfg(all(test, not(miri)))]
28    if std::env::var("HUGR_TEST_SCHEMA").is_ok_and(|x| !x.is_empty()) {
29        use crate::hugr::serialize::test::check_hugr_serialization_schema;
30
31        for hugr in &pkg_ser.modules {
32            check_hugr_serialization_schema(hugr.0);
33        }
34    }
35
36    serde_json::to_writer(writer, &pkg_ser)?;
37    Ok(())
38}
39
40/// Error raised while loading a package.
41#[derive(Debug, Display, Error, From)]
42#[non_exhaustive]
43#[display("Error reading or writing a package in JSON format.")]
44pub enum PackageEncodingError {
45    /// Error raised while parsing the package json.
46    JsonEncoding(#[from] serde_json::Error),
47    /// Error raised while reading from a file.
48    IOError(#[from] io::Error),
49    /// Could not resolve the extension needed to encode the hugr.
50    ExtensionResolution(#[from] super::WithGenerator<ExtensionResolutionError>),
51    /// Error resolving packaged extensions.
52    PackagedExtension(#[from] ExtensionResolutionError),
53}
54
55/// A private package structure implementing the serde traits.
56///
57/// We use this to avoid exposing a public implementation of Serialize/Deserialize,
58/// as the json definition is not stable, and should always be wrapped in an Envelope.
59#[derive(Debug, serde::Serialize)]
60struct PackageSer<'h> {
61    pub modules: Vec<HugrSer<'h>>,
62    pub extensions: Vec<&'h Extension>,
63}
64#[derive(Debug, serde::Serialize)]
65#[serde(transparent)]
66struct HugrSer<'h>(#[serde(serialize_with = "Hugr::serde_serialize")] pub &'h Hugr);
67
68/// A private package structure implementing the serde traits.
69///
70/// We use this to avoid exposing a public implementation of Serialize/Deserialize,
71/// as the json definition is not stable, and should always be wrapped in an Envelope.
72#[derive(Debug, serde::Deserialize)]
73pub(super) struct PackageDeser {
74    pub modules: Vec<HugrDeser>,
75    pub extensions: Vec<Extension>,
76}
77#[derive(Debug, serde::Deserialize)]
78#[serde(transparent)]
79pub(super) struct HugrDeser(#[serde(deserialize_with = "Hugr::serde_deserialize")] pub Hugr);