diff --git a/hugr-core/Cargo.toml b/hugr-core/Cargo.toml index e7284ebca..1596cc39c 100644 --- a/hugr-core/Cargo.toml +++ b/hugr-core/Cargo.toml @@ -54,9 +54,6 @@ strum = { workspace = true } strum_macros = { workspace = true } semver = { version = "1.0.23", features = ["serde"] } hugr-model = { version = "0.16.0", path = "../hugr-model", optional = true } -indexmap.workspace = true -fxhash.workspace = true -bumpalo = { workspace = true, features = ["collections"] } [dev-dependencies] rstest = { workspace = true } diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs index 645a7a0e6..86979ce5c 100644 --- a/hugr-core/src/export.rs +++ b/hugr-core/src/export.rs @@ -11,9 +11,7 @@ use crate::{ }, Direction, Hugr, HugrView, IncomingPort, Node, Port, }; -use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump}; -use fxhash::FxHashMap; -use hugr_model::v0::{self as model}; +use hugr_model::v0::{self as model, fxhash::FxHashMap, bumpalo::{Bump, collections::{Vec as BumpVec, String as BumpString}}}; use std::fmt::Write; pub(crate) const OP_FUNC_CALL_INDIRECT: &str = "func.call-indirect"; @@ -1148,7 +1146,7 @@ mod test { #[rstest] #[case(test_simple_circuit())] fn test_export(#[case] hugr: Hugr) { - use bumpalo::Bump; + use hugr_model::v0::bumpalo::Bump; let bump = Bump::new(); let _model = super::export_hugr(&hugr, &bump); } diff --git a/hugr-core/src/import.rs b/hugr-core/src/import.rs index f542ac695..ea39871f2 100644 --- a/hugr-core/src/import.rs +++ b/hugr-core/src/import.rs @@ -22,8 +22,7 @@ use crate::{ }, Direction, Hugr, HugrView, Node, Port, }; -use fxhash::FxHashMap; -use hugr_model::v0::{self as model}; +use hugr_model::v0::{self as model, fxhash::FxHashMap}; use itertools::Either; use smol_str::{SmolStr, ToSmolStr}; use thiserror::Error; diff --git a/hugr-core/tests/model.rs b/hugr-core/tests/model.rs index ea5b69b22..ae3a41312 100644 --- a/hugr-core/tests/model.rs +++ b/hugr-core/tests/model.rs @@ -5,7 +5,7 @@ use hugr_core::{export::export_hugr, import::import_hugr}; use hugr_model::v0 as model; fn roundtrip(source: &str) -> String { - let bump = bumpalo::Bump::new(); + let bump = model::bumpalo::Bump::new(); let parsed_model = model::text::parse(source, &bump).unwrap(); let imported_hugr = import_hugr(&parsed_model.module, &std_reg()).unwrap(); let exported_model = export_hugr(&imported_hugr, &bump); diff --git a/hugr-model/Cargo.toml b/hugr-model/Cargo.toml index d1e3636b9..d8ff51f84 100644 --- a/hugr-model/Cargo.toml +++ b/hugr-model/Cargo.toml @@ -19,7 +19,7 @@ bench = false base64 = { workspace = true } bumpalo = { workspace = true, features = ["collections"] } capnp = "0.20.1" -derive_more = { version = "1.0.0", features = ["display"] } +derive_more = { version = "1.0.0", features = ["display", "from", "error"] } fxhash.workspace = true indexmap.workspace = true pest = "2.7.12" diff --git a/hugr-model/src/v0/binary/mod.rs b/hugr-model/src/v0/binary/mod.rs index 816c64fb2..eb74c59c2 100644 --- a/hugr-model/src/v0/binary/mod.rs +++ b/hugr-model/src/v0/binary/mod.rs @@ -2,5 +2,5 @@ mod read; mod write; -pub use read::read_from_slice; -pub use write::write_to_vec; +pub use read::{read_from_reader, read_from_slice, ReadError}; +pub use write::{write_to_vec, write_to_writer, WriteError}; diff --git a/hugr-model/src/v0/binary/read.rs b/hugr-model/src/v0/binary/read.rs index 8f0c9a50d..85f177f25 100644 --- a/hugr-model/src/v0/binary/read.rs +++ b/hugr-model/src/v0/binary/read.rs @@ -1,14 +1,30 @@ +use std::io::BufRead; + use crate::hugr_v0_capnp as hugr_capnp; use crate::v0 as model; use bumpalo::collections::Vec as BumpVec; use bumpalo::Bump; -type ReadResult = Result; +/// TODO docs +#[derive(Debug, derive_more::From, derive_more::Display, derive_more::Error)] +#[non_exhaustive] +pub enum ReadError { + #[from(forward)] + /// TODO docs + EncodingError(capnp::Error), +} + +type ReadResult = Result; /// Read a hugr module from a byte slice. pub fn read_from_slice<'a>(slice: &[u8], bump: &'a Bump) -> ReadResult> { + read_from_reader(slice, bump) +} + +/// Read a hugr module from an impl of [BufRead]. +pub fn read_from_reader(reader: impl BufRead, bump: &Bump) -> ReadResult> { let reader = - capnp::serialize_packed::read_message(slice, capnp::message::ReaderOptions::new())?; + capnp::serialize_packed::read_message(reader, capnp::message::ReaderOptions::new())?; let root = reader.get_root::()?; read_module(bump, root) } diff --git a/hugr-model/src/v0/binary/write.rs b/hugr-model/src/v0/binary/write.rs index 74dc763ab..296313214 100644 --- a/hugr-model/src/v0/binary/write.rs +++ b/hugr-model/src/v0/binary/write.rs @@ -1,6 +1,16 @@ +use std::io::Write; + use crate::hugr_v0_capnp as hugr_capnp; use crate::v0 as model; +/// TODO docs +#[derive(Debug, derive_more::From, derive_more::Display, derive_more::Error)] +#[non_exhaustive] +pub enum WriteError { + /// TODO docs + EncodingError(capnp::Error), +} + /// Write a list of items into a list builder. macro_rules! write_list { ($builder:expr, $init:ident, $write:expr, $list:expr) => { @@ -11,6 +21,15 @@ macro_rules! write_list { }; } +/// Writes a module to an impl of [Write]. +pub fn write_to_writer(module: &model::Module, writer: impl Write) -> Result<(), WriteError> { + let mut message = capnp::message::Builder::new_default(); + let builder = message.init_root(); + write_module(builder, module); + + Ok(capnp::serialize_packed::write_message(writer, &message)?) +} + /// Writes a module to a byte vector. pub fn write_to_vec(module: &model::Module) -> Vec { let mut message = capnp::message::Builder::new_default(); diff --git a/hugr-model/src/v0/mod.rs b/hugr-model/src/v0/mod.rs index 32d79f7dc..aca89db8c 100644 --- a/hugr-model/src/v0/mod.rs +++ b/hugr-model/src/v0/mod.rs @@ -123,6 +123,10 @@ pub mod binary; pub mod scope; pub mod text; +pub use bumpalo; +pub use fxhash; +pub use indexmap; + macro_rules! define_index { ($(#[$meta:meta])* $vis:vis struct $name:ident(pub u32);) => { #[repr(transparent)] diff --git a/hugr-model/src/v0/text/parse.rs b/hugr-model/src/v0/text/parse.rs index 40692b67e..d7f8c6df6 100644 --- a/hugr-model/src/v0/text/parse.rs +++ b/hugr-model/src/v0/text/parse.rs @@ -1,6 +1,4 @@ use base64::{prelude::BASE64_STANDARD, Engine}; -use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump}; -use fxhash::FxHashMap; use pest::{ iterators::{Pair, Pairs}, Parser, RuleType, @@ -8,10 +6,12 @@ use pest::{ use thiserror::Error; use crate::v0::{ + fxhash::FxHashMap, + bumpalo::{Bump, collections::{Vec as BumpVec, String as BumpString}}, scope::{LinkTable, SymbolTable, UnknownSymbolError, VarTable}, - AliasDecl, ConstructorDecl, ExtSetPart, FuncDecl, LinkIndex, ListPart, Module, Node, NodeId, - Operation, OperationDecl, Param, ParamSort, Region, RegionId, RegionKind, RegionScope, - ScopeClosure, Term, TermId, + AliasDecl, ConstructorDecl, ExtSetPart, FuncDecl, LinkIndex, + ListPart, Module, Node, NodeId, Operation, OperationDecl, Param, ParamSort, Region, RegionId, + RegionKind, RegionScope, ScopeClosure, Term, TermId, }; mod pest_parser { diff --git a/hugr-model/tests/binary.rs b/hugr-model/tests/binary.rs index 6120abb60..18ab842e0 100644 --- a/hugr-model/tests/binary.rs +++ b/hugr-model/tests/binary.rs @@ -1,7 +1,7 @@ #![allow(missing_docs)] -use bumpalo::Bump; use hugr_model::v0 as model; +use model::bumpalo::Bump; use pretty_assertions::assert_eq; /// Reads a module from a string, serializes it to binary, and then deserializes it back to a module. diff --git a/hugr-model/tests/text.rs b/hugr-model/tests/text.rs index 7139acf64..45c6adc54 100644 --- a/hugr-model/tests/text.rs +++ b/hugr-model/tests/text.rs @@ -3,7 +3,7 @@ use hugr_model::v0 as model; fn roundtrip(source: &str) -> String { - let bump = bumpalo::Bump::new(); + let bump = model::bumpalo::Bump::new(); let parsed_model = model::text::parse(source, &bump).unwrap(); model::text::print_to_string(&parsed_model.module, 80).unwrap() }