Conversation
fdbe638 to
e8a0c79
Compare
|
It seems surprising that this doesn't work either, currently. That you need the original type information to de/serialize any dynamic types: #[derive(Reflect)]
#[reflect(from_reflect = false)]
struct TestStruct {
a: i32,
b: DynamicStruct,
}
fn main() {
let mut registry = TypeRegistry::default();
registry.register::<TestStruct>();
let mut dyn_struct = DynamicStruct::default();
dyn_struct.insert("c", 456.0);
let my_struct = TestStruct {
a: 123,
// b: OtherStruct { c: 456.0 }.clone_dynamic(),
b: dyn_struct,
};
let reflect_serializer = ReflectSerializer::new(&my_struct, ®istry);
let output = ron::to_string(&reflect_serializer).unwrap();
}Results in: "type |
The reason this doesn't work is because there is no associated type for This could be a lot of information depending on how much nested data It might be something we do, but it would be a much larger and more controversial change. On top of that, the exact format and manner in which we serialize that type information will likely need proper design. |
| .unwrap_err(); | ||
| assert_eq!( | ||
| error, | ||
| ron::Error::Message( |
There was a problem hiding this comment.
Should we really assert the message? Wouldn't a matches! here do the work?
There was a problem hiding this comment.
This test is specifically checking that the debug stack correctly handles dynamic types. And the way we check this is the error message
Objective
Say we have the following code:
Using the
ReflectSerializer, we can serialize this to get the following output:However, if we try to deserialize this output, we get hit with an error:
It's understandable why this errors: we can't deserialize the
DynamicStructbecause we don't know what type it represents......or do we?
Solution
This PR makes it so that nested dynamic proxies are serialized as a type map so that we can easily deserialize it back into a dynamic type.
What do I mean by "nested dynamic proxies"? Well, "dynamic proxies" here refers to the fact that these are dynamic types (e.g.
DynamicStruct,DynamicArray, etc.) that contain theTypeInfoand structure of a concrete type, thus proxying (or representing) that concrete type.For example, a
DynamicListcontaining theTypeInfoofVec<i32>would be a proxy of aVec<i32>.And I'm using "nested" to imply that these dynamic types are embedded within another type. Serializing and deserializing a dynamic type as the root already works. It's when the dynamic type is nested as a struct field or list element that it doesn't work.
By serializing a dynamic type as a type map, we give the deserializer knowledge of how to deserialize the dynamic data.
So if we serialize our data again, we get this output:
With the type information embedded, the deserializer can then know that we need to deserialize a
DynamicStructwith the structure ofOtherStruct.Future Work
Originally, I wanted to explore making dynamic types implement
FromReflectby simply calling.clone_dynamic()on them.However, I feel like that would be a lot more controversial (if it even worked), so I thought it would be best to save that for a future PR.
Testing
You can test locally by running:
Showcase
You can now serialize and deserialize nested dynamic type data!
Migration Guide
The serialized representation of dynamic types have changed. Dynamic types will now serialize as a type map rather than just as the type itself.
{ "my_crate::MyStruct": ( - dynamic_struct_field: ( - c: 1.23, - ), + dynamic_struct_field: { + "my_crate::MyOtherStruct": ( + c: 1.23, + ), + }, ), }Note that this only affects types where they are strongly-typed as a dynamic type. For example,
Vec<MyStruct>would not be affected, butVec<DynamicTuple>would be affected.