Serializing resource handles

This commit is contained in:
b-guild
2025-10-17 13:08:40 -07:00
parent f433968e62
commit e3546e1a8b
2 changed files with 47 additions and 6 deletions
+31 -5
View File
@@ -39,6 +39,7 @@ use crate::{
};
use fxhash::FxHashSet;
pub use fyrox_core as core;
use serde::{Deserialize, Serialize};
use std::{
any::Any,
error::Error,
@@ -197,7 +198,12 @@ where
/// ## Default State
///
/// Default state of the resource will be [`ResourceState::Ok`] with `T::default`.
#[derive(Reflect)]
#[derive(Reflect, Serialize, Deserialize)]
#[serde(
bound = "T: TypedResourceData",
from = "UntypedResource",
into = "UntypedResource"
)]
pub struct Resource<T: Debug> {
untyped: UntypedResource,
#[reflect(hidden)]
@@ -448,10 +454,12 @@ where
{
#[inline]
fn from(untyped: UntypedResource) -> Self {
assert_eq!(
untyped.type_uuid(),
Some(<T as TypeUuidProvider>::type_uuid())
);
if let Some(type_uuid) = untyped.type_uuid() {
let expected = <T as TypeUuidProvider>::type_uuid();
if type_uuid != expected {
panic!("Resource type mismatch. Expected: {expected}. Found: {type_uuid}");
}
}
Self {
untyped,
phantom: Default::default(),
@@ -834,6 +842,24 @@ mod tests {
}
}
#[test]
fn test_serialize() {
let uuid = uuid!("6d1aadb5-42e1-485b-910b-fa4d81b61855");
let typed = Resource::<MyData>::from(uuid);
let untyped = UntypedResource::from(uuid);
let s = ron::ser::to_string(&typed).unwrap();
assert_eq!(&ron::ser::to_string(&uuid).unwrap(), &s);
assert_eq!(&ron::ser::to_string(&untyped).unwrap(), &s);
let output_uuid = ron::de::from_str::<Uuid>(&s).unwrap();
assert_eq!(output_uuid, uuid);
let untyped = ron::de::from_str::<UntypedResource>(&s).unwrap();
assert_eq!(untyped.resource_uuid(), uuid);
assert_eq!(untyped.kind(), ResourceKind::External);
let output = ron::de::from_str::<Resource<MyData>>(&s).unwrap();
assert_eq!(output.resource_uuid(), uuid);
assert_eq!(output.kind(), ResourceKind::External);
}
#[test]
fn test_registry_scan() {
write_test_resources(TEST_FOLDER1, 0..2);
+16 -1
View File
@@ -37,6 +37,7 @@ use fyrox_core::io::FileError;
use fyrox_core::log::Log;
use fyrox_core::parking_lot::MutexGuard;
use fyrox_core::SafeLock;
use serde::{Deserialize, Serialize};
use std::fmt::Write;
use std::{
error::Error,
@@ -451,10 +452,24 @@ impl Visit for ResourceHeader {
/// that the resource is in default state. This is a trade-off to prevent wrapping internals into
/// `Option`, that in some cases could lead to convoluted code with lots of `unwrap`s and state
/// assumptions.
#[derive(Default, Clone, Reflect, TypeUuidProvider)]
#[derive(Default, Clone, Reflect, TypeUuidProvider, Deserialize)]
#[serde(from = "Uuid")]
#[type_uuid(id = "21613484-7145-4d1c-87d8-62fa767560ab")]
pub struct UntypedResource(pub Arc<Mutex<ResourceHeader>>);
impl Serialize for UntypedResource {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let header = self.lock();
if header.kind == ResourceKind::Embedded {
panic!("Embedded resources cannot be serialized.");
}
header.uuid.serialize(serializer)
}
}
impl Visit for UntypedResource {
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
let result = self.visit_with_type_uuid(name, None, visitor);