Skip to content

Commit 9164c54

Browse files
committed
Add SerializeReflect
1 parent 19481f2 commit 9164c54

File tree

4 files changed

+305
-127
lines changed

4 files changed

+305
-127
lines changed

crates/bevy_reflect/src/impls/std.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl_reflect_value!(::core::num::NonZeroI8(
200200
Serialize,
201201
Deserialize
202202
));
203-
impl_reflect_value!(::std::sync::Arc<T: Send + Sync>);
203+
impl_reflect_value!(::std::sync::Arc<T: Send + Sync + ?Sized>);
204204

205205
// `Serialize` and `Deserialize` only for platforms supported by serde:
206206
// https://github.com/serde-rs/serde/blob/3ffb86fc70efd3d329519e2dddfa306cc04f167c/serde/src/de/impls.rs#L1732

crates/bevy_reflect/src/serde/mod.rs

Lines changed: 160 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
11
mod de;
22
mod deserialize_reflect;
33
mod ser;
4+
mod serialize_reflect;
45
mod type_data;
56

67
pub use de::*;
78
pub use deserialize_reflect::*;
89
pub use ser::*;
10+
pub use serialize_reflect::*;
911
pub use type_data::*;
1012

1113
#[cfg(test)]
1214
mod tests {
13-
use crate::{self as bevy_reflect, DynamicTupleStruct, ReflectDeserialize, Struct};
15+
use crate::{self as bevy_reflect, DynamicTupleStruct, Struct};
1416
use crate::{
15-
serde::{
16-
DeserializeReflect, ReflectDeserializeReflect, ReflectSerializer,
17-
TypedReflectDeserializer, UntypedReflectDeserializer,
18-
},
17+
serde::{ReflectSerializer, UntypedReflectDeserializer},
1918
type_registry::TypeRegistry,
2019
DynamicStruct, FromReflect, Reflect,
2120
};
22-
use serde::de::{DeserializeSeed, SeqAccess, Visitor};
23-
use serde::{Deserialize, Deserializer};
24-
use std::fmt::Formatter;
21+
use serde::de::DeserializeSeed;
2522

2623
#[test]
2724
fn test_serialization_struct() {
@@ -189,138 +186,196 @@ mod tests {
189186
assert!(expected.reflect_partial_eq(&result).unwrap());
190187
}
191188

192-
#[test]
193-
fn should_deserialize_using_deserialize_reflect() {
194-
#[derive(Reflect, PartialEq, Debug, Deserialize)]
195-
#[reflect(Deserialize)]
196-
enum AnimalType {
197-
Dog,
198-
Cat,
189+
mod type_data {
190+
use super::*;
191+
use crate::from_reflect::FromReflect;
192+
use crate::serde::serialize_reflect::{ReflectSerializeReflect, SerializeReflect};
193+
use crate::serde::{DeserializeReflect, ReflectDeserializeReflect};
194+
use crate::{ReflectFromReflect, TypePath};
195+
use bevy_reflect_derive::reflect_trait;
196+
use core::fmt::{Debug, Formatter};
197+
use serde::de::{SeqAccess, Visitor};
198+
use serde::ser::SerializeSeq;
199+
use serde::{Deserializer, Serializer};
200+
use std::sync::Arc;
201+
202+
#[reflect_trait]
203+
trait Enemy: Reflect + Debug {
204+
fn hp(&self) -> u8;
199205
}
200206

201-
#[derive(Reflect)]
202-
struct Dog {
203-
name: DogName,
207+
// This is needed to support Arc<dyn Enemy>
208+
impl TypePath for dyn Enemy {
209+
fn type_path() -> &'static str {
210+
"dyn bevy_reflect::serde::tests::type_data::Enemy"
211+
}
212+
213+
fn short_type_path() -> &'static str {
214+
"dyn Enemy"
215+
}
204216
}
205217

206-
#[derive(Reflect)]
207-
enum DogName {
208-
Spot,
209-
Fido,
210-
Rex,
218+
#[derive(Reflect, Debug)]
219+
#[reflect(Enemy)]
220+
struct Skeleton(u8);
221+
222+
impl Enemy for Skeleton {
223+
fn hp(&self) -> u8 {
224+
self.0
225+
}
211226
}
212227

213-
#[derive(Reflect)]
214-
struct Cat {
215-
name: CatName,
228+
#[derive(Reflect, Debug)]
229+
#[reflect(Enemy)]
230+
struct Zombie(u8);
231+
232+
impl Enemy for Zombie {
233+
fn hp(&self) -> u8 {
234+
self.0
235+
}
216236
}
217237

218-
#[derive(Reflect)]
219-
enum CatName {
220-
Fluffy,
221-
Snowball,
222-
Luna,
238+
#[derive(Reflect, Debug)]
239+
struct Level {
240+
name: String,
241+
enemies: EnemyList,
223242
}
224243

225-
/// Pet is made up of two fields: the type of animal and the animal itself.
226-
///
227-
/// This allows us to store a type-erased version of our pet,
228-
/// rather than having to define one like this:
229-
///
230-
/// ```
231-
/// # use bevy_reflect::prelude::Reflect;
232-
/// #[derive(Reflect)]
233-
/// struct Pet<T: Reflect>(T);
234-
/// ```
235-
///
236-
/// If we wanted to allow for deserialization of any type,
237-
/// we could replace `AnimalType` with a `String` containing the type name of the animal.
238-
#[derive(Reflect)]
239-
#[reflect(DeserializeReflect)]
240-
#[reflect(from_reflect = false)]
241-
struct Pet(AnimalType, DynamicStruct);
244+
#[derive(Reflect, Debug)]
245+
#[reflect(SerializeReflect, DeserializeReflect)]
246+
struct EnemyList(Vec<Arc<dyn Enemy>>);
247+
248+
impl SerializeReflect for EnemyList {
249+
fn serialize<S>(
250+
&self,
251+
serializer: S,
252+
registry: &TypeRegistry,
253+
) -> Result<S::Ok, S::Error>
254+
where
255+
S: Serializer,
256+
{
257+
let mut state = serializer.serialize_seq(Some(self.0.len()))?;
258+
for enemy in &self.0 {
259+
state.serialize_element(&ReflectSerializer::new(
260+
(**enemy).as_reflect(),
261+
registry,
262+
))?;
263+
}
264+
state.end()
265+
}
266+
}
242267

243-
impl<'de> DeserializeReflect<'de> for Pet {
268+
impl<'de> DeserializeReflect<'de> for EnemyList {
244269
fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
245270
where
246271
D: Deserializer<'de>,
247272
{
248-
struct PetVisitor<'a> {
273+
struct EnemyListVisitor<'a> {
249274
registry: &'a TypeRegistry,
250275
}
251-
impl<'a, 'de> Visitor<'de> for PetVisitor<'a> {
252-
type Value = Pet;
253276

254-
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
255-
write!(formatter, "a pet tuple struct")
277+
impl<'a, 'de> Visitor<'de> for EnemyListVisitor<'a> {
278+
type Value = Vec<Arc<dyn Enemy>>;
279+
280+
fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
281+
write!(formatter, "a list of enemies")
256282
}
257283

258284
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
259285
where
260286
A: SeqAccess<'de>,
261287
{
262-
let kind = seq.next_element::<AnimalType>()?.unwrap();
263-
match kind {
264-
AnimalType::Cat => {
265-
let cat = seq
266-
.next_element_seed(TypedReflectDeserializer::of::<Cat>(
267-
self.registry,
268-
))?
269-
.unwrap()
270-
.take::<DynamicStruct>()
271-
.unwrap();
272-
Ok(Pet(kind, cat))
273-
}
274-
AnimalType::Dog => {
275-
let dog = seq
276-
.next_element_seed(TypedReflectDeserializer::of::<Dog>(
277-
self.registry,
278-
))?
279-
.unwrap()
280-
.take::<DynamicStruct>()
281-
.unwrap();
282-
Ok(Pet(kind, dog))
283-
}
288+
let mut enemies = Vec::new();
289+
while let Some(enemy) =
290+
seq.next_element_seed(UntypedReflectDeserializer::new(self.registry))?
291+
{
292+
let registration = self
293+
.registry
294+
.get_with_type_path(
295+
enemy.get_represented_type_info().unwrap().type_path(),
296+
)
297+
.unwrap();
298+
299+
// 1. Convert any possible dynamic values to concrete ones
300+
let enemy = registration
301+
.data::<ReflectFromReflect>()
302+
.unwrap()
303+
.from_reflect(&*enemy)
304+
.unwrap();
305+
306+
// 2. Convert the concrete value to a boxed trait object
307+
let enemy = registration
308+
.data::<ReflectEnemy>()
309+
.unwrap()
310+
.get_boxed(enemy)
311+
.unwrap();
312+
313+
enemies.push(enemy.into());
284314
}
315+
316+
Ok(enemies)
285317
}
286318
}
287319

288-
deserializer.deserialize_tuple_struct("Pet", 1, PetVisitor { registry })
320+
deserializer
321+
.deserialize_seq(EnemyListVisitor { registry })
322+
.map(EnemyList)
289323
}
290324
}
291325

292-
let mut registry = TypeRegistry::default();
293-
registry.register::<Pet>();
294-
registry.register::<AnimalType>();
295-
registry.register::<Dog>();
296-
registry.register::<DogName>();
297-
registry.register::<Cat>();
298-
registry.register::<CatName>();
299-
300-
let pet = Pet(
301-
AnimalType::Cat,
302-
Cat {
303-
name: CatName::Fluffy,
304-
}
305-
.clone_dynamic(),
306-
);
326+
fn create_registry() -> TypeRegistry {
327+
let mut registry = TypeRegistry::default();
328+
registry.register::<Level>();
329+
registry.register::<EnemyList>();
330+
registry.register::<Skeleton>();
331+
registry.register::<Zombie>();
332+
registry
333+
}
307334

308-
let serializer = ReflectSerializer::new(&pet, &registry);
309-
let serialized = ron::ser::to_string(&serializer).unwrap();
335+
#[test]
336+
fn should_serialize_with_serialize_reflect() {
337+
let registry = create_registry();
310338

311-
let expected = r#"{"bevy_reflect::serde::tests::Pet":(Cat,(name:Fluffy))}"#;
339+
let level = Level {
340+
name: String::from("Level 1"),
341+
enemies: EnemyList(vec![Arc::new(Skeleton(10)), Arc::new(Zombie(20))]),
342+
};
312343

313-
assert_eq!(expected, serialized);
344+
let serializer = ReflectSerializer::new(&level, &registry);
345+
let serialized = ron::ser::to_string(&serializer).unwrap();
314346

315-
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
316-
let reflect_deserializer = UntypedReflectDeserializer::new(&registry);
317-
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
318-
let deserialized = value.take::<Pet>().unwrap();
347+
let expected = r#"{"bevy_reflect::serde::tests::type_data::Level":(name:"Level 1",enemies:[{"bevy_reflect::serde::tests::type_data::Skeleton":(10)},{"bevy_reflect::serde::tests::type_data::Zombie":(20)}])}"#;
319348

320-
assert_eq!(pet.0, deserialized.0);
321-
assert!(pet
322-
.1
323-
.reflect_partial_eq(&deserialized.1)
324-
.unwrap_or_default());
349+
assert_eq!(expected, serialized);
350+
}
351+
352+
#[test]
353+
fn should_deserialize_with_deserialize_reflect() {
354+
let registry = create_registry();
355+
356+
let input = r#"{"bevy_reflect::serde::tests::type_data::Level":(name:"Level 1",enemies:[{"bevy_reflect::serde::tests::type_data::Skeleton":(10)},{"bevy_reflect::serde::tests::type_data::Zombie":(20)}])}"#;
357+
358+
let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
359+
let reflect_deserializer = UntypedReflectDeserializer::new(&registry);
360+
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
361+
362+
let output = Level::from_reflect(&*value).unwrap();
363+
364+
let expected = Level {
365+
name: String::from("Level 1"),
366+
enemies: EnemyList(vec![Arc::new(Skeleton(10)), Arc::new(Zombie(20))]),
367+
};
368+
369+
// Poor man's comparison since we can't derive PartialEq for Arc<dyn Enemy>
370+
assert_eq!(format!("{:?}", expected), format!("{:?}", output));
371+
372+
let unexpected = Level {
373+
name: String::from("Level 1"),
374+
enemies: EnemyList(vec![Arc::new(Skeleton(20)), Arc::new(Zombie(10))]),
375+
};
376+
377+
// Poor man's comparison since we can't derive PartialEq for Arc<dyn Enemy>
378+
assert_ne!(format!("{:?}", unexpected), format!("{:?}", output));
379+
}
325380
}
326381
}

0 commit comments

Comments
 (0)