mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
More consistent document crate names (#4323)
* More consistent document crate names * Fix fmt * Fix ASCII art diagrams * rename document-graph to document-graph-storage
This commit is contained in:
34
Cargo.lock
generated
34
Cargo.lock
generated
@@ -1298,9 +1298,9 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"core-types",
|
"core-types",
|
||||||
"document-container",
|
"document-container",
|
||||||
|
"document-graph-storage",
|
||||||
"futures",
|
"futures",
|
||||||
"graph-craft",
|
"graph-craft",
|
||||||
"graph-storage",
|
|
||||||
"graphene-resource",
|
"graphene-resource",
|
||||||
"log",
|
"log",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
@@ -1310,6 +1310,21 @@ dependencies = [
|
|||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "document-graph-storage"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"blake3",
|
||||||
|
"core-types",
|
||||||
|
"graph-craft",
|
||||||
|
"graphene-resource",
|
||||||
|
"rmp-serde",
|
||||||
|
"rustc-hash 2.1.1",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.18",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "downcast-rs"
|
name = "downcast-rs"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@@ -2015,21 +2030,6 @@ dependencies = [
|
|||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "graph-storage"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"blake3",
|
|
||||||
"core-types",
|
|
||||||
"graph-craft",
|
|
||||||
"graphene-resource",
|
|
||||||
"rmp-serde",
|
|
||||||
"rustc-hash 2.1.1",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror 2.0.18",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "graphene-application-io"
|
name = "graphene-application-io"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -2334,12 +2334,12 @@ dependencies = [
|
|||||||
"derivative",
|
"derivative",
|
||||||
"document-container",
|
"document-container",
|
||||||
"document-format",
|
"document-format",
|
||||||
|
"document-graph-storage",
|
||||||
"dyn-any",
|
"dyn-any",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"glam",
|
"glam",
|
||||||
"graph-craft",
|
"graph-craft",
|
||||||
"graph-storage",
|
|
||||||
"graphene-hash",
|
"graphene-hash",
|
||||||
"graphene-std",
|
"graphene-std",
|
||||||
"graphite-proc-macros",
|
"graphite-proc-macros",
|
||||||
|
|||||||
@@ -2,15 +2,15 @@
|
|||||||
members = [
|
members = [
|
||||||
"desktop",
|
"desktop",
|
||||||
"desktop/wrapper",
|
"desktop/wrapper",
|
||||||
|
"desktop/ui",
|
||||||
"desktop/embedded-resources",
|
"desktop/embedded-resources",
|
||||||
"desktop/bundle",
|
"desktop/bundle",
|
||||||
"desktop/platform/linux",
|
"desktop/platform/linux",
|
||||||
"desktop/platform/mac",
|
"desktop/platform/mac",
|
||||||
"desktop/platform/win",
|
"desktop/platform/win",
|
||||||
"desktop/ui",
|
"document/format",
|
||||||
"document/graph-storage",
|
"document/graph-storage",
|
||||||
"document/container",
|
"document/container",
|
||||||
"document/document-format",
|
|
||||||
"editor",
|
"editor",
|
||||||
"frontend/wrapper",
|
"frontend/wrapper",
|
||||||
"libraries/dyn-any",
|
"libraries/dyn-any",
|
||||||
@@ -92,8 +92,8 @@ repeat-nodes = { path = "node-graph/nodes/repeat" }
|
|||||||
math-nodes = { path = "node-graph/nodes/math" }
|
math-nodes = { path = "node-graph/nodes/math" }
|
||||||
path-bool-nodes = { path = "node-graph/nodes/path-bool" }
|
path-bool-nodes = { path = "node-graph/nodes/path-bool" }
|
||||||
graph-craft = { path = "node-graph/graph-craft" }
|
graph-craft = { path = "node-graph/graph-craft" }
|
||||||
graph-storage = { path = "document/graph-storage", default-features = false }
|
document-format = { path = "document/format" }
|
||||||
document-format = { path = "document/document-format" }
|
document-graph-storage = { path = "document/graph-storage", default-features = false }
|
||||||
document-container = { path = "document/container" }
|
document-container = { path = "document/container" }
|
||||||
raster-nodes = { path = "node-graph/nodes/raster" }
|
raster-nodes = { path = "node-graph/nodes/raster" }
|
||||||
graphene-std = { path = "node-graph/nodes/gstd" }
|
graphene-std = { path = "node-graph/nodes/gstd" }
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "document-format"
|
name = "document-format"
|
||||||
description = "Typed handle for the .gdd document format, sitting over graph-storage and document-container"
|
description = "Typed handle for the .gdd document format, sitting over document-graph-storage and document-container"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Runtime bridge: the editor↔storage conversion methods (stage/commit from a `NodeNetwork`,
|
# Runtime bridge: the editor <-> storage conversion methods (stage/commit from a `NodeNetwork`,
|
||||||
# `network_ids`, `declarations`). Off lets a standalone migration tool build without `graph-craft`
|
# `network_ids`, `declarations`). Off lets a standalone migration tool build without `graph-craft`
|
||||||
# or `core-types`. Forwards to `graph-storage/conversion`.
|
# or `core-types`. Forwards to `document-graph-storage/conversion`.
|
||||||
conversion = ["graph-storage/conversion", "dep:graph-craft", "dep:core-types"]
|
conversion = ["document-graph-storage/conversion", "dep:graph-craft", "dep:core-types"]
|
||||||
# Compressed-archive export/open. Each forwards to the matching `document-container` feature and
|
# Compressed-archive export/open. Each forwards to the matching `document-container` feature and
|
||||||
# gates that format's `ExportFormat` arm and sink. The folder/memory codec-free core needs neither.
|
# gates that format's `ExportFormat` arm and sink. The folder/memory codec-free core needs neither.
|
||||||
zip = ["document-container/zip"]
|
zip = ["document-container/zip"]
|
||||||
@@ -19,7 +19,7 @@ default = ["conversion", "zip", "xz"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
document-container = { workspace = true }
|
document-container = { workspace = true }
|
||||||
graph-storage = { workspace = true, default-features = false }
|
document-graph-storage = { workspace = true, default-features = false }
|
||||||
graph-craft = { workspace = true, optional = true }
|
graph-craft = { workspace = true, optional = true }
|
||||||
graphene-resource = { workspace = true }
|
graphene-resource = { workspace = true }
|
||||||
core-types = { workspace = true, optional = true }
|
core-types = { workspace = true, optional = true }
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
use document_container::ContainerError;
|
use document_container::ContainerError;
|
||||||
#[cfg(feature = "conversion")]
|
#[cfg(feature = "conversion")]
|
||||||
use graph_storage::CommitError;
|
use document_graph_storage::CommitError;
|
||||||
use graph_storage::CrdtError;
|
use document_graph_storage::CrdtError;
|
||||||
use graphene_resource::ResourceHash;
|
use graphene_resource::ResourceHash;
|
||||||
|
|
||||||
use crate::codec::CodecError;
|
use crate::codec::CodecError;
|
||||||
@@ -162,7 +162,7 @@ impl<L: Layout> Gdd<L> {
|
|||||||
// below, so only the gap is loaded from the byte store here.
|
// below, so only the gap is loaded from the byte store here.
|
||||||
let mut export_session = self.session.clone();
|
let mut export_session = self.session.clone();
|
||||||
let mut hashes_from_store: Vec<ResourceHash> = Vec::new();
|
let mut hashes_from_store: Vec<ResourceHash> = Vec::new();
|
||||||
let mut links_to_promote: Vec<graph_storage::ResourceId> = Vec::new();
|
let mut links_to_promote: Vec<document_graph_storage::ResourceId> = Vec::new();
|
||||||
for (id, entry) in &export_session.registry().resources {
|
for (id, entry) in &export_session.registry().resources {
|
||||||
let Some(hash) = entry.hash else { continue };
|
let Some(hash) = entry.hash else { continue };
|
||||||
let embed = entry.has_embedded_source() || options.embed_all_resources;
|
let embed = entry.has_embedded_source() || options.embed_all_resources;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Typed handle for `.gdd` documents.
|
//! Typed handle for `.gdd` documents.
|
||||||
//!
|
//!
|
||||||
//! [`Gdd`] owns a [`graph_storage::Session`] plus a working-copy [`document_container::AnyContainer`].
|
//! [`Gdd`] owns a [`document_graph_storage::Session`] plus a working-copy [`document_container::AnyContainer`].
|
||||||
//! Mutations flow through `Gdd` to keep the session and the on-disk working copy mirrored.
|
//! Mutations flow through `Gdd` to keep the session and the on-disk working copy mirrored.
|
||||||
//! Export is a separate, explicit operation — see [`export::ExportFormat`].
|
//! Export is a separate, explicit operation — see [`export::ExportFormat`].
|
||||||
//!
|
//!
|
||||||
@@ -16,8 +16,8 @@ use std::path::Path;
|
|||||||
use document_container::backends::folder::FolderBackend;
|
use document_container::backends::folder::FolderBackend;
|
||||||
use document_container::{AnyContainer, AsyncContainer, ByteHolder, ContainerError};
|
use document_container::{AnyContainer, AsyncContainer, ByteHolder, ContainerError};
|
||||||
#[cfg(feature = "conversion")]
|
#[cfg(feature = "conversion")]
|
||||||
use graph_storage::{CommitError, NodeMetadataSource};
|
use document_graph_storage::{CommitError, NodeMetadataSource};
|
||||||
use graph_storage::{Delta, HotOp, PeerId, Registry, Session};
|
use document_graph_storage::{Delta, HotOp, PeerId, Registry, Session};
|
||||||
#[cfg(feature = "conversion")]
|
#[cfg(feature = "conversion")]
|
||||||
use graphene_resource::LoadResource;
|
use graphene_resource::LoadResource;
|
||||||
use graphene_resource::ResourceHash;
|
use graphene_resource::ResourceHash;
|
||||||
@@ -83,7 +83,7 @@ pub struct Gdd<L: Layout = GddV1Layout> {
|
|||||||
pub(crate) view_settings: std::collections::BTreeMap<String, serde_json::Value>,
|
pub(crate) view_settings: std::collections::BTreeMap<String, serde_json::Value>,
|
||||||
/// Per-network view settings (node-graph nav + previewing), keyed by stable [`NetworkId`]. Same per-peer
|
/// Per-network view settings (node-graph nav + previewing), keyed by stable [`NetworkId`]. Same per-peer
|
||||||
/// `session.json` treatment as [`view_settings`](Self::view_settings), but scoped per network.
|
/// `session.json` treatment as [`view_settings`](Self::view_settings), but scoped per network.
|
||||||
pub(crate) network_view_settings: std::collections::BTreeMap<graph_storage::NetworkId, std::collections::BTreeMap<String, serde_json::Value>>,
|
pub(crate) network_view_settings: std::collections::BTreeMap<document_graph_storage::NetworkId, std::collections::BTreeMap<String, serde_json::Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Native folder-backed convenience constructors. On wasm the editor builds an OPFS-backed
|
/// Native folder-backed convenience constructors. On wasm the editor builds an OPFS-backed
|
||||||
@@ -261,19 +261,19 @@ impl<L: Layout> Gdd<L> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The per-network view settings read from `session.json` (node-graph nav + previewing), keyed by
|
/// The per-network view settings read from `session.json` (node-graph nav + previewing), keyed by
|
||||||
/// [`NetworkId`](graph_storage::NetworkId). Opaque `ui::nav::*` / `ui::previewing` blobs the editor decodes.
|
/// [`NetworkId`](document_graph_storage::NetworkId). Opaque `ui::nav::*` / `ui::previewing` blobs the editor decodes.
|
||||||
pub fn network_view_settings(&self) -> &std::collections::BTreeMap<graph_storage::NetworkId, std::collections::BTreeMap<String, serde_json::Value>> {
|
pub fn network_view_settings(&self) -> &std::collections::BTreeMap<document_graph_storage::NetworkId, std::collections::BTreeMap<String, serde_json::Value>> {
|
||||||
&self.network_view_settings
|
&self.network_view_settings
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve each runtime `network_path` to its stable [`NetworkId`](graph_storage::NetworkId), so the
|
/// Resolve each runtime `network_path` to its stable [`NetworkId`](document_graph_storage::NetworkId), so the
|
||||||
/// editor can key per-network, per-peer view state by a stable id. See [`Session::network_ids`].
|
/// editor can key per-network, per-peer view state by a stable id. See [`Session::network_ids`].
|
||||||
#[cfg(feature = "conversion")]
|
#[cfg(feature = "conversion")]
|
||||||
pub fn network_ids<M: NodeMetadataSource>(
|
pub fn network_ids<M: NodeMetadataSource>(
|
||||||
&self,
|
&self,
|
||||||
network: &graph_craft::document::NodeNetwork,
|
network: &graph_craft::document::NodeNetwork,
|
||||||
metadata: &M,
|
metadata: &M,
|
||||||
) -> Result<std::collections::HashMap<Vec<core_types::uuid::NodeId>, graph_storage::NetworkId>, CommitError> {
|
) -> Result<std::collections::HashMap<Vec<core_types::uuid::NodeId>, document_graph_storage::NetworkId>, CommitError> {
|
||||||
self.session.network_ids(network, metadata)
|
self.session.network_ids(network, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,17 +292,17 @@ impl<L: Layout> Gdd<L> {
|
|||||||
(working, self.layout)
|
(working, self.layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve the proto-node declarations referenced by the registry into a [`graph_storage::Declarations`]
|
/// Resolve the proto-node declarations referenced by the registry into a [`document_graph_storage::Declarations`]
|
||||||
/// map, loading each `ProtoNode`'s bytes from `byte_store` (the global cache in the editor, the
|
/// map, loading each `ProtoNode`'s bytes from `byte_store` (the global cache in the editor, the
|
||||||
/// working-copy container for standalone). Only resources referenced by `Implementation::ProtoNode`
|
/// working-copy container for standalone). Only resources referenced by `Implementation::ProtoNode`
|
||||||
/// are visited, so image/font resources are skipped. Cold-path (open / `to_runtime`); async
|
/// are visited, so image/font resources are skipped. Cold-path (open / `to_runtime`); async
|
||||||
/// because resource loads are.
|
/// because resource loads are.
|
||||||
#[cfg(feature = "conversion")]
|
#[cfg(feature = "conversion")]
|
||||||
pub async fn declarations(&self, byte_store: &dyn LoadResource) -> graph_storage::Declarations {
|
pub async fn declarations(&self, byte_store: &dyn LoadResource) -> document_graph_storage::Declarations {
|
||||||
use graph_storage::Implementation;
|
use document_graph_storage::Implementation;
|
||||||
|
|
||||||
let registry = self.session.registry();
|
let registry = self.session.registry();
|
||||||
let mut declarations = graph_storage::Declarations::new();
|
let mut declarations = document_graph_storage::Declarations::new();
|
||||||
|
|
||||||
for node in registry.node_instances.values() {
|
for node in registry.node_instances.values() {
|
||||||
let Implementation::ProtoNode(id) = node.implementation() else { continue };
|
let Implementation::ProtoNode(id) = node.implementation() else { continue };
|
||||||
@@ -317,7 +317,7 @@ impl<L: Layout> Gdd<L> {
|
|||||||
log::error!("Declaration bytes for {id} (hash {hash}) missing from byte store");
|
log::error!("Declaration bytes for {id} (hash {hash}) missing from byte store");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
match graph_storage::decode_declaration(resource.as_ref()) {
|
match document_graph_storage::decode_declaration(resource.as_ref()) {
|
||||||
Ok(proto) => {
|
Ok(proto) => {
|
||||||
declarations.insert(*id, proto);
|
declarations.insert(*id, proto);
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
use document_container::AsyncContainer;
|
use document_container::AsyncContainer;
|
||||||
#[cfg(feature = "conversion")]
|
#[cfg(feature = "conversion")]
|
||||||
use graph_storage::NodeMetadataSource;
|
use document_graph_storage::NodeMetadataSource;
|
||||||
use graph_storage::{HotOp, Rev, TimeStamp};
|
use document_graph_storage::{HotOp, Rev, TimeStamp};
|
||||||
#[cfg(feature = "conversion")]
|
#[cfg(feature = "conversion")]
|
||||||
use graphene_resource::ResourceStorage;
|
use graphene_resource::ResourceStorage;
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ impl<L: Layout> Gdd<L> {
|
|||||||
|
|
||||||
/// Advance the published frontier to `rev` and persist it to `session.json`, so the silent/published
|
/// Advance the published frontier to `rev` and persist it to `session.json`, so the silent/published
|
||||||
/// undo boundary survives a reopen. Called by the (future) broadcast transport as commits are shared.
|
/// undo boundary survives a reopen. Called by the (future) broadcast transport as commits are shared.
|
||||||
pub fn publish_up_to(&mut self, rev: graph_storage::Rev) -> Result<(), Error> {
|
pub fn publish_up_to(&mut self, rev: document_graph_storage::Rev) -> Result<(), Error> {
|
||||||
self.session.publish_up_to(rev);
|
self.session.publish_up_to(rev);
|
||||||
self.persist_session_state()
|
self.persist_session_state()
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ impl<L: Layout> Gdd<L> {
|
|||||||
/// enters the registry, history, or CRDT.
|
/// enters the registry, history, or CRDT.
|
||||||
pub fn set_network_view_settings(
|
pub fn set_network_view_settings(
|
||||||
&mut self,
|
&mut self,
|
||||||
network_view_settings: std::collections::BTreeMap<graph_storage::NetworkId, std::collections::BTreeMap<String, serde_json::Value>>,
|
network_view_settings: std::collections::BTreeMap<document_graph_storage::NetworkId, std::collections::BTreeMap<String, serde_json::Value>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.network_view_settings = network_view_settings;
|
self.network_view_settings = network_view_settings;
|
||||||
self.persist_session_state()
|
self.persist_session_state()
|
||||||
@@ -23,7 +23,7 @@ impl<L: Layout> Gdd<L> {
|
|||||||
/// `DataSource::Embedded` source resolved to the content hash) through the session so the registry
|
/// `DataSource::Embedded` source resolved to the content hash) through the session so the registry
|
||||||
/// records the resource and the entry replicates, then writes the bytes into the working copy's
|
/// records the resource and the entry replicates, then writes the bytes into the working copy's
|
||||||
/// content-addressed store. The caller owns `id` allocation.
|
/// content-addressed store. The caller owns `id` allocation.
|
||||||
pub fn add_resource(&mut self, id: graph_storage::ResourceId, bytes: &[u8]) -> Result<(), Error> {
|
pub fn add_resource(&mut self, id: document_graph_storage::ResourceId, bytes: &[u8]) -> Result<(), Error> {
|
||||||
let hash = ResourceHash::from(bytes);
|
let hash = ResourceHash::from(bytes);
|
||||||
|
|
||||||
self.working.write_non_blocking(&self.layout.resource_path(&hash), bytes)?;
|
self.working.write_non_blocking(&self.layout.resource_path(&hash), bytes)?;
|
||||||
@@ -37,7 +37,7 @@ impl<L: Layout> Gdd<L> {
|
|||||||
/// than buffering them. Folder backends use `fs::copy` (CoW on supported filesystems); other
|
/// than buffering them. Folder backends use `fs::copy` (CoW on supported filesystems); other
|
||||||
/// backends fall back to read-then-write. Native-only: there is no filesystem source path on wasm.
|
/// backends fall back to read-then-write. Native-only: there is no filesystem source path on wasm.
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
pub fn add_resource_from_path(&mut self, id: graph_storage::ResourceId, hash: ResourceHash, src: &Path) -> Result<(), Error> {
|
pub fn add_resource_from_path(&mut self, id: document_graph_storage::ResourceId, hash: ResourceHash, src: &Path) -> Result<(), Error> {
|
||||||
let dest_path = self.layout.resource_path(&hash);
|
let dest_path = self.layout.resource_path(&hash);
|
||||||
if let AnyContainer::Folder(folder) = self.working.as_ref() {
|
if let AnyContainer::Folder(folder) = self.working.as_ref() {
|
||||||
let full = folder.root().join(&dest_path);
|
let full = folder.root().join(&dest_path);
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Lives in `session.json`. Rewritten on retirement.
|
//! Lives in `session.json`. Rewritten on retirement.
|
||||||
|
|
||||||
use graph_storage::{NetworkId, PeerId, Rev};
|
use document_graph_storage::{NetworkId, PeerId, Rev};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
use document_container::AnyContainer;
|
use document_container::AnyContainer;
|
||||||
use document_container::backends::memory::MemoryBackend;
|
use document_container::backends::memory::MemoryBackend;
|
||||||
use document_format::{Codec, Error, GddV1, GddV1Layout, Layout, Manifest, io, manifest};
|
use document_format::{Codec, Error, GddV1, GddV1Layout, Layout, Manifest, io, manifest};
|
||||||
use graph_storage::{HotOp, Network, NetworkId, PeerId, ROOT_NETWORK, RegistryDelta, TimeStamp};
|
use document_graph_storage::{HotOp, Network, NetworkId, PeerId, ROOT_NETWORK, RegistryDelta, TimeStamp};
|
||||||
|
|
||||||
fn empty_container() -> AnyContainer {
|
fn empty_container() -> AnyContainer {
|
||||||
AnyContainer::Memory(MemoryBackend::new())
|
AnyContainer::Memory(MemoryBackend::new())
|
||||||
@@ -416,8 +416,8 @@ fn export_carries_resources() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn embed_all_resources_materializes_link_only_resource() {
|
fn embed_all_resources_materializes_link_only_resource() {
|
||||||
use document_format::{ExportFormat, ExportOptions};
|
use document_format::{ExportFormat, ExportOptions};
|
||||||
|
use document_graph_storage::NoMetadata;
|
||||||
use graph_craft::application_io::resource::ResourceStorage;
|
use graph_craft::application_io::resource::ResourceStorage;
|
||||||
use graph_storage::NoMetadata;
|
|
||||||
use graphene_resource::{DataSource, ResourceHash, ResourceId, ResourceRegistry};
|
use graphene_resource::{DataSource, ResourceHash, ResourceId, ResourceRegistry};
|
||||||
|
|
||||||
futures::executor::block_on(async {
|
futures::executor::block_on(async {
|
||||||
@@ -483,8 +483,8 @@ fn embed_all_resources_materializes_link_only_resource() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn export_materializes_embedded_resource_from_byte_store() {
|
fn export_materializes_embedded_resource_from_byte_store() {
|
||||||
use document_format::{ExportFormat, ExportOptions};
|
use document_format::{ExportFormat, ExportOptions};
|
||||||
|
use document_graph_storage::NoMetadata;
|
||||||
use graph_craft::application_io::resource::ResourceStorage;
|
use graph_craft::application_io::resource::ResourceStorage;
|
||||||
use graph_storage::NoMetadata;
|
|
||||||
use graphene_resource::{DataSource, ResourceHash, ResourceId, ResourceRegistry};
|
use graphene_resource::{DataSource, ResourceHash, ResourceId, ResourceRegistry};
|
||||||
|
|
||||||
futures::executor::block_on(async {
|
futures::executor::block_on(async {
|
||||||
@@ -526,8 +526,8 @@ fn export_materializes_embedded_resource_from_byte_store() {
|
|||||||
/// export, which previously failed at `embed_resource_sources` and fell back to the legacy blob.
|
/// export, which previously failed at `embed_resource_sources` and fell back to the legacy blob.
|
||||||
#[test]
|
#[test]
|
||||||
fn export_round_trips_unretired_hot_ops() {
|
fn export_round_trips_unretired_hot_ops() {
|
||||||
|
use document_graph_storage::NoMetadata;
|
||||||
use graph_craft::application_io::resource::ResourceStorage;
|
use graph_craft::application_io::resource::ResourceStorage;
|
||||||
use graph_storage::NoMetadata;
|
|
||||||
use graphene_resource::{DataSource, ResourceId, ResourceRegistry};
|
use graphene_resource::{DataSource, ResourceId, ResourceRegistry};
|
||||||
|
|
||||||
futures::executor::block_on(async {
|
futures::executor::block_on(async {
|
||||||
@@ -602,10 +602,10 @@ fn create_in_records_default_codecs_in_manifest() {
|
|||||||
/// persistence and retirement, so the `peer_users` mapping survives a reopen.
|
/// persistence and retirement, so the `peer_users` mapping survives a reopen.
|
||||||
#[test]
|
#[test]
|
||||||
fn first_commit_registers_peer_and_survives_reopen() {
|
fn first_commit_registers_peer_and_survives_reopen() {
|
||||||
|
use document_graph_storage::{NoMetadata, UserId};
|
||||||
use graph_craft::application_io::resource::HashMapResourceStorage;
|
use graph_craft::application_io::resource::HashMapResourceStorage;
|
||||||
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeInput, NodeNetwork};
|
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeInput, NodeNetwork};
|
||||||
use graph_craft::{ProtoNodeIdentifier, concrete};
|
use graph_craft::{ProtoNodeIdentifier, concrete};
|
||||||
use graph_storage::{NoMetadata, UserId};
|
|
||||||
use graphene_resource::ResourceRegistry;
|
use graphene_resource::ResourceRegistry;
|
||||||
|
|
||||||
futures::executor::block_on(async {
|
futures::executor::block_on(async {
|
||||||
@@ -674,10 +674,10 @@ fn persist_path_writes_at_manifest_declared_codec_paths() {
|
|||||||
/// editor-shaped path (declaration bytes live in the resource store, not the Gdd container).
|
/// editor-shaped path (declaration bytes live in the resource store, not the Gdd container).
|
||||||
#[test]
|
#[test]
|
||||||
fn declarations_round_trip_through_byte_store() {
|
fn declarations_round_trip_through_byte_store() {
|
||||||
|
use document_graph_storage::NoMetadata;
|
||||||
use graph_craft::application_io::resource::HashMapResourceStorage;
|
use graph_craft::application_io::resource::HashMapResourceStorage;
|
||||||
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeInput, NodeNetwork};
|
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeInput, NodeNetwork};
|
||||||
use graph_craft::{ProtoNodeIdentifier, concrete};
|
use graph_craft::{ProtoNodeIdentifier, concrete};
|
||||||
use graph_storage::NoMetadata;
|
|
||||||
use graphene_resource::ResourceRegistry;
|
use graphene_resource::ResourceRegistry;
|
||||||
|
|
||||||
const PROTO: &str = "graphene_core::ops::identity::IdentityNode";
|
const PROTO: &str = "graphene_core::ops::identity::IdentityNode";
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "graph-storage"
|
name = "document-graph-storage"
|
||||||
description = "Provides a delta based graph representation used in the Graphite file format"
|
description = "Provides a delta based graph representation used in the Graphite file format"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ impl TryFrom<&NodeNetwork> for Registry {
|
|||||||
pub type DeclarationBytes = HashMap<ResourceHash, Vec<u8>>;
|
pub type DeclarationBytes = HashMap<ResourceHash, Vec<u8>>;
|
||||||
|
|
||||||
/// A `from_runtime` conversion result: the reference-only [`Registry`] plus the proto-node
|
/// A `from_runtime` conversion result: the reference-only [`Registry`] plus the proto-node
|
||||||
/// declaration *bytes* it extracted, keyed by content hash. `graph-storage` doesn't own a byte
|
/// declaration *bytes* it extracted, keyed by content hash. `document-graph-storage` doesn't own a byte
|
||||||
/// store, so the caller (the `Gdd`) persists these into its content store; the registry only holds
|
/// store, so the caller (the `Gdd`) persists these into its content store; the registry only holds
|
||||||
/// the `ResourceId`/`ResourceHash` references.
|
/// the `ResourceId`/`ResourceHash` references.
|
||||||
pub struct RuntimeConversion {
|
pub struct RuntimeConversion {
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ pub struct ExportSlot {
|
|||||||
|
|
||||||
/// Content of a proto-node declaration. Stored as a content-addressed resource (serialized bytes
|
/// Content of a proto-node declaration. Stored as a content-addressed resource (serialized bytes
|
||||||
/// keyed by `ResourceHash`, held by the `Gdd` byte store) and referenced from
|
/// keyed by `ResourceHash`, held by the `Gdd` byte store) and referenced from
|
||||||
/// `Implementation::ProtoNode(ResourceId)`. `graph-storage` itself only holds the reference.
|
/// `Implementation::ProtoNode(ResourceId)`. `document-graph-storage` itself only holds the reference.
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ProtoNode {
|
pub struct ProtoNode {
|
||||||
pub identifier: String,
|
pub identifier: String,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ impl Session {
|
|||||||
/// op as its own `Delta` on the local chain. One `clock.tick()` per op (strictly causal within
|
/// op as its own `Delta` on the local chain. One `clock.tick()` per op (strictly causal within
|
||||||
/// a commit). Returns the new `Rev`s in commit order (empty if nothing changed) plus the
|
/// a commit). Returns the new `Rev`s in commit order (empty if nothing changed) plus the
|
||||||
/// proto-node declaration bytes the conversion extracted, keyed by content hash, for the caller
|
/// proto-node declaration bytes the conversion extracted, keyed by content hash, for the caller
|
||||||
/// to persist into its byte store (`graph-storage` itself is byte-unaware).
|
/// to persist into its byte store (`document-graph-storage` itself is byte-unaware).
|
||||||
///
|
///
|
||||||
/// Stages the diff as hot ops rather than retired deltas: each op is applied to the registry and
|
/// Stages the diff as hot ops rather than retired deltas: each op is applied to the registry and
|
||||||
/// pushed onto the hot log. The caller persists the returned hot frames and then calls `retire`
|
/// pushed onto the hot log. The caller persists the returned hot frames and then calls `retire`
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pub enum ConversionError {
|
|||||||
|
|
||||||
/// Resolved proto-node declarations, keyed by the `ResourceId` that `Implementation::ProtoNode`
|
/// Resolved proto-node declarations, keyed by the `ResourceId` that `Implementation::ProtoNode`
|
||||||
/// references. The caller resolves these from its byte store (`ResourceId` → `ResourceHash` →
|
/// references. The caller resolves these from its byte store (`ResourceId` → `ResourceHash` →
|
||||||
/// stored `ProtoNode` bytes) before converting, since `graph-storage` holds only references.
|
/// stored `ProtoNode` bytes) before converting, since `document-graph-storage` holds only references.
|
||||||
pub type Declarations = std::collections::HashMap<ResourceId, ProtoNode>;
|
pub type Declarations = std::collections::HashMap<ResourceId, ProtoNode>;
|
||||||
|
|
||||||
impl Registry {
|
impl Registry {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ gpu = ["interpreted-executor/gpu", "dep:wgpu-executor"]
|
|||||||
# Local dependencies
|
# Local dependencies
|
||||||
graphite-proc-macros = { workspace = true }
|
graphite-proc-macros = { workspace = true }
|
||||||
graph-craft = { workspace = true }
|
graph-craft = { workspace = true }
|
||||||
graph-storage = { workspace = true, features = ["conversion"] }
|
|
||||||
document-format = { workspace = true }
|
document-format = { workspace = true }
|
||||||
|
document-graph-storage = { workspace = true, features = ["conversion"] }
|
||||||
document-container = { workspace = true }
|
document-container = { workspace = true }
|
||||||
graphene-hash = { workspace = true }
|
graphene-hash = { workspace = true }
|
||||||
interpreted-executor = { workspace = true }
|
interpreted-executor = { workspace = true }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
pub(crate) fn diff_registries(stored: &graph_storage::Registry, target: &graph_storage::Registry) -> String {
|
pub(crate) fn diff_registries(stored: &document_graph_storage::Registry, target: &document_graph_storage::Registry) -> String {
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
|
|
||||||
let stored_node_ids: std::collections::BTreeSet<_> = stored.node_instances.keys().copied().collect();
|
let stored_node_ids: std::collections::BTreeSet<_> = stored.node_instances.keys().copied().collect();
|
||||||
@@ -91,7 +91,7 @@ pub(crate) fn diff_registries(stored: &graph_storage::Registry, target: &graph_s
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diff_node(out: &mut String, stored: &graph_storage::Node, target: &graph_storage::Node) {
|
fn diff_node(out: &mut String, stored: &document_graph_storage::Node, target: &document_graph_storage::Node) {
|
||||||
if stored.implementation() != target.implementation() {
|
if stored.implementation() != target.implementation() {
|
||||||
let _ = writeln!(out, " implementation: stored={:?} target={:?}", stored.implementation(), target.implementation());
|
let _ = writeln!(out, " implementation: stored={:?} target={:?}", stored.implementation(), target.implementation());
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ fn diff_node(out: &mut String, stored: &graph_storage::Node, target: &graph_stor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diff_network(out: &mut String, stored: &graph_storage::Network, target: &graph_storage::Network) {
|
fn diff_network(out: &mut String, stored: &document_graph_storage::Network, target: &document_graph_storage::Network) {
|
||||||
if stored.exports.len() != target.exports.len() {
|
if stored.exports.len() != target.exports.len() {
|
||||||
let _ = writeln!(out, " exports.len: stored={} target={}", stored.exports.len(), target.exports.len());
|
let _ = writeln!(out, " exports.len: stored={} target={}", stored.exports.len(), target.exports.len());
|
||||||
}
|
}
|
||||||
@@ -144,13 +144,13 @@ fn diff_network(out: &mut String, stored: &graph_storage::Network, target: &grap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Value-level resource comparison (same resolved hash, same source bodies keyed by `SourceKey`),
|
/// Value-level resource comparison (same resolved hash, same source bodies keyed by `SourceKey`),
|
||||||
/// ignoring LWW timestamps. Mirrors `graph_storage`'s internal `resources_value_equal` for a single
|
/// ignoring LWW timestamps. Mirrors `document_graph_storage`'s internal `resources_value_equal` for a single
|
||||||
/// entry, since that helper is crate-private and only operates over a whole store.
|
/// entry, since that helper is crate-private and only operates over a whole store.
|
||||||
fn resource_value_equal(stored: &graph_storage::ResourceEntry, target: &graph_storage::ResourceEntry) -> bool {
|
fn resource_value_equal(stored: &document_graph_storage::ResourceEntry, target: &document_graph_storage::ResourceEntry) -> bool {
|
||||||
stored.hash == target.hash && stored.sources.len() == target.sources.len() && stored.sources.iter().all(|(key, value)| target.source(key).is_some_and(|other| value.source == other.source))
|
stored.hash == target.hash && stored.sources.len() == target.sources.len() && stored.sources.iter().all(|(key, value)| target.source(key).is_some_and(|other| value.source == other.source))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diff_resource(out: &mut String, stored: &graph_storage::ResourceEntry, target: &graph_storage::ResourceEntry) {
|
fn diff_resource(out: &mut String, stored: &document_graph_storage::ResourceEntry, target: &document_graph_storage::ResourceEntry) {
|
||||||
if stored.hash != target.hash {
|
if stored.hash != target.hash {
|
||||||
let _ = writeln!(out, " hash: stored={:?} target={:?}", stored.hash, target.hash);
|
let _ = writeln!(out, " hash: stored={:?} target={:?}", stored.hash, target.hash);
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ fn diff_resource(out: &mut String, stored: &graph_storage::ResourceEntry, target
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diff_attributes(out: &mut String, label: &str, stored: &graph_storage::Attributes, target: &graph_storage::Attributes) {
|
fn diff_attributes(out: &mut String, label: &str, stored: &document_graph_storage::Attributes, target: &document_graph_storage::Attributes) {
|
||||||
let stored_keys: std::collections::BTreeSet<_> = stored.keys().collect();
|
let stored_keys: std::collections::BTreeSet<_> = stored.keys().collect();
|
||||||
let target_keys: std::collections::BTreeSet<_> = target.keys().collect();
|
let target_keys: std::collections::BTreeSet<_> = target.keys().collect();
|
||||||
let missing: Vec<_> = target_keys.difference(&stored_keys).collect();
|
let missing: Vec<_> = target_keys.difference(&stored_keys).collect();
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::collections::{BTreeMap, HashSet};
|
use std::collections::{BTreeMap, HashSet};
|
||||||
|
|
||||||
|
use document_graph_storage::Registry;
|
||||||
use graph_craft::application_io::resource::{ResourceId, ResourceRegistry, ResourceStorage};
|
use graph_craft::application_io::resource::{ResourceId, ResourceRegistry, ResourceStorage};
|
||||||
use graph_storage::Registry;
|
|
||||||
|
|
||||||
use super::utility_types::network_interface::NodeNetworkInterface;
|
use super::utility_types::network_interface::NodeNetworkInterface;
|
||||||
use super::utility_types::network_interface::storage_metadata::{StorageMetadataView, collect_network_view_settings};
|
use super::utility_types::network_interface::storage_metadata::{StorageMetadataView, collect_network_view_settings};
|
||||||
|
|||||||
@@ -2049,7 +2049,7 @@ impl DocumentMessageHandler {
|
|||||||
|
|
||||||
/// Restore `view_settings` map into the document.
|
/// Restore `view_settings` map into the document.
|
||||||
pub fn apply_stored_document_settings(&mut self, view_settings: &std::collections::BTreeMap<String, serde_json::Value>) {
|
pub fn apply_stored_document_settings(&mut self, view_settings: &std::collections::BTreeMap<String, serde_json::Value>) {
|
||||||
use graph_storage::attr::session::doc;
|
use document_graph_storage::attr::session::doc;
|
||||||
|
|
||||||
fn decode<T: serde::de::DeserializeOwned>(view_settings: &std::collections::BTreeMap<String, serde_json::Value>, key: &str) -> Option<T> {
|
fn decode<T: serde::de::DeserializeOwned>(view_settings: &std::collections::BTreeMap<String, serde_json::Value>, key: &str) -> Option<T> {
|
||||||
view_settings.get(key).and_then(|value| serde_json::from_value(value.clone()).ok())
|
view_settings.get(key).and_then(|value| serde_json::from_value(value.clone()).ok())
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use graph_storage::{NodeMetadataSource, PeerId, Registry};
|
use document_graph_storage::{NodeMetadataSource, PeerId, Registry};
|
||||||
|
|
||||||
use super::test_support::{load_demo, node_paths};
|
use super::test_support::{load_demo, node_paths};
|
||||||
use crate::messages::portfolio::document::document_message_handler::DocumentMessageHandler;
|
use crate::messages::portfolio::document::document_message_handler::DocumentMessageHandler;
|
||||||
@@ -34,7 +34,7 @@ fn editor_metadata_round_trip_against_demo() {
|
|||||||
let (_converted_network, entries) = registry.to_runtime_with_metadata(&declarations).expect("to_runtime_with_metadata failed");
|
let (_converted_network, entries) = registry.to_runtime_with_metadata(&declarations).expect("to_runtime_with_metadata failed");
|
||||||
|
|
||||||
// Index emitted entries by their (network_path, local_id) address.
|
// Index emitted entries by their (network_path, local_id) address.
|
||||||
let entries_by_address: HashMap<(Vec<NodeId>, NodeId), &graph_storage::NodeMetadataEntry> = entries.iter().map(|e| ((e.network_path.clone(), e.local_id), e)).collect();
|
let entries_by_address: HashMap<(Vec<NodeId>, NodeId), &document_graph_storage::NodeMetadataEntry> = entries.iter().map(|e| ((e.network_path.clone(), e.local_id), e)).collect();
|
||||||
|
|
||||||
let mut checked_any_position = false;
|
let mut checked_any_position = false;
|
||||||
let mut checked_any_layer = false;
|
let mut checked_any_layer = false;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
use document_container::AnyContainer;
|
use document_container::AnyContainer;
|
||||||
use document_container::backends::memory::MemoryBackend;
|
use document_container::backends::memory::MemoryBackend;
|
||||||
use document_format::{GddV1, GddV1Layout};
|
use document_format::{GddV1, GddV1Layout};
|
||||||
|
use document_graph_storage::{NodeMetadataSource, PeerId};
|
||||||
use graph_craft::application_io::resource::HashMapResourceStorage;
|
use graph_craft::application_io::resource::HashMapResourceStorage;
|
||||||
use graph_storage::{NodeMetadataSource, PeerId};
|
|
||||||
|
|
||||||
use super::test_support::{RoundTrip, node_paths, round_trip_through_gdd};
|
use super::test_support::{RoundTrip, node_paths, round_trip_through_gdd};
|
||||||
use crate::messages::portfolio::document::document_message_handler::DocumentMessageHandler;
|
use crate::messages::portfolio::document::document_message_handler::DocumentMessageHandler;
|
||||||
@@ -125,7 +125,7 @@ async fn recommit_after_open_is_stable() {
|
|||||||
// that same peer for deterministic node-ID derivation.
|
// that same peer for deterministic node-ID derivation.
|
||||||
let rebuilt_network = round_trip.rebuilt.document_network().clone();
|
let rebuilt_network = round_trip.rebuilt.document_network().clone();
|
||||||
let view = StorageMetadataView::new(&round_trip.rebuilt);
|
let view = StorageMetadataView::new(&round_trip.rebuilt);
|
||||||
let reconverted = graph_storage::Registry::convert_from_runtime(&rebuilt_network, &view, &Default::default(), PeerId(1)).expect("re-convert from_runtime");
|
let reconverted = document_graph_storage::Registry::convert_from_runtime(&rebuilt_network, &view, &Default::default(), PeerId(1)).expect("re-convert from_runtime");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
round_trip.registry.value_equal(&reconverted.registry),
|
round_trip.registry.value_equal(&reconverted.registry),
|
||||||
@@ -351,7 +351,7 @@ async fn live_undo_shadows_storage_cursor() {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn round_trip_document_settings() {
|
async fn round_trip_document_settings() {
|
||||||
use graph_storage::attr::session::doc;
|
use document_graph_storage::attr::session::doc;
|
||||||
|
|
||||||
let mut editor = EditorTestUtils::create();
|
let mut editor = EditorTestUtils::create();
|
||||||
editor.new_document().await;
|
editor.new_document().await;
|
||||||
@@ -382,7 +382,7 @@ async fn round_trip_document_settings() {
|
|||||||
/// and reopens via `open_from_archive`, asserting the PTZ round-trips.
|
/// and reopens via `open_from_archive`, asserting the PTZ round-trips.
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn gdd_archive_round_trips_view_settings() {
|
async fn gdd_archive_round_trips_view_settings() {
|
||||||
use graph_storage::attr::session::doc;
|
use document_graph_storage::attr::session::doc;
|
||||||
|
|
||||||
let byte_store = HashMapResourceStorage::new();
|
let byte_store = HashMapResourceStorage::new();
|
||||||
let mut gdd = GddV1::create_in(AnyContainer::Memory(MemoryBackend::new()), GddV1Layout, PeerId(1), 0xABCD, "test".into(), "test".into())
|
let mut gdd = GddV1::create_in(AnyContainer::Memory(MemoryBackend::new()), GddV1Layout, PeerId(1), 0xABCD, "test".into(), "test".into())
|
||||||
@@ -420,7 +420,7 @@ async fn gdd_archive_round_trips_view_settings() {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn per_network_navigation_round_trips_via_session_not_registry() {
|
async fn per_network_navigation_round_trips_via_session_not_registry() {
|
||||||
use crate::messages::portfolio::document::utility_types::network_interface::storage_metadata::{apply_network_view_settings, collect_network_view_settings, network_ids_from_entries};
|
use crate::messages::portfolio::document::utility_types::network_interface::storage_metadata::{apply_network_view_settings, collect_network_view_settings, network_ids_from_entries};
|
||||||
use graph_storage::attr::session::network;
|
use document_graph_storage::attr::session::network;
|
||||||
|
|
||||||
let byte_store = HashMapResourceStorage::new();
|
let byte_store = HashMapResourceStorage::new();
|
||||||
|
|
||||||
@@ -449,7 +449,7 @@ async fn per_network_navigation_round_trips_via_session_not_registry() {
|
|||||||
gdd.set_network_view_settings(network_view_settings).expect("set_network_view_settings");
|
gdd.set_network_view_settings(network_view_settings).expect("set_network_view_settings");
|
||||||
|
|
||||||
// The registry must NOT carry the node-graph nav (it's per-peer, not document content).
|
// The registry must NOT carry the node-graph nav (it's per-peer, not document content).
|
||||||
let root_network = gdd.registry().networks.get(&graph_storage::ROOT_NETWORK).expect("root network in registry");
|
let root_network = gdd.registry().networks.get(&document_graph_storage::ROOT_NETWORK).expect("root network in registry");
|
||||||
assert!(!root_network.attributes.contains_key(network::NAV_PTZ), "node-graph nav must not be stored in the registry attributes");
|
assert!(!root_network.attributes.contains_key(network::NAV_PTZ), "node-graph nav must not be stored in the registry attributes");
|
||||||
|
|
||||||
// Reopen, rebuild the interface, and apply the persisted per-network view state.
|
// Reopen, rebuild the interface, and apply the persisted per-network view state.
|
||||||
@@ -632,7 +632,7 @@ fn assert_cursor_matches_runtime(document: &DocumentMessageHandler, at: &str) {
|
|||||||
|
|
||||||
let network = document.network_interface.document_network().clone();
|
let network = document.network_interface.document_network().clone();
|
||||||
let view = StorageMetadataView::new(&document.network_interface);
|
let view = StorageMetadataView::new(&document.network_interface);
|
||||||
let target = graph_storage::Registry::convert_from_runtime(&network, &view, &document.resources.registry, peer).expect("from_runtime");
|
let target = document_graph_storage::Registry::convert_from_runtime(&network, &view, &document.resources.registry, peer).expect("from_runtime");
|
||||||
|
|
||||||
let stored = storage.registry();
|
let stored = storage.registry();
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
use document_container::AnyContainer;
|
use document_container::AnyContainer;
|
||||||
use document_container::backends::memory::MemoryBackend;
|
use document_container::backends::memory::MemoryBackend;
|
||||||
use document_format::{GddV1, GddV1Layout};
|
use document_format::{GddV1, GddV1Layout};
|
||||||
|
use document_graph_storage::PeerId;
|
||||||
use graph_craft::application_io::resource::HashMapResourceStorage;
|
use graph_craft::application_io::resource::HashMapResourceStorage;
|
||||||
use graph_craft::document::{DocumentNodeImplementation, NodeId};
|
use graph_craft::document::{DocumentNodeImplementation, NodeId};
|
||||||
use graph_storage::PeerId;
|
|
||||||
|
|
||||||
use crate::messages::portfolio::document::document_message_handler::DocumentMessageHandler;
|
use crate::messages::portfolio::document::document_message_handler::DocumentMessageHandler;
|
||||||
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
|
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
|
||||||
@@ -45,7 +45,7 @@ pub fn node_paths(interface: &NodeNetworkInterface) -> Vec<(Vec<NodeId>, NodeId)
|
|||||||
/// storage, the reopened registry, and the reopened per-peer view settings (`ui::doc::*`).
|
/// storage, the reopened registry, and the reopened per-peer view settings (`ui::doc::*`).
|
||||||
pub struct RoundTrip {
|
pub struct RoundTrip {
|
||||||
pub rebuilt: NodeNetworkInterface,
|
pub rebuilt: NodeNetworkInterface,
|
||||||
pub registry: graph_storage::Registry,
|
pub registry: document_graph_storage::Registry,
|
||||||
pub view_settings: std::collections::BTreeMap<String, serde_json::Value>,
|
pub view_settings: std::collections::BTreeMap<String, serde_json::Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Bridge between `NodeNetworkInterface` and `graph-storage`'s `NodeMetadataSource` trait.
|
//! Bridge between `NodeNetworkInterface` and `document-graph-storage`'s `NodeMetadataSource` trait.
|
||||||
//! Conversion round-trip tests live in `storage_metadata_tests`.
|
//! Conversion round-trip tests live in `storage_metadata_tests`.
|
||||||
//!
|
//!
|
||||||
//! The trait impl lives on the [`StorageMetadataView`] wrapper (not on `NodeNetworkInterface`
|
//! The trait impl lives on the [`StorageMetadataView`] wrapper (not on `NodeNetworkInterface`
|
||||||
@@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
|
use document_graph_storage::attr::session;
|
||||||
|
use document_graph_storage::{InputMetadataEntry, NetworkMetadataEntry, NodeMetadataEntry, NodeMetadataSource, Position};
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeNetwork};
|
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeNetwork};
|
||||||
use graph_storage::attr::session;
|
|
||||||
use graph_storage::{InputMetadataEntry, NetworkMetadataEntry, NodeMetadataEntry, NodeMetadataSource, Position};
|
|
||||||
use graphene_std::vector::style::RenderMode;
|
use graphene_std::vector::style::RenderMode;
|
||||||
|
|
||||||
use super::memo_network::MemoNetwork;
|
use super::memo_network::MemoNetwork;
|
||||||
@@ -41,7 +41,7 @@ pub struct DocumentSettings<'a> {
|
|||||||
pub collapsed: &'a CollapsedLayers,
|
pub collapsed: &'a CollapsedLayers,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adapts a `&NodeNetworkInterface` to `graph-storage`'s `NodeMetadataSource` (node/network metadata
|
/// Adapts a `&NodeNetworkInterface` to `document-graph-storage`'s `NodeMetadataSource` (node/network metadata
|
||||||
/// only; document-level view settings live in `session.json`, not the registry).
|
/// only; document-level view settings live in `session.json`, not the registry).
|
||||||
pub struct StorageMetadataView<'a> {
|
pub struct StorageMetadataView<'a> {
|
||||||
interface: &'a NodeNetworkInterface,
|
interface: &'a NodeNetworkInterface,
|
||||||
@@ -183,18 +183,18 @@ pub fn build_interface_from_storage(network: NodeNetwork, node_entries: Vec<Node
|
|||||||
|
|
||||||
/// Build the runtime-`network_path` -> stable-`NetworkId` map from the `NetworkMetadataEntry`s that
|
/// Build the runtime-`network_path` -> stable-`NetworkId` map from the `NetworkMetadataEntry`s that
|
||||||
/// `to_runtime_with_full_metadata` emits, so the open path can apply per-network view settings.
|
/// `to_runtime_with_full_metadata` emits, so the open path can apply per-network view settings.
|
||||||
pub fn network_ids_from_entries(network_entries: &[NetworkMetadataEntry]) -> HashMap<Vec<NodeId>, graph_storage::NetworkId> {
|
pub fn network_ids_from_entries(network_entries: &[NetworkMetadataEntry]) -> HashMap<Vec<NodeId>, document_graph_storage::NetworkId> {
|
||||||
network_entries.iter().map(|entry| (entry.network_path.clone(), entry.network_id)).collect()
|
network_entries.iter().map(|entry| (entry.network_path.clone(), entry.network_id)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect the per-network, per-peer view state (node-graph nav + previewing) from `interface` into a
|
/// Collect the per-network, per-peer view state (node-graph nav + previewing) from `interface` into a
|
||||||
/// `session.json` map keyed by the stable storage [`NetworkId`](graph_storage::NetworkId), which
|
/// `session.json` map keyed by the stable storage [`NetworkId`](document_graph_storage::NetworkId), which
|
||||||
/// `network_ids` resolves from each runtime `network_path`. Networks at their default nav with no preview
|
/// `network_ids` resolves from each runtime `network_path`. Networks at their default nav with no preview
|
||||||
/// produce no entry.
|
/// produce no entry.
|
||||||
pub fn collect_network_view_settings(
|
pub fn collect_network_view_settings(
|
||||||
interface: &NodeNetworkInterface,
|
interface: &NodeNetworkInterface,
|
||||||
network_ids: &HashMap<Vec<NodeId>, graph_storage::NetworkId>,
|
network_ids: &HashMap<Vec<NodeId>, document_graph_storage::NetworkId>,
|
||||||
) -> BTreeMap<graph_storage::NetworkId, BTreeMap<String, serde_json::Value>> {
|
) -> BTreeMap<document_graph_storage::NetworkId, BTreeMap<String, serde_json::Value>> {
|
||||||
let mut out = BTreeMap::new();
|
let mut out = BTreeMap::new();
|
||||||
|
|
||||||
for (network_path, &network_id) in network_ids {
|
for (network_path, &network_id) in network_ids {
|
||||||
@@ -240,12 +240,12 @@ pub fn collect_network_view_settings(
|
|||||||
|
|
||||||
/// Apply persisted per-network view state (node-graph nav + previewing) from `session.json` onto
|
/// Apply persisted per-network view state (node-graph nav + previewing) from `session.json` onto
|
||||||
/// `interface`. Inverse of [`collect_network_view_settings`]: `network_ids` resolves each runtime
|
/// `interface`. Inverse of [`collect_network_view_settings`]: `network_ids` resolves each runtime
|
||||||
/// `network_path` to its [`NetworkId`](graph_storage::NetworkId), and the matching inner map is decoded
|
/// `network_path` to its [`NetworkId`](document_graph_storage::NetworkId), and the matching inner map is decoded
|
||||||
/// back onto the network's navigation/previewing metadata.
|
/// back onto the network's navigation/previewing metadata.
|
||||||
pub fn apply_network_view_settings(
|
pub fn apply_network_view_settings(
|
||||||
interface: &mut NodeNetworkInterface,
|
interface: &mut NodeNetworkInterface,
|
||||||
network_ids: &HashMap<Vec<NodeId>, graph_storage::NetworkId>,
|
network_ids: &HashMap<Vec<NodeId>, document_graph_storage::NetworkId>,
|
||||||
network_view_settings: &BTreeMap<graph_storage::NetworkId, BTreeMap<String, serde_json::Value>>,
|
network_view_settings: &BTreeMap<document_graph_storage::NetworkId, BTreeMap<String, serde_json::Value>>,
|
||||||
) {
|
) {
|
||||||
for (network_path, network_id) in network_ids {
|
for (network_path, network_id) in network_ids {
|
||||||
let Some(settings) = network_view_settings.get(network_id) else { continue };
|
let Some(settings) = network_view_settings.get(network_id) else { continue };
|
||||||
|
|||||||
@@ -48,7 +48,12 @@ async fn build_per_document_container(path: Option<&std::path::Path>) -> Result<
|
|||||||
/// Open the existing working copy at `path`, or create a fresh one bound to `peer` (in-memory when
|
/// Open the existing working copy at `path`, or create a fresh one bound to `peer` (in-memory when
|
||||||
/// `path` is `None`). Returns the working copy plus whether it was reopened (vs freshly created); only a
|
/// `path` is `None`). Returns the working copy plus whether it was reopened (vs freshly created); only a
|
||||||
/// reopen has independently-stored state worth comparing against the legacy load.
|
/// reopen has independently-stored state worth comparing against the legacy load.
|
||||||
pub(super) async fn build_or_open_working_copy(path: Option<&std::path::Path>, peer: graph_storage::PeerId, document_uuid: u64, version: String) -> Result<(GddV1, bool), DocumentFormatError> {
|
pub(super) async fn build_or_open_working_copy(
|
||||||
|
path: Option<&std::path::Path>,
|
||||||
|
peer: document_graph_storage::PeerId,
|
||||||
|
document_uuid: u64,
|
||||||
|
version: String,
|
||||||
|
) -> Result<(GddV1, bool), DocumentFormatError> {
|
||||||
let (container, exists) = build_per_document_container(path).await?;
|
let (container, exists) = build_per_document_container(path).await?;
|
||||||
|
|
||||||
let gdd = if exists {
|
let gdd = if exists {
|
||||||
|
|||||||
@@ -1896,7 +1896,7 @@ impl PortfolioMessageHandler {
|
|||||||
) -> Message {
|
) -> Message {
|
||||||
let path = working_copy_root.map(|root| root.join(format!("{:016x}", document_id.0)));
|
let path = working_copy_root.map(|root| root.join(format!("{:016x}", document_id.0)));
|
||||||
let editor_version = crate::application::GRAPHITE_GIT_COMMIT_HASH.to_string();
|
let editor_version = crate::application::GRAPHITE_GIT_COMMIT_HASH.to_string();
|
||||||
let peer = graph_storage::PeerId(generate_uuid());
|
let peer = document_graph_storage::PeerId(generate_uuid());
|
||||||
|
|
||||||
let future = async move {
|
let future = async move {
|
||||||
let (gdd, reopened) = match build_or_open_working_copy(path.as_deref(), peer, document_id.0, editor_version).await {
|
let (gdd, reopened) = match build_or_open_working_copy(path.as_deref(), peer, document_id.0, editor_version).await {
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ The editor operates on its existing runtime types. Storage is a serialization la
|
|||||||
│ to_runtime │ from_runtime
|
│ to_runtime │ from_runtime
|
||||||
│ ▼
|
│ ▼
|
||||||
┌─────────────────────────────────────────┐
|
┌─────────────────────────────────────────┐
|
||||||
│ Storage layer (graph-storage crate) │
|
│ Storage layer (document-graph-storage) │
|
||||||
│ Registry, RegistryDelta, Document │
|
│ Registry, RegistryDelta, Document │
|
||||||
└─────────────────────────────────────────┘
|
└─────────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
@@ -228,7 +228,7 @@ The editor operates on its existing runtime types. Storage is a serialization la
|
|||||||
└─────────────────────────────────────────┘
|
└─────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
The runtime is the source of truth during editing. Conversion runs on save, on load, and across the sync boundary when broadcasting or receiving ops. The editor-facing handle is `Session` (`graph_storage::Session`), and `Document` is internal. `Session::stage_from_runtime(&NodeNetwork, &dyn NodeMetadataSource)` is the entry point: it diffs the stored registry against a fresh conversion, ticks the clock once per emitted op, and applies each as a hot op on the hot log. The `Gdd` handle then persists the hot frames and retires them into durable history.
|
The runtime is the source of truth during editing. Conversion runs on save, on load, and across the sync boundary when broadcasting or receiving ops. The editor-facing handle is `Session` (`document_graph_storage::Session`), and `Document` is internal. `Session::stage_from_runtime(&NodeNetwork, &dyn NodeMetadataSource)` is the entry point: it diffs the stored registry against a fresh conversion, ticks the clock once per emitted op, and applies each as a hot op on the hot log. The `Gdd` handle then persists the hot frames and retires them into durable history.
|
||||||
|
|
||||||
Staging and retirement are split so that one undo gesture maps to one retired gesture. The editor's undo unit is one legacy transaction boundary, but a single user action (for example, a tool drag) re-commits the runtime many times within one such boundary. So the editor *stages* on every commit (keeping the working registry and autosave current) and *retires the pending hot ops as one gesture* only at the undo-step boundary and before any undo/redo. (`commit_from_runtime`, which stages and retires atomically, remains for one-shot callers.) Solo editing thus flows through the same hot-op-then-retire path that collaboration uses, exercising it before any transport lands.
|
Staging and retirement are split so that one undo gesture maps to one retired gesture. The editor's undo unit is one legacy transaction boundary, but a single user action (for example, a tool drag) re-commits the runtime many times within one such boundary. So the editor *stages* on every commit (keeping the working registry and autosave current) and *retires the pending hot ops as one gesture* only at the undo-step boundary and before any undo/redo. (`commit_from_runtime`, which stages and retires atomically, remains for one-shot callers.) Solo editing thus flows through the same hot-op-then-retire path that collaboration uses, exercising it before any transport lands.
|
||||||
|
|
||||||
@@ -236,30 +236,30 @@ Staging and retirement are split so that one undo gesture maps to one retired ge
|
|||||||
|
|
||||||
A `.gdd` document is a collection of named byte payloads. A `Container` backend (loose folder, in-memory, OPFS in the browser) provides the path-keyed read/write surface. An `Archive` codec (zip, xz-compressed tarball) optionally encodes a container into a single byte stream for compact distribution. The same logical document can be saved as a loose folder for VCS-friendly checkouts or as an archive for shipping, without any change above the container layer.
|
A `.gdd` document is a collection of named byte payloads. A `Container` backend (loose folder, in-memory, OPFS in the browser) provides the path-keyed read/write surface. An `Archive` codec (zip, xz-compressed tarball) optionally encodes a container into a single byte stream for compact distribution. The same logical document can be saved as a loose folder for VCS-friendly checkouts or as an archive for shipping, without any change above the container layer.
|
||||||
|
|
||||||
The two concerns live in downstream crates. `document-container` defines the `Container` and `AsyncContainer` traits, the backends, byte ownership (mmap regions, owned buffers, external file mmaps via `mmap-io`), and the `Archive` trait. `document-format` defines the typed `Gdd` handle, the layout (logical-payload-name to in-container path), the data codec (JSON or binary), the manifest, and the save/load orchestration. `graph-storage` itself stays disk-unaware.
|
The two concerns live in downstream crates. `document-container` defines the `Container` and `AsyncContainer` traits, the backends, byte ownership (mmap regions, owned buffers, external file mmaps via `mmap-io`), and the `Archive` trait. `document-format` defines the typed `Gdd` handle, the layout (logical-payload-name to in-container path), the data codec (JSON or binary), the manifest, and the save/load orchestration. `document-graph-storage` itself stays disk-unaware.
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────┐
|
┌─────────────────────────────────┐
|
||||||
│ editor │
|
│ editor │
|
||||||
└─────────────────────────────────┘
|
└─────────────────────────────────┘
|
||||||
│ │
|
│ │
|
||||||
▼ ▼
|
▼ ▼
|
||||||
┌───────────────┐ ┌──────────────────────────────┐
|
┌────────────────────────┐ ┌──────────────────────────────┐
|
||||||
│ graph-storage │ │ document-format │
|
│ document-graph-storage │ │ document-format │
|
||||||
│ (disk-unaware)│◀─│ Gdd handle, Layout, codec, │
|
│ (disk-unaware) │◀─│ Gdd handle, Layout, codec, │
|
||||||
└───────────────┘ │ ExportOptions │
|
└────────────────────────┘ │ ExportOptions │
|
||||||
└──────────────────────────────┘
|
└──────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌──────────────────────────────┐
|
┌──────────────────────────────┐
|
||||||
│ document-container │
|
│ document-container │
|
||||||
│ Container backends + Archive│
|
│ Container backends + Archive│
|
||||||
│ codecs (folder, memory, │
|
│ codecs (folder, memory, │
|
||||||
│ OPFS / zip, xz) │
|
│ OPFS / zip, xz) │
|
||||||
└──────────────────────────────┘
|
└──────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
Arrows mean "depends on". The editor uses `Session` from `graph-storage` at runtime and `Gdd` from `document-format` on save/load. `document-format` serializes `graph-storage`'s types and delegates byte I/O to `document-container`. `graph-storage` and `document-container` are independent leaves.
|
Arrows mean "depends on". The editor uses `Session` from `document-graph-storage` at runtime and `Gdd` from `document-format` on save/load. `document-format` serializes `document-graph-storage`'s types and delegates byte I/O to `document-container`. `document-graph-storage` and `document-container` are independent leaves.
|
||||||
|
|
||||||
A document contains:
|
A document contains:
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ The `Gdd` handle owns the loaded bytes and exposes them as zero-copy slices. On
|
|||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
Everything content-addressable is a resource: raster images, fonts, embedded WASM, **and proto-node declarations**. The storage `Registry` holds `resources: ResourceStore` (references only). The bytes live in a content-addressed byte store keyed by `ResourceHash`, owned by the caller (the app-global cache in the editor, the `Gdd` container for standalone/export) rather than by `graph-storage`.
|
Everything content-addressable is a resource: raster images, fonts, embedded WASM, **and proto-node declarations**. The storage `Registry` holds `resources: ResourceStore` (references only). The bytes live in a content-addressed byte store keyed by `ResourceHash`, owned by the caller (the app-global cache in the editor, the `Gdd` container for standalone/export) rather than by `document-graph-storage`.
|
||||||
|
|
||||||
```rs
|
```rs
|
||||||
pub type ResourceStore = HashMap<ResourceId, ResourceEntry>;
|
pub type ResourceStore = HashMap<ResourceId, ResourceEntry>;
|
||||||
@@ -329,7 +329,7 @@ Migrations live in a dedicated crate so they are usable both from the editor and
|
|||||||
- Each nested `NodeNetwork`'s `NetworkId` is derived from the owning node's path (blake3 of `(peer, path)` with a `"network"` domain tag), not assigned by a traversal counter. This makes it stable across a `to_runtime` then `from_runtime` round trip. That stability is load-bearing, because node paths (and thus node-ID hashes) include `NetworkId`s, so an unstable network ID would cascade into unstable node IDs and break re-commit after open. Aliasing (multiple nodes referencing the same network) is structurally supported by the storage model, since `Implementation::Network(NetworkId)` is a reference, but the converter does not exploit it yet. Aliasing is fixed at the runtime layer first, and the converter then preserves sharing without an explicit dedup pass.
|
- Each nested `NodeNetwork`'s `NetworkId` is derived from the owning node's path (blake3 of `(peer, path)` with a `"network"` domain tag), not assigned by a traversal counter. This makes it stable across a `to_runtime` then `from_runtime` round trip. That stability is load-bearing, because node paths (and thus node-ID hashes) include `NetworkId`s, so an unstable network ID would cascade into unstable node IDs and break re-commit after open. Aliasing (multiple nodes referencing the same network) is structurally supported by the storage model, since `Implementation::Network(NetworkId)` is a reference, but the converter does not exploit it yet. Aliasing is fixed at the runtime layer first, and the converter then preserves sharing without an explicit dedup pass.
|
||||||
- Non-structural `DocumentNode` fields (`call_argument`, `context_features`, `visible`, `skip_deduplication`, and so on) become entries in the node's `attributes`. UI metadata from `DocumentNodeMetadata` (positions, display names, locked, pinned, and so on) flows through the same bucket under `ui::*` keys.
|
- Non-structural `DocumentNode` fields (`call_argument`, `context_features`, `visible`, `skip_deduplication`, and so on) become entries in the node's `attributes`. UI metadata from `DocumentNodeMetadata` (positions, display names, locked, pinned, and so on) flows through the same bucket under `ui::*` keys.
|
||||||
|
|
||||||
`to_runtime` is the inverse. It rebuilds local IDs from the stashed attribute, restores typed fields from attribute values, follows `Implementation::Network` references to recursively materialize nested networks, and resolves `Implementation::ProtoNode(ResourceId)` against a `Declarations` map (`ResourceId` to `ProtoNode`) the caller supplies from its byte store. Since `graph-storage` is byte-unaware, `to_runtime` takes the resolved declarations as a parameter rather than reaching for bytes itself.
|
`to_runtime` is the inverse. It rebuilds local IDs from the stashed attribute, restores typed fields from attribute values, follows `Implementation::Network` references to recursively materialize nested networks, and resolves `Implementation::ProtoNode(ResourceId)` against a `Declarations` map (`ResourceId` to `ProtoNode`) the caller supplies from its byte store. Since `document-graph-storage` is byte-unaware, `to_runtime` takes the resolved declarations as a parameter rather than reaching for bytes itself.
|
||||||
|
|
||||||
## Slots: inputs and exports
|
## Slots: inputs and exports
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user