|
1 | 1 | mod de; |
2 | 2 | mod deserialize_reflect; |
3 | 3 | mod ser; |
| 4 | +mod serialize_reflect; |
4 | 5 | mod type_data; |
5 | 6 |
|
6 | 7 | pub use de::*; |
7 | 8 | pub use deserialize_reflect::*; |
8 | 9 | pub use ser::*; |
| 10 | +pub use serialize_reflect::*; |
9 | 11 | pub use type_data::*; |
10 | 12 |
|
11 | 13 | #[cfg(test)] |
12 | 14 | mod tests { |
13 | | - use crate::{self as bevy_reflect, DynamicTupleStruct, ReflectDeserialize, Struct}; |
| 15 | + use crate::{self as bevy_reflect, DynamicTupleStruct, Struct}; |
14 | 16 | use crate::{ |
15 | | - serde::{ |
16 | | - DeserializeReflect, ReflectDeserializeReflect, ReflectSerializer, |
17 | | - TypedReflectDeserializer, UntypedReflectDeserializer, |
18 | | - }, |
| 17 | + serde::{ReflectSerializer, UntypedReflectDeserializer}, |
19 | 18 | type_registry::TypeRegistry, |
20 | 19 | DynamicStruct, FromReflect, Reflect, |
21 | 20 | }; |
22 | | - use serde::de::{DeserializeSeed, SeqAccess, Visitor}; |
23 | | - use serde::{Deserialize, Deserializer}; |
24 | | - use std::fmt::Formatter; |
| 21 | + use serde::de::DeserializeSeed; |
25 | 22 |
|
26 | 23 | #[test] |
27 | 24 | fn test_serialization_struct() { |
@@ -189,138 +186,196 @@ mod tests { |
189 | 186 | assert!(expected.reflect_partial_eq(&result).unwrap()); |
190 | 187 | } |
191 | 188 |
|
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; |
199 | 205 | } |
200 | 206 |
|
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 | + } |
204 | 216 | } |
205 | 217 |
|
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 | + } |
211 | 226 | } |
212 | 227 |
|
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 | + } |
216 | 236 | } |
217 | 237 |
|
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, |
223 | 242 | } |
224 | 243 |
|
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 | + } |
242 | 267 |
|
243 | | - impl<'de> DeserializeReflect<'de> for Pet { |
| 268 | + impl<'de> DeserializeReflect<'de> for EnemyList { |
244 | 269 | fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error> |
245 | 270 | where |
246 | 271 | D: Deserializer<'de>, |
247 | 272 | { |
248 | | - struct PetVisitor<'a> { |
| 273 | + struct EnemyListVisitor<'a> { |
249 | 274 | registry: &'a TypeRegistry, |
250 | 275 | } |
251 | | - impl<'a, 'de> Visitor<'de> for PetVisitor<'a> { |
252 | | - type Value = Pet; |
253 | 276 |
|
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") |
256 | 282 | } |
257 | 283 |
|
258 | 284 | fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> |
259 | 285 | where |
260 | 286 | A: SeqAccess<'de>, |
261 | 287 | { |
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()); |
284 | 314 | } |
| 315 | + |
| 316 | + Ok(enemies) |
285 | 317 | } |
286 | 318 | } |
287 | 319 |
|
288 | | - deserializer.deserialize_tuple_struct("Pet", 1, PetVisitor { registry }) |
| 320 | + deserializer |
| 321 | + .deserialize_seq(EnemyListVisitor { registry }) |
| 322 | + .map(EnemyList) |
289 | 323 | } |
290 | 324 | } |
291 | 325 |
|
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 | + } |
307 | 334 |
|
308 | | - let serializer = ReflectSerializer::new(&pet, ®istry); |
309 | | - let serialized = ron::ser::to_string(&serializer).unwrap(); |
| 335 | + #[test] |
| 336 | + fn should_serialize_with_serialize_reflect() { |
| 337 | + let registry = create_registry(); |
310 | 338 |
|
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 | + }; |
312 | 343 |
|
313 | | - assert_eq!(expected, serialized); |
| 344 | + let serializer = ReflectSerializer::new(&level, ®istry); |
| 345 | + let serialized = ron::ser::to_string(&serializer).unwrap(); |
314 | 346 |
|
315 | | - let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap(); |
316 | | - let reflect_deserializer = UntypedReflectDeserializer::new(®istry); |
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)}])}"#; |
319 | 348 |
|
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(®istry); |
| 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 | + } |
325 | 380 | } |
326 | 381 | } |
0 commit comments