Skip to content

Commit e32ff4b

Browse files
Make Resource aware of its own hash (#4187)
* Fix future message handler field name * Add Resource::hash() * Move all remaining resource types from core-types to graphene-resources * Review
1 parent 78679a5 commit e32ff4b

11 files changed

Lines changed: 94 additions & 90 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/application.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl Editor {
1515
graphene_std::uuid::set_uuid_seed(uuid_random_seed);
1616

1717
let mut dispatcher = Dispatcher::new(resource_storage);
18-
dispatcher.message_handlers.async_message_handler.set_wake(wake);
18+
dispatcher.message_handlers.future_message_handler.set_wake(wake);
1919
application_io.inject_resource_proxy(dispatcher.message_handlers.resource_storage_message_handler.resources());
2020
crate::node_graph_executor::replace_application_io(application_io);
2121

editor/src/dispatcher.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub struct Dispatcher {
2020
pub struct DispatcherMessageHandlers {
2121
animation_message_handler: AnimationMessageHandler,
2222
app_window_message_handler: AppWindowMessageHandler,
23-
pub(crate) async_message_handler: FutureMessageHandler,
23+
pub(crate) future_message_handler: FutureMessageHandler,
2424
broadcast_message_handler: BroadcastMessageHandler,
2525
clipboard_message_handler: ClipboardMessageHandler,
2626
color_picker_message_handler: ColorPickerMessageHandler,
@@ -127,7 +127,7 @@ impl Dispatcher {
127127

128128
// Drain async results into the queue before processing the new message.
129129
let mut async_results = VecDeque::new();
130-
self.message_handlers.async_message_handler.drain_results(&mut async_results);
130+
self.message_handlers.future_message_handler.drain_results(&mut async_results);
131131
if !async_results.is_empty() {
132132
Self::schedule_execution(&mut self.message_queues, true, async_results);
133133
}
@@ -182,7 +182,7 @@ impl Dispatcher {
182182
self.message_handlers.app_window_message_handler.process_message(message, &mut queue, ());
183183
}
184184
Message::Future(message) => {
185-
self.message_handlers.async_message_handler.process_message(message, &mut queue, FutureMessageContext {});
185+
self.message_handlers.future_message_handler.process_message(message, &mut queue, FutureMessageContext {});
186186
}
187187
Message::Broadcast(message) => self.message_handlers.broadcast_message_handler.process_message(message, &mut queue, ()),
188188
Message::Clipboard(message) => self.message_handlers.clipboard_message_handler.process_message(message, &mut queue, ()),

node-graph/graph-craft/src/application_io/resource/mmap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl MmapResourceStorage {
5353

5454
let path = self.path_for(hash);
5555
let mmap = Self::open_mmap(&path)?;
56-
let resource = Resource::new(MmappedBytes(mmap));
56+
let resource = Resource::new_unchecked(MmappedBytes(mmap), *hash);
5757

5858
self.cache.write().unwrap_or_else(|poisoned| poisoned.into_inner()).insert(*hash, resource.clone());
5959
Some(resource)

node-graph/graph-craft/src/application_io/resource/opfs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl ResourceStorage for OpfsResourceStorage {
8181
let mut bytes = None;
8282
if !guard.cache.contains_key(&hash) {
8383
let resource_bytes = Arc::<[u8]>::from(data);
84-
guard.cache.insert(hash, Resource::new(resource_bytes.clone()));
84+
guard.cache.insert(hash, Resource::new_unchecked(resource_bytes.clone(), hash));
8585
bytes = Some(resource_bytes);
8686
}
8787

@@ -302,7 +302,7 @@ async fn read_from_opfs(inner: Arc<Mutex<Inner>>, hash: ResourceHash) -> Option<
302302
return None;
303303
}
304304

305-
let resource = Resource::new(bytes);
305+
let resource = Resource::new_unchecked(bytes, hash);
306306
let mut guard = inner.lock().unwrap();
307307
if let Some(resource) = guard.cache.get(&hash) {
308308
return Some(resource.clone());

node-graph/libraries/application-io/src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ use std::time::Duration;
99
use text_nodes::FontCache;
1010
use vector_types::vector::style::RenderMode;
1111

12-
pub mod resource {
13-
pub use core_types::resource::*;
14-
pub use graphene_resource::*;
15-
}
12+
pub use graphene_resource as resource;
1613

1714
#[cfg(feature = "wgpu")]
1815
#[derive(Debug, Clone, Hash, PartialEq, Eq, DynAny)]

node-graph/libraries/core-types/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ pub mod misc;
1111
pub mod ops;
1212
pub mod registry;
1313
pub mod render_complexity;
14-
pub mod resource;
1514
pub mod transform;
1615
pub mod uuid;
1716
pub mod value;

node-graph/libraries/core-types/src/resource.rs

Lines changed: 0 additions & 54 deletions
This file was deleted.

node-graph/libraries/resources/src/lib.rs

Lines changed: 82 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,68 @@
1-
use core_types::resource::Resource;
21
use core_types::{CacheHash, graphene_hash};
32
use dyn_any::DynAny;
43
use std::collections::HashMap;
5-
use std::fmt;
64
use std::future::Future;
75
use std::hash::Hash;
6+
use std::ops::Deref;
87
use std::pin::Pin;
8+
use std::sync::Arc;
99

10-
pub trait LoadResource: Send + Sync {
11-
fn load(&self, hash: ResourceHash) -> ResourceFuture;
10+
#[derive(Clone, DynAny)]
11+
pub struct Resource {
12+
inner: Arc<dyn AsRef<[u8]> + Send + Sync>,
13+
hash: ResourceHash,
1214
}
1315

14-
pub type ResourceFuture = Pin<Box<dyn Future<Output = Option<Resource>> + Send + 'static>>;
16+
impl Resource {
17+
pub fn new<T: AsRef<[u8]> + Send + Sync + 'static>(data: T) -> Self {
18+
let hash = ResourceHash::from(data.as_ref());
19+
Self { inner: Arc::new(data), hash }
20+
}
1521

16-
pub trait ResourceStorage: LoadResource {
17-
fn store(&mut self, data: &[u8]) -> ResourceHash;
18-
fn contains(&mut self, hash: &ResourceHash) -> bool;
19-
fn garbage_collect(&mut self, used: &[ResourceHash]);
22+
pub fn new_unchecked<T: AsRef<[u8]> + Send + Sync + 'static>(data: T, hash: ResourceHash) -> Self {
23+
Self { inner: Arc::new(data), hash }
24+
}
25+
26+
pub fn hash(&self) -> ResourceHash {
27+
self.hash
28+
}
2029
}
2130

22-
#[repr(transparent)]
23-
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, graphene_hash::CacheHash, PartialOrd, Ord, DynAny)]
24-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25-
pub struct ResourceId(u64);
31+
impl From<&Resource> for Arc<dyn AsRef<[u8]> + Send + Sync> {
32+
fn from(val: &Resource) -> Self {
33+
val.inner.clone()
34+
}
35+
}
2636

27-
impl ResourceId {
28-
pub fn new() -> Self {
29-
Self(core_types::uuid::generate_uuid())
37+
impl Deref for Resource {
38+
type Target = [u8];
39+
40+
fn deref(&self) -> &[u8] {
41+
(*self.inner).as_ref()
3042
}
3143
}
3244

33-
impl std::fmt::Display for ResourceId {
45+
impl AsRef<[u8]> for Resource {
46+
fn as_ref(&self) -> &[u8] {
47+
(*self.inner).as_ref()
48+
}
49+
}
50+
51+
impl std::fmt::Debug for Resource {
3452
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35-
write!(f, "{}", self.0)
53+
f.debug_struct("Resource").field("len", &self.len()).finish()
54+
}
55+
}
56+
57+
impl PartialEq for Resource {
58+
fn eq(&self, other: &Self) -> bool {
59+
self.hash == other.hash
60+
}
61+
}
62+
63+
impl CacheHash for Resource {
64+
fn cache_hash<H: core::hash::Hasher>(&self, state: &mut H) {
65+
self.hash.cache_hash(state);
3666
}
3767
}
3868

@@ -70,8 +100,8 @@ impl From<&ResourceHash> for String {
70100
}
71101
}
72102

73-
impl fmt::Display for ResourceHash {
74-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103+
impl std::fmt::Display for ResourceHash {
104+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75105
f.write_str(&String::from(self))
76106
}
77107
}
@@ -111,8 +141,8 @@ pub enum ResourceHashParseError {
111141
InvalidCharacter { byte: u8, position: usize },
112142
}
113143

114-
impl fmt::Display for ResourceHashParseError {
115-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144+
impl std::fmt::Display for ResourceHashParseError {
145+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116146
match self {
117147
Self::InvalidLength { found } => write!(f, "resource hash must be 64 hex characters, got {found}"),
118148
Self::InvalidCharacter { byte, position } => write!(f, "resource hash contains non-hex byte {byte:#04x} at position {position}"),
@@ -149,7 +179,7 @@ impl<'de> serde::Deserialize<'de> for ResourceHash {
149179
impl<'de> serde::de::Visitor<'de> for ResourceHashVisitor {
150180
type Value = ResourceHash;
151181

152-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
182+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
153183
formatter.write_str("a 64-character hex string or 32 raw bytes")
154184
}
155185

@@ -185,6 +215,35 @@ impl CacheHash for ResourceHash {
185215
}
186216
}
187217

218+
pub trait LoadResource: Send + Sync {
219+
fn load(&self, hash: ResourceHash) -> ResourceFuture;
220+
}
221+
222+
pub type ResourceFuture = Pin<Box<dyn Future<Output = Option<Resource>> + Send + 'static>>;
223+
224+
pub trait ResourceStorage: LoadResource {
225+
fn store(&mut self, data: &[u8]) -> ResourceHash;
226+
fn contains(&mut self, hash: &ResourceHash) -> bool;
227+
fn garbage_collect(&mut self, used: &[ResourceHash]);
228+
}
229+
230+
#[repr(transparent)]
231+
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, graphene_hash::CacheHash, PartialOrd, Ord, DynAny)]
232+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
233+
pub struct ResourceId(u64);
234+
235+
impl ResourceId {
236+
pub fn new() -> Self {
237+
Self(core_types::uuid::generate_uuid())
238+
}
239+
}
240+
241+
impl std::fmt::Display for ResourceId {
242+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243+
write!(f, "{}", self.0)
244+
}
245+
}
246+
188247
pub type DataSources = Box<[DataSource]>;
189248

190249
#[derive(Clone, Debug, PartialEq, Eq)]

node-graph/nodes/raster/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ std = [
1717
"serde",
1818
"dep:core-types",
1919
"dep:dyn-any",
20+
"dep:graphene-resource",
2021
"dep:graphene-hash",
2122
"dep:raster-types",
2223
"dep:vector-types",
@@ -43,6 +44,7 @@ node-macro = { workspace = true }
4344
# Local std dependencies
4445
dyn-any = { workspace = true, optional = true }
4546
core-types = { workspace = true, optional = true }
47+
graphene-resource = { workspace = true, optional = true }
4648
graphene-hash = { workspace = true, optional = true }
4749
raster-types = { workspace = true, optional = true }
4850
vector-types = { workspace = true, optional = true }

0 commit comments

Comments
 (0)