Skip to content

Commit e1cb924

Browse files
committed
Add DeserializeReflect trait
Also added the ReflectDeserializeReflect type data
1 parent 3d75210 commit e1cb924

File tree

3 files changed

+255
-3
lines changed

3 files changed

+255
-3
lines changed

crates/bevy_reflect/src/serde/de.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::serde::deserialize_reflect::ReflectDeserializeReflect;
12
use crate::serde::SerializationData;
23
use crate::{
34
ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple,
@@ -355,12 +356,33 @@ pub struct TypedReflectDeserializer<'a> {
355356
}
356357

357358
impl<'a> TypedReflectDeserializer<'a> {
359+
// Creates a new [`TypedReflectDeserializer`] for the given type registration.
358360
pub fn new(registration: &'a TypeRegistration, registry: &'a TypeRegistry) -> Self {
359361
Self {
360362
registration,
361363
registry,
362364
}
363365
}
366+
367+
/// Creates a new [`TypedReflectDeserializer`] for the given type `T`.
368+
///
369+
/// # Panics
370+
///
371+
/// Panics if `T` is not registered in the given [`TypeRegistry`].
372+
pub fn of<T: Reflect>(registry: &'a TypeRegistry) -> Self {
373+
let registration = registry
374+
.get(std::any::TypeId::of::<T>())
375+
.unwrap_or_else(|| {
376+
panic!(
377+
"no registration found for type `{}`",
378+
std::any::type_name::<T>()
379+
)
380+
});
381+
Self {
382+
registration,
383+
registry,
384+
}
385+
}
364386
}
365387

366388
impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
@@ -378,6 +400,11 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
378400
return Ok(value);
379401
}
380402

403+
if let Some(deserialize_reflect) = self.registration.data::<ReflectDeserializeReflect>() {
404+
let value = deserialize_reflect.deserialize(deserializer, self.registry)?;
405+
return Ok(value);
406+
}
407+
381408
match self.registration.type_info() {
382409
TypeInfo::Struct(struct_info) => {
383410
let mut dynamic_struct = deserializer.deserialize_struct(
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use crate::{FromType, Reflect, TypeRegistry};
2+
use serde::{Deserialize, Deserializer};
3+
4+
/// Trait used to provide finer control when deserializing a reflected type with one of
5+
/// the reflection deserializers.
6+
///
7+
/// This trait is the reflection equivalent of `serde`'s [`Deserialize`] trait.
8+
/// The main difference is that this trait provides access to the [`TypeRegistry`],
9+
/// which means that we can use the registry and all its stored type information
10+
/// to deserialize our type.
11+
///
12+
/// This can be useful when writing a custom reflection deserializer where we may
13+
/// want to handle parts of the deserialization process, but temporarily pass control
14+
/// to the standard reflection deserializer for other parts.
15+
///
16+
/// Without this trait and its associated [type data], such a deserializer would have to
17+
/// write out all of the deserialization logic itself, possibly including
18+
/// unnecessary code duplication and trivial implementations.
19+
///
20+
/// # Implementors
21+
///
22+
/// In order for this to work with the reflection deserializers like [`TypedReflectDeserializer`]
23+
/// and [`UntypedReflectDeserializer`], implementors should be sure to register the
24+
/// [`ReflectDeserializeReflect`] type data.
25+
/// This can be done [via the registry] or by adding `#[reflect(DeserializeReflect)]` to
26+
/// the type definition.
27+
///
28+
/// Note that this trait has a blanket implementation for all types that implement
29+
/// [`Reflect`] and [`Deserialize`].
30+
///
31+
/// [type data]: ReflectDeserializeReflect
32+
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
33+
/// [`UntypedReflectDeserializer`]: crate::serde::UntypedReflectDeserializer
34+
/// [via the registry]: TypeRegistry::register_type_data
35+
pub trait DeserializeReflect<'de>: Reflect + Sized {
36+
fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
37+
where
38+
D: Deserializer<'de>;
39+
}
40+
41+
impl<'de, T: Reflect + Deserialize<'de>> DeserializeReflect<'de> for T {
42+
fn deserialize<D>(deserializer: D, _registry: &TypeRegistry) -> Result<Self, D::Error>
43+
where
44+
D: Deserializer<'de>,
45+
{
46+
<T as Deserialize>::deserialize(deserializer)
47+
}
48+
}
49+
50+
/// Type data used to deserialize a [`Reflect`] type with a custom [`DeserializeReflect`] implementation.
51+
#[derive(Clone)]
52+
pub struct ReflectDeserializeReflect {
53+
deserialize: fn(
54+
deserializer: &mut dyn erased_serde::Deserializer,
55+
registry: &TypeRegistry,
56+
) -> Result<Box<dyn Reflect>, erased_serde::Error>,
57+
}
58+
59+
impl ReflectDeserializeReflect {
60+
/// Deserialize a [`Reflect`] type with this type data's custom [`DeserializeReflect`] implementation.
61+
pub fn deserialize<'de, D>(
62+
&self,
63+
deserializer: D,
64+
registry: &TypeRegistry,
65+
) -> Result<Box<dyn Reflect>, D::Error>
66+
where
67+
D: Deserializer<'de>,
68+
{
69+
let mut erased = <dyn erased_serde::Deserializer>::erase(deserializer);
70+
(self.deserialize)(&mut erased, registry)
71+
.map_err(<<D as Deserializer<'de>>::Error as serde::de::Error>::custom)
72+
}
73+
}
74+
75+
impl<T: Reflect + for<'de> DeserializeReflect<'de>> FromType<T> for ReflectDeserializeReflect {
76+
fn from_type() -> Self {
77+
Self {
78+
deserialize: |deserializer, registry| {
79+
Ok(Box::new(T::deserialize(deserializer, registry)?))
80+
},
81+
}
82+
}
83+
}

crates/bevy_reflect/src/serde/mod.rs

Lines changed: 145 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
mod de;
2+
mod deserialize_reflect;
23
mod ser;
34
mod type_data;
45

56
pub use de::*;
7+
pub use deserialize_reflect::*;
68
pub use ser::*;
79
pub use type_data::*;
810

911
#[cfg(test)]
1012
mod tests {
11-
use crate::{self as bevy_reflect, DynamicTupleStruct};
13+
use crate::{self as bevy_reflect, DynamicTupleStruct, ReflectDeserialize, Struct};
1214
use crate::{
13-
serde::{ReflectSerializer, UntypedReflectDeserializer},
15+
serde::{
16+
DeserializeReflect, ReflectDeserializeReflect, ReflectSerializer,
17+
TypedReflectDeserializer, UntypedReflectDeserializer,
18+
},
1419
type_registry::TypeRegistry,
1520
DynamicStruct, Reflect,
1621
};
17-
use serde::de::DeserializeSeed;
22+
use bevy_reflect_derive::FromReflect;
23+
use serde::de::{DeserializeSeed, SeqAccess, Visitor};
24+
use serde::{Deserialize, Deserializer};
25+
use std::fmt::Formatter;
1826

1927
#[test]
2028
fn test_serialization_struct() {
@@ -104,4 +112,138 @@ mod tests {
104112
let serializer = ReflectSerializer::new(&value, &registry);
105113
ron::ser::to_string(&serializer).unwrap();
106114
}
115+
116+
#[test]
117+
fn should_deserialize_using_deserialize_reflect() {
118+
#[derive(Reflect, FromReflect, PartialEq, Debug, Deserialize)]
119+
#[reflect(Deserialize)]
120+
enum AnimalType {
121+
Dog,
122+
Cat,
123+
}
124+
125+
#[derive(Reflect, FromReflect)]
126+
struct Dog {
127+
name: DogName,
128+
}
129+
130+
#[derive(Reflect, FromReflect)]
131+
enum DogName {
132+
Spot,
133+
Fido,
134+
Rex,
135+
}
136+
137+
#[derive(Reflect, FromReflect)]
138+
struct Cat {
139+
name: CatName,
140+
}
141+
142+
#[derive(Reflect, FromReflect)]
143+
enum CatName {
144+
Fluffy,
145+
Snowball,
146+
Luna,
147+
}
148+
149+
/// Pet is made up of two fields: the type of animal and the animal itself.
150+
///
151+
/// This allows us to store a type-erased version of our pet,
152+
/// rather than having to define one like this:
153+
///
154+
/// ```
155+
/// # use bevy_reflect::prelude::Reflect;
156+
/// #[derive(Reflect)]
157+
/// struct Pet<T: Reflect>(T);
158+
/// ```
159+
///
160+
/// If we wanted to allow for deserialization of any type,
161+
/// we could replace `AnimalType` with a `String` containing the type name of the animal.
162+
#[derive(Reflect)]
163+
#[reflect(DeserializeReflect)]
164+
struct Pet(AnimalType, DynamicStruct);
165+
166+
impl<'de> DeserializeReflect<'de> for Pet {
167+
fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
168+
where
169+
D: Deserializer<'de>,
170+
{
171+
struct PetVisitor<'a> {
172+
registry: &'a TypeRegistry,
173+
}
174+
impl<'a, 'de> Visitor<'de> for PetVisitor<'a> {
175+
type Value = Pet;
176+
177+
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
178+
write!(formatter, "a pet tuple struct")
179+
}
180+
181+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
182+
where
183+
A: SeqAccess<'de>,
184+
{
185+
let kind = seq.next_element::<AnimalType>()?.unwrap();
186+
match kind {
187+
AnimalType::Cat => {
188+
let cat = seq
189+
.next_element_seed(TypedReflectDeserializer::of::<Cat>(
190+
self.registry,
191+
))?
192+
.unwrap()
193+
.take::<DynamicStruct>()
194+
.unwrap();
195+
Ok(Pet(kind, cat))
196+
}
197+
AnimalType::Dog => {
198+
let dog = seq
199+
.next_element_seed(TypedReflectDeserializer::of::<Dog>(
200+
self.registry,
201+
))?
202+
.unwrap()
203+
.take::<DynamicStruct>()
204+
.unwrap();
205+
Ok(Pet(kind, dog))
206+
}
207+
}
208+
}
209+
}
210+
211+
deserializer.deserialize_tuple_struct("Pet", 1, PetVisitor { registry })
212+
}
213+
}
214+
215+
let mut registry = TypeRegistry::default();
216+
registry.register::<Pet>();
217+
registry.register::<AnimalType>();
218+
registry.register::<Dog>();
219+
registry.register::<DogName>();
220+
registry.register::<Cat>();
221+
registry.register::<CatName>();
222+
223+
let pet = Pet(
224+
AnimalType::Cat,
225+
Cat {
226+
name: CatName::Fluffy,
227+
}
228+
.clone_dynamic(),
229+
);
230+
231+
let serializer = ReflectSerializer::new(&pet, &registry);
232+
let serialized = ron::ser::to_string(&serializer).unwrap();
233+
234+
let expected = r#"{"bevy_reflect::serde::tests::should_deserialize_using_deserialize_reflect::Pet":(Cat,(name:Fluffy))}"#;
235+
236+
assert_eq!(expected, serialized);
237+
238+
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
239+
let reflect_deserializer = UntypedReflectDeserializer::new(&registry);
240+
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
241+
let deserialized = value.take::<Pet>().unwrap();
242+
243+
assert_eq!(pet.0, deserialized.0);
244+
assert!(pet
245+
.1
246+
.reflect_partial_eq(&deserialized.1)
247+
.unwrap_or_default());
248+
}
107249
}

0 commit comments

Comments
 (0)