bevy_reflect: Fix dynamic type serialization (#10103)
# Objective Fixes #10086 ## Solution Instead of serializing via `DynamicTypePath::reflect_type_path`, now uses the `TypePath` found on the `TypeInfo` returned by `Reflect::get_represented_type_info`. This issue was happening because the dynamic types implement `TypePath` themselves and do not (and cannot) forward their proxy's `TypePath` data. The solution was to access the proxy's type information in order to get the correct `TypePath` data. ## Changed - The `Debug` impl for `TypePathTable` now includes output for all fields.
This commit is contained in:
parent
71329fe0c2
commit
01b910a148
@ -8,7 +8,7 @@ pub use type_data::*;
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{self as bevy_reflect, DynamicTupleStruct};
|
use crate::{self as bevy_reflect, DynamicTupleStruct, Struct};
|
||||||
use crate::{
|
use crate::{
|
||||||
serde::{ReflectSerializer, UntypedReflectDeserializer},
|
serde::{ReflectSerializer, UntypedReflectDeserializer},
|
||||||
type_registry::TypeRegistry,
|
type_registry::TypeRegistry,
|
||||||
@ -94,8 +94,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "cannot get type info for bevy_reflect::DynamicStruct")]
|
#[should_panic(
|
||||||
fn unproxied_dynamic_should_not_serialize() {
|
expected = "cannot serialize dynamic value without represented type: bevy_reflect::DynamicStruct"
|
||||||
|
)]
|
||||||
|
fn should_not_serialize_unproxied_dynamic() {
|
||||||
let registry = TypeRegistry::default();
|
let registry = TypeRegistry::default();
|
||||||
|
|
||||||
let mut value = DynamicStruct::default();
|
let mut value = DynamicStruct::default();
|
||||||
@ -104,4 +106,36 @@ mod tests {
|
|||||||
let serializer = ReflectSerializer::new(&value, ®istry);
|
let serializer = ReflectSerializer::new(&value, ®istry);
|
||||||
ron::ser::to_string(&serializer).unwrap();
|
ron::ser::to_string(&serializer).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_roundtrip_proxied_dynamic() {
|
||||||
|
#[derive(Reflect)]
|
||||||
|
struct TestStruct {
|
||||||
|
a: i32,
|
||||||
|
b: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut registry = TypeRegistry::default();
|
||||||
|
registry.register::<TestStruct>();
|
||||||
|
|
||||||
|
let value: DynamicStruct = TestStruct { a: 123, b: 456 }.clone_dynamic();
|
||||||
|
|
||||||
|
let serializer = ReflectSerializer::new(&value, ®istry);
|
||||||
|
|
||||||
|
let expected = r#"{"bevy_reflect::serde::tests::TestStruct":(a:123,b:456)}"#;
|
||||||
|
let result = ron::ser::to_string(&serializer).unwrap();
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
|
let mut deserializer = ron::de::Deserializer::from_str(&result).unwrap();
|
||||||
|
let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
|
||||||
|
|
||||||
|
let expected = value.clone_value();
|
||||||
|
let result = reflect_deserializer
|
||||||
|
.deserialize(&mut deserializer)
|
||||||
|
.unwrap()
|
||||||
|
.take::<DynamicStruct>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(expected.reflect_partial_eq(&result).unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,22 @@ impl<'a> Serialize for ReflectSerializer<'a> {
|
|||||||
{
|
{
|
||||||
let mut state = serializer.serialize_map(Some(1))?;
|
let mut state = serializer.serialize_map(Some(1))?;
|
||||||
state.serialize_entry(
|
state.serialize_entry(
|
||||||
self.value.reflect_type_path(),
|
self.value
|
||||||
|
.get_represented_type_info()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
if self.value.is_dynamic() {
|
||||||
|
Error::custom(format_args!(
|
||||||
|
"cannot serialize dynamic value without represented type: {}",
|
||||||
|
self.value.reflect_type_path()
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Error::custom(format_args!(
|
||||||
|
"cannot get type info for {}",
|
||||||
|
self.value.reflect_type_path()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})?
|
||||||
|
.type_path(),
|
||||||
&TypedReflectSerializer::new(self.value, self.registry),
|
&TypedReflectSerializer::new(self.value, self.registry),
|
||||||
)?;
|
)?;
|
||||||
state.end()
|
state.end()
|
||||||
|
@ -183,6 +183,10 @@ impl fmt::Debug for TypePathTable {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("TypePathVtable")
|
f.debug_struct("TypePathVtable")
|
||||||
.field("type_path", &self.type_path)
|
.field("type_path", &self.type_path)
|
||||||
|
.field("short_type_path", &(self.short_type_path)())
|
||||||
|
.field("type_ident", &(self.type_ident)())
|
||||||
|
.field("crate_name", &(self.crate_name)())
|
||||||
|
.field("module_path", &(self.module_path)())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user