|
1 | | -use core_types::resource::Resource; |
2 | 1 | use core_types::{CacheHash, graphene_hash}; |
3 | 2 | use dyn_any::DynAny; |
4 | 3 | use std::collections::HashMap; |
5 | | -use std::fmt; |
6 | 4 | use std::future::Future; |
7 | 5 | use std::hash::Hash; |
| 6 | +use std::ops::Deref; |
8 | 7 | use std::pin::Pin; |
| 8 | +use std::sync::Arc; |
9 | 9 |
|
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, |
12 | 14 | } |
13 | 15 |
|
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 | + } |
15 | 21 |
|
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 | + } |
20 | 29 | } |
21 | 30 |
|
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 | +} |
26 | 36 |
|
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() |
30 | 42 | } |
31 | 43 | } |
32 | 44 |
|
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 { |
34 | 52 | 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); |
36 | 66 | } |
37 | 67 | } |
38 | 68 |
|
@@ -70,8 +100,8 @@ impl From<&ResourceHash> for String { |
70 | 100 | } |
71 | 101 | } |
72 | 102 |
|
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 { |
75 | 105 | f.write_str(&String::from(self)) |
76 | 106 | } |
77 | 107 | } |
@@ -111,8 +141,8 @@ pub enum ResourceHashParseError { |
111 | 141 | InvalidCharacter { byte: u8, position: usize }, |
112 | 142 | } |
113 | 143 |
|
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 { |
116 | 146 | match self { |
117 | 147 | Self::InvalidLength { found } => write!(f, "resource hash must be 64 hex characters, got {found}"), |
118 | 148 | 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 { |
149 | 179 | impl<'de> serde::de::Visitor<'de> for ResourceHashVisitor { |
150 | 180 | type Value = ResourceHash; |
151 | 181 |
|
152 | | - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
| 182 | + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { |
153 | 183 | formatter.write_str("a 64-character hex string or 32 raw bytes") |
154 | 184 | } |
155 | 185 |
|
@@ -185,6 +215,35 @@ impl CacheHash for ResourceHash { |
185 | 215 | } |
186 | 216 | } |
187 | 217 |
|
| 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 | + |
188 | 247 | pub type DataSources = Box<[DataSource]>; |
189 | 248 |
|
190 | 249 | #[derive(Clone, Debug, PartialEq, Eq)] |
|
0 commit comments