1use crate::{DynamicEntity, DynamicScene};
4use bevy_ecs::entity::Entity;
5use bevy_reflect::{
6 serde::{
7 ReflectDeserializer, TypeRegistrationDeserializer, TypedReflectDeserializer,
8 TypedReflectSerializer,
9 },
10 PartialReflect, ReflectFromReflect, TypeRegistry,
11};
12use bevy_utils::HashSet;
13use core::fmt::Formatter;
14use serde::{
15 de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor},
16 ser::{SerializeMap, SerializeStruct},
17 Deserialize, Deserializer, Serialize, Serializer,
18};
19
20pub const SCENE_STRUCT: &str = "Scene";
22pub const SCENE_RESOURCES: &str = "resources";
24pub const SCENE_ENTITIES: &str = "entities";
26
27pub const ENTITY_STRUCT: &str = "Entity";
29pub const ENTITY_FIELD_COMPONENTS: &str = "components";
31
32pub struct SceneSerializer<'a> {
58 pub scene: &'a DynamicScene,
60 pub registry: &'a TypeRegistry,
62}
63
64impl<'a> SceneSerializer<'a> {
65 pub fn new(scene: &'a DynamicScene, registry: &'a TypeRegistry) -> Self {
72 SceneSerializer { scene, registry }
73 }
74}
75
76impl<'a> Serialize for SceneSerializer<'a> {
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: Serializer,
80 {
81 let mut state = serializer.serialize_struct(SCENE_STRUCT, 2)?;
82 state.serialize_field(
83 SCENE_RESOURCES,
84 &SceneMapSerializer {
85 entries: &self.scene.resources,
86 registry: self.registry,
87 },
88 )?;
89 state.serialize_field(
90 SCENE_ENTITIES,
91 &EntitiesSerializer {
92 entities: &self.scene.entities,
93 registry: self.registry,
94 },
95 )?;
96 state.end()
97 }
98}
99
100pub struct EntitiesSerializer<'a> {
102 pub entities: &'a [DynamicEntity],
104 pub registry: &'a TypeRegistry,
106}
107
108impl<'a> Serialize for EntitiesSerializer<'a> {
109 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110 where
111 S: Serializer,
112 {
113 let mut state = serializer.serialize_map(Some(self.entities.len()))?;
114 for entity in self.entities {
115 state.serialize_entry(
116 &entity.entity,
117 &EntitySerializer {
118 entity,
119 registry: self.registry,
120 },
121 )?;
122 }
123 state.end()
124 }
125}
126
127pub struct EntitySerializer<'a> {
129 pub entity: &'a DynamicEntity,
131 pub registry: &'a TypeRegistry,
133}
134
135impl<'a> Serialize for EntitySerializer<'a> {
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: Serializer,
139 {
140 let mut state = serializer.serialize_struct(ENTITY_STRUCT, 1)?;
141 state.serialize_field(
142 ENTITY_FIELD_COMPONENTS,
143 &SceneMapSerializer {
144 entries: &self.entity.components,
145 registry: self.registry,
146 },
147 )?;
148 state.end()
149 }
150}
151
152pub struct SceneMapSerializer<'a> {
160 pub entries: &'a [Box<dyn PartialReflect>],
162 pub registry: &'a TypeRegistry,
164}
165
166impl<'a> Serialize for SceneMapSerializer<'a> {
167 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
168 where
169 S: Serializer,
170 {
171 let mut state = serializer.serialize_map(Some(self.entries.len()))?;
172 let sorted_entries = {
173 let mut entries = self
174 .entries
175 .iter()
176 .map(|entry| {
177 (
178 entry.get_represented_type_info().unwrap().type_path(),
179 entry.as_partial_reflect(),
180 )
181 })
182 .collect::<Vec<_>>();
183 entries.sort_by_key(|(type_path, _partial_reflect)| *type_path);
184 entries
185 };
186
187 for (type_path, partial_reflect) in sorted_entries {
188 state.serialize_entry(
189 type_path,
190 &TypedReflectSerializer::new(partial_reflect, self.registry),
191 )?;
192 }
193 state.end()
194 }
195}
196
197#[derive(Deserialize)]
198#[serde(field_identifier, rename_all = "lowercase")]
199enum SceneField {
200 Resources,
201 Entities,
202}
203
204#[derive(Deserialize)]
205#[serde(field_identifier, rename_all = "lowercase")]
206enum EntityField {
207 Components,
208}
209
210pub struct SceneDeserializer<'a> {
212 pub type_registry: &'a TypeRegistry,
214}
215
216impl<'a, 'de> DeserializeSeed<'de> for SceneDeserializer<'a> {
217 type Value = DynamicScene;
218
219 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
220 where
221 D: Deserializer<'de>,
222 {
223 deserializer.deserialize_struct(
224 SCENE_STRUCT,
225 &[SCENE_RESOURCES, SCENE_ENTITIES],
226 SceneVisitor {
227 type_registry: self.type_registry,
228 },
229 )
230 }
231}
232
233struct SceneVisitor<'a> {
234 pub type_registry: &'a TypeRegistry,
235}
236
237impl<'a, 'de> Visitor<'de> for SceneVisitor<'a> {
238 type Value = DynamicScene;
239
240 fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
241 formatter.write_str("scene struct")
242 }
243
244 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
245 where
246 A: SeqAccess<'de>,
247 {
248 let resources = seq
249 .next_element_seed(SceneMapDeserializer {
250 registry: self.type_registry,
251 })?
252 .ok_or_else(|| Error::missing_field(SCENE_RESOURCES))?;
253
254 let entities = seq
255 .next_element_seed(SceneEntitiesDeserializer {
256 type_registry: self.type_registry,
257 })?
258 .ok_or_else(|| Error::missing_field(SCENE_ENTITIES))?;
259
260 Ok(DynamicScene {
261 resources,
262 entities,
263 })
264 }
265
266 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
267 where
268 A: MapAccess<'de>,
269 {
270 let mut resources = None;
271 let mut entities = None;
272 while let Some(key) = map.next_key()? {
273 match key {
274 SceneField::Resources => {
275 if resources.is_some() {
276 return Err(Error::duplicate_field(SCENE_RESOURCES));
277 }
278 resources = Some(map.next_value_seed(SceneMapDeserializer {
279 registry: self.type_registry,
280 })?);
281 }
282 SceneField::Entities => {
283 if entities.is_some() {
284 return Err(Error::duplicate_field(SCENE_ENTITIES));
285 }
286 entities = Some(map.next_value_seed(SceneEntitiesDeserializer {
287 type_registry: self.type_registry,
288 })?);
289 }
290 }
291 }
292
293 let resources = resources.ok_or_else(|| Error::missing_field(SCENE_RESOURCES))?;
294 let entities = entities.ok_or_else(|| Error::missing_field(SCENE_ENTITIES))?;
295
296 Ok(DynamicScene {
297 resources,
298 entities,
299 })
300 }
301}
302
303pub struct SceneEntitiesDeserializer<'a> {
305 pub type_registry: &'a TypeRegistry,
307}
308
309impl<'a, 'de> DeserializeSeed<'de> for SceneEntitiesDeserializer<'a> {
310 type Value = Vec<DynamicEntity>;
311
312 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
313 where
314 D: Deserializer<'de>,
315 {
316 deserializer.deserialize_map(SceneEntitiesVisitor {
317 type_registry: self.type_registry,
318 })
319 }
320}
321
322struct SceneEntitiesVisitor<'a> {
323 pub type_registry: &'a TypeRegistry,
324}
325
326impl<'a, 'de> Visitor<'de> for SceneEntitiesVisitor<'a> {
327 type Value = Vec<DynamicEntity>;
328
329 fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
330 formatter.write_str("map of entities")
331 }
332
333 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
334 where
335 A: MapAccess<'de>,
336 {
337 let mut entities = Vec::new();
338 while let Some(entity) = map.next_key::<Entity>()? {
339 let entity = map.next_value_seed(SceneEntityDeserializer {
340 entity,
341 type_registry: self.type_registry,
342 })?;
343 entities.push(entity);
344 }
345
346 Ok(entities)
347 }
348}
349
350pub struct SceneEntityDeserializer<'a> {
352 pub entity: Entity,
354 pub type_registry: &'a TypeRegistry,
356}
357
358impl<'a, 'de> DeserializeSeed<'de> for SceneEntityDeserializer<'a> {
359 type Value = DynamicEntity;
360
361 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
362 where
363 D: Deserializer<'de>,
364 {
365 deserializer.deserialize_struct(
366 ENTITY_STRUCT,
367 &[ENTITY_FIELD_COMPONENTS],
368 SceneEntityVisitor {
369 entity: self.entity,
370 registry: self.type_registry,
371 },
372 )
373 }
374}
375
376struct SceneEntityVisitor<'a> {
377 pub entity: Entity,
378 pub registry: &'a TypeRegistry,
379}
380
381impl<'a, 'de> Visitor<'de> for SceneEntityVisitor<'a> {
382 type Value = DynamicEntity;
383
384 fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
385 formatter.write_str("entities")
386 }
387
388 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
389 where
390 A: SeqAccess<'de>,
391 {
392 let components = seq
393 .next_element_seed(SceneMapDeserializer {
394 registry: self.registry,
395 })?
396 .ok_or_else(|| Error::missing_field(ENTITY_FIELD_COMPONENTS))?;
397
398 Ok(DynamicEntity {
399 entity: self.entity,
400 components,
401 })
402 }
403
404 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
405 where
406 A: MapAccess<'de>,
407 {
408 let mut components = None;
409 while let Some(key) = map.next_key()? {
410 match key {
411 EntityField::Components => {
412 if components.is_some() {
413 return Err(Error::duplicate_field(ENTITY_FIELD_COMPONENTS));
414 }
415
416 components = Some(map.next_value_seed(SceneMapDeserializer {
417 registry: self.registry,
418 })?);
419 }
420 }
421 }
422
423 let components = components
424 .take()
425 .ok_or_else(|| Error::missing_field(ENTITY_FIELD_COMPONENTS))?;
426 Ok(DynamicEntity {
427 entity: self.entity,
428 components,
429 })
430 }
431}
432
433pub struct SceneMapDeserializer<'a> {
435 pub registry: &'a TypeRegistry,
437}
438
439impl<'a, 'de> DeserializeSeed<'de> for SceneMapDeserializer<'a> {
440 type Value = Vec<Box<dyn PartialReflect>>;
441
442 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
443 where
444 D: Deserializer<'de>,
445 {
446 deserializer.deserialize_map(SceneMapVisitor {
447 registry: self.registry,
448 })
449 }
450}
451
452struct SceneMapVisitor<'a> {
453 pub registry: &'a TypeRegistry,
454}
455
456impl<'a, 'de> Visitor<'de> for SceneMapVisitor<'a> {
457 type Value = Vec<Box<dyn PartialReflect>>;
458
459 fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
460 formatter.write_str("map of reflect types")
461 }
462
463 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
464 where
465 A: SeqAccess<'de>,
466 {
467 let mut dynamic_properties = Vec::new();
468 while let Some(entity) = seq.next_element_seed(ReflectDeserializer::new(self.registry))? {
469 dynamic_properties.push(entity);
470 }
471
472 Ok(dynamic_properties)
473 }
474
475 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
476 where
477 A: MapAccess<'de>,
478 {
479 let mut added = HashSet::new();
480 let mut entries = Vec::new();
481 while let Some(registration) =
482 map.next_key_seed(TypeRegistrationDeserializer::new(self.registry))?
483 {
484 if !added.insert(registration.type_id()) {
485 return Err(Error::custom(format_args!(
486 "duplicate reflect type: `{}`",
487 registration.type_info().type_path(),
488 )));
489 }
490
491 let value =
492 map.next_value_seed(TypedReflectDeserializer::new(registration, self.registry))?;
493
494 let value = self
496 .registry
497 .get(registration.type_id())
498 .and_then(|tr| tr.data::<ReflectFromReflect>())
499 .and_then(|fr| fr.from_reflect(value.as_partial_reflect()))
500 .map(PartialReflect::into_partial_reflect)
501 .unwrap_or(value);
502
503 entries.push(value);
504 }
505
506 Ok(entries)
507 }
508}
509
510#[cfg(test)]
511mod tests {
512 use crate::{
513 ron,
514 serde::{SceneDeserializer, SceneSerializer},
515 DynamicScene, DynamicSceneBuilder,
516 };
517 use bevy_ecs::{
518 entity::{Entity, EntityHashMap, VisitEntities, VisitEntitiesMut},
519 prelude::{Component, ReflectComponent, ReflectResource, Resource, World},
520 query::{With, Without},
521 reflect::{AppTypeRegistry, ReflectMapEntities},
522 world::FromWorld,
523 };
524 use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
525 use bincode::Options;
526 use serde::{de::DeserializeSeed, Deserialize, Serialize};
527 use std::io::BufReader;
528
529 #[derive(Component, Reflect, Default)]
530 #[reflect(Component)]
531 struct Foo(i32);
532 #[derive(Component, Reflect, Default)]
533 #[reflect(Component)]
534 struct Bar(i32);
535 #[derive(Component, Reflect, Default)]
536 #[reflect(Component)]
537 struct Baz(i32);
538
539 mod qux {
541 use serde::{de::Error, Deserialize, Deserializer, Serializer};
542
543 pub fn serialize<S>(value: &u32, serializer: S) -> Result<S::Ok, S::Error>
544 where
545 S: Serializer,
546 {
547 serializer.serialize_str(&format!("{:X}", value))
548 }
549
550 pub fn deserialize<'de, D>(deserializer: D) -> Result<u32, D::Error>
551 where
552 D: Deserializer<'de>,
553 {
554 u32::from_str_radix(<&str as Deserialize>::deserialize(deserializer)?, 16)
555 .map_err(Error::custom)
556 }
557 }
558
559 #[derive(Component, Copy, Clone, Reflect, Debug, PartialEq, Serialize, Deserialize)]
560 #[reflect(Component, Serialize, Deserialize)]
561 struct Qux(#[serde(with = "qux")] u32);
562
563 #[derive(Component, Reflect, Default)]
564 #[reflect(Component)]
565 struct MyComponent {
566 foo: [usize; 3],
567 bar: (f32, f32),
568 baz: MyEnum,
569 }
570
571 #[derive(Reflect, Default)]
572 enum MyEnum {
573 #[default]
574 Unit,
575 Tuple(String),
576 Struct {
577 value: u32,
578 },
579 }
580
581 #[derive(Resource, Reflect, Default)]
582 #[reflect(Resource)]
583 struct MyResource {
584 foo: i32,
585 }
586
587 #[derive(Clone, Component, Reflect, PartialEq, VisitEntities, VisitEntitiesMut)]
588 #[reflect(Component, MapEntities, PartialEq)]
589 struct MyEntityRef(Entity);
590
591 impl FromWorld for MyEntityRef {
592 fn from_world(_world: &mut World) -> Self {
593 Self(Entity::PLACEHOLDER)
594 }
595 }
596
597 fn create_world() -> World {
598 let mut world = World::new();
599 let registry = AppTypeRegistry::default();
600 {
601 let mut registry = registry.write();
602 registry.register::<Foo>();
603 registry.register::<Bar>();
604 registry.register::<Baz>();
605 registry.register::<Qux>();
606 registry.register::<MyComponent>();
607 registry.register::<MyEnum>();
608 registry.register::<String>();
609 registry.register_type_data::<String, ReflectSerialize>();
610 registry.register::<[usize; 3]>();
611 registry.register::<(f32, f32)>();
612 registry.register::<MyEntityRef>();
613 registry.register::<Entity>();
614 registry.register::<MyResource>();
615 }
616 world.insert_resource(registry);
617 world
618 }
619
620 #[test]
621 fn should_serialize() {
622 let mut world = create_world();
623
624 let a = world.spawn(Foo(123)).id();
625 let b = world.spawn((Foo(123), Bar(345))).id();
626 let c = world.spawn((Foo(123), Bar(345), Baz(789))).id();
627
628 world.insert_resource(MyResource { foo: 123 });
629
630 let scene = DynamicSceneBuilder::from_world(&world)
631 .extract_entities([a, b, c].into_iter())
632 .extract_resources()
633 .build();
634
635 let expected = r#"(
636 resources: {
637 "bevy_scene::serde::tests::MyResource": (
638 foo: 123,
639 ),
640 },
641 entities: {
642 4294967296: (
643 components: {
644 "bevy_scene::serde::tests::Foo": (123),
645 },
646 ),
647 4294967297: (
648 components: {
649 "bevy_scene::serde::tests::Bar": (345),
650 "bevy_scene::serde::tests::Foo": (123),
651 },
652 ),
653 4294967298: (
654 components: {
655 "bevy_scene::serde::tests::Bar": (345),
656 "bevy_scene::serde::tests::Baz": (789),
657 "bevy_scene::serde::tests::Foo": (123),
658 },
659 ),
660 },
661)"#;
662 let output = scene
663 .serialize(&world.resource::<AppTypeRegistry>().read())
664 .unwrap();
665 assert_eq!(expected, output);
666 }
667
668 #[test]
669 fn should_deserialize() {
670 let world = create_world();
671
672 let input = r#"(
673 resources: {
674 "bevy_scene::serde::tests::MyResource": (
675 foo: 123,
676 ),
677 },
678 entities: {
679 4294967296: (
680 components: {
681 "bevy_scene::serde::tests::Foo": (123),
682 },
683 ),
684 4294967297: (
685 components: {
686 "bevy_scene::serde::tests::Foo": (123),
687 "bevy_scene::serde::tests::Bar": (345),
688 },
689 ),
690 4294967298: (
691 components: {
692 "bevy_scene::serde::tests::Foo": (123),
693 "bevy_scene::serde::tests::Bar": (345),
694 "bevy_scene::serde::tests::Baz": (789),
695 },
696 ),
697 },
698)"#;
699 let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
700 let scene_deserializer = SceneDeserializer {
701 type_registry: &world.resource::<AppTypeRegistry>().read(),
702 };
703 let scene = scene_deserializer.deserialize(&mut deserializer).unwrap();
704
705 assert_eq!(
706 1,
707 scene.resources.len(),
708 "expected `resources` to contain 1 resource"
709 );
710 assert_eq!(
711 3,
712 scene.entities.len(),
713 "expected `entities` to contain 3 entities"
714 );
715
716 let mut map = EntityHashMap::default();
717 let mut dst_world = create_world();
718 scene.write_to_world(&mut dst_world, &mut map).unwrap();
719
720 let my_resource = dst_world.get_resource::<MyResource>();
721 assert!(my_resource.is_some());
722 let my_resource = my_resource.unwrap();
723 assert_eq!(my_resource.foo, 123);
724
725 assert_eq!(3, dst_world.query::<&Foo>().iter(&dst_world).count());
726 assert_eq!(2, dst_world.query::<&Bar>().iter(&dst_world).count());
727 assert_eq!(1, dst_world.query::<&Baz>().iter(&dst_world).count());
728 }
729
730 fn roundtrip_ron(world: &World) -> (DynamicScene, DynamicScene) {
731 let scene = DynamicScene::from_world(world);
732 let registry = world.resource::<AppTypeRegistry>().read();
733 let serialized = scene.serialize(®istry).unwrap();
734 let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
735 let scene_deserializer = SceneDeserializer {
736 type_registry: ®istry,
737 };
738 let deserialized_scene = scene_deserializer.deserialize(&mut deserializer).unwrap();
739 (scene, deserialized_scene)
740 }
741
742 #[test]
743 fn should_roundtrip_with_later_generations_and_obsolete_references() {
744 let mut world = create_world();
745
746 world.spawn_empty().despawn();
747
748 let a = world.spawn_empty().id();
749 let foo = world.spawn(MyEntityRef(a)).insert(Foo(123)).id();
750 world.despawn(a);
751 world.spawn(MyEntityRef(foo)).insert(Bar(123));
752
753 let (scene, deserialized_scene) = roundtrip_ron(&world);
754
755 let mut map = EntityHashMap::default();
756 let mut dst_world = create_world();
757 deserialized_scene
758 .write_to_world(&mut dst_world, &mut map)
759 .unwrap();
760
761 assert_eq!(2, deserialized_scene.entities.len());
762 assert_scene_eq(&scene, &deserialized_scene);
763
764 let bar_to_foo = dst_world
765 .query_filtered::<&MyEntityRef, Without<Foo>>()
766 .get_single(&dst_world)
767 .cloned()
768 .unwrap();
769 let foo = dst_world
770 .query_filtered::<Entity, With<Foo>>()
771 .get_single(&dst_world)
772 .unwrap();
773
774 assert_eq!(foo, bar_to_foo.0);
775 assert!(dst_world
776 .query_filtered::<&MyEntityRef, With<Foo>>()
777 .iter(&dst_world)
778 .all(|r| world.get_entity(r.0).is_err()));
779 }
780
781 #[test]
782 fn should_roundtrip_with_custom_serialization() {
783 let mut world = create_world();
784 let qux = Qux(42);
785 world.spawn(qux);
786
787 let (scene, deserialized_scene) = roundtrip_ron(&world);
788
789 assert_eq!(1, deserialized_scene.entities.len());
790 assert_scene_eq(&scene, &deserialized_scene);
791
792 let mut world = create_world();
793 deserialized_scene
794 .write_to_world(&mut world, &mut EntityHashMap::default())
795 .unwrap();
796 assert_eq!(&qux, world.query::<&Qux>().single(&world));
797 }
798
799 #[test]
800 fn should_roundtrip_postcard() {
801 let mut world = create_world();
802
803 world.spawn(MyComponent {
804 foo: [1, 2, 3],
805 bar: (1.3, 3.7),
806 baz: MyEnum::Tuple("Hello World!".to_string()),
807 });
808
809 let registry = world.resource::<AppTypeRegistry>();
810 let registry = ®istry.read();
811
812 let scene = DynamicScene::from_world(&world);
813
814 let scene_serializer = SceneSerializer::new(&scene, registry);
815 let serialized_scene = postcard::to_allocvec(&scene_serializer).unwrap();
816
817 assert_eq!(
818 vec![
819 0, 1, 128, 128, 128, 128, 16, 1, 37, 98, 101, 118, 121, 95, 115, 99, 101, 110, 101,
820 58, 58, 115, 101, 114, 100, 101, 58, 58, 116, 101, 115, 116, 115, 58, 58, 77, 121,
821 67, 111, 109, 112, 111, 110, 101, 110, 116, 1, 2, 3, 102, 102, 166, 63, 205, 204,
822 108, 64, 1, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33
823 ],
824 serialized_scene
825 );
826
827 let scene_deserializer = SceneDeserializer {
828 type_registry: registry,
829 };
830 let deserialized_scene = scene_deserializer
831 .deserialize(&mut postcard::Deserializer::from_bytes(&serialized_scene))
832 .unwrap();
833
834 assert_eq!(1, deserialized_scene.entities.len());
835 assert_scene_eq(&scene, &deserialized_scene);
836 }
837
838 #[test]
839 fn should_roundtrip_messagepack() {
840 let mut world = create_world();
841
842 world.spawn(MyComponent {
843 foo: [1, 2, 3],
844 bar: (1.3, 3.7),
845 baz: MyEnum::Tuple("Hello World!".to_string()),
846 });
847
848 let registry = world.resource::<AppTypeRegistry>();
849 let registry = ®istry.read();
850
851 let scene = DynamicScene::from_world(&world);
852
853 let scene_serializer = SceneSerializer::new(&scene, registry);
854 let mut buf = Vec::new();
855 let mut ser = rmp_serde::Serializer::new(&mut buf);
856 scene_serializer.serialize(&mut ser).unwrap();
857
858 assert_eq!(
859 vec![
860 146, 128, 129, 207, 0, 0, 0, 1, 0, 0, 0, 0, 145, 129, 217, 37, 98, 101, 118, 121,
861 95, 115, 99, 101, 110, 101, 58, 58, 115, 101, 114, 100, 101, 58, 58, 116, 101, 115,
862 116, 115, 58, 58, 77, 121, 67, 111, 109, 112, 111, 110, 101, 110, 116, 147, 147, 1,
863 2, 3, 146, 202, 63, 166, 102, 102, 202, 64, 108, 204, 205, 129, 165, 84, 117, 112,
864 108, 101, 172, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33
865 ],
866 buf
867 );
868
869 let scene_deserializer = SceneDeserializer {
870 type_registry: registry,
871 };
872 let mut reader = BufReader::new(buf.as_slice());
873
874 let deserialized_scene = scene_deserializer
875 .deserialize(&mut rmp_serde::Deserializer::new(&mut reader))
876 .unwrap();
877
878 assert_eq!(1, deserialized_scene.entities.len());
879 assert_scene_eq(&scene, &deserialized_scene);
880 }
881
882 #[test]
883 fn should_roundtrip_bincode() {
884 let mut world = create_world();
885
886 world.spawn(MyComponent {
887 foo: [1, 2, 3],
888 bar: (1.3, 3.7),
889 baz: MyEnum::Tuple("Hello World!".to_string()),
890 });
891
892 let registry = world.resource::<AppTypeRegistry>();
893 let registry = ®istry.read();
894
895 let scene = DynamicScene::from_world(&world);
896
897 let scene_serializer = SceneSerializer::new(&scene, registry);
898 let serialized_scene = bincode::serialize(&scene_serializer).unwrap();
899
900 assert_eq!(
901 vec![
902 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
903 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 98, 101, 118, 121, 95, 115, 99, 101, 110, 101,
904 58, 58, 115, 101, 114, 100, 101, 58, 58, 116, 101, 115, 116, 115, 58, 58, 77, 121,
905 67, 111, 109, 112, 111, 110, 101, 110, 116, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
906 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 102, 102, 166, 63, 205, 204, 108, 64, 1, 0, 0, 0,
907 12, 0, 0, 0, 0, 0, 0, 0, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33
908 ],
909 serialized_scene
910 );
911
912 let scene_deserializer = SceneDeserializer {
913 type_registry: registry,
914 };
915
916 let deserialized_scene = bincode::DefaultOptions::new()
917 .with_fixint_encoding()
918 .deserialize_seed(scene_deserializer, &serialized_scene)
919 .unwrap();
920
921 assert_eq!(1, deserialized_scene.entities.len());
922 assert_scene_eq(&scene, &deserialized_scene);
923 }
924
925 fn assert_scene_eq(expected: &DynamicScene, received: &DynamicScene) {
927 assert_eq!(
928 expected.entities.len(),
929 received.entities.len(),
930 "entity count did not match",
931 );
932
933 for expected in &expected.entities {
934 let received = received
935 .entities
936 .iter()
937 .find(|dynamic_entity| dynamic_entity.entity == expected.entity)
938 .unwrap_or_else(|| panic!("missing entity (expected: `{:?}`)", expected.entity));
939
940 assert_eq!(expected.entity, received.entity, "entities did not match");
941
942 for expected in &expected.components {
943 let received = received
944 .components
945 .iter()
946 .find(|component| {
947 component.get_represented_type_info().unwrap().type_path()
948 == expected.get_represented_type_info().unwrap().type_path()
949 })
950 .unwrap_or_else(|| {
951 panic!(
952 "missing component (expected: `{}`)",
953 expected.get_represented_type_info().unwrap().type_path()
954 )
955 });
956
957 assert!(
958 expected
959 .reflect_partial_eq(received.as_ref())
960 .unwrap_or_default(),
961 "components did not match: (expected: `{expected:?}`, received: `{received:?}`)",
962 );
963 }
964 }
965 }
966
967 mod assert_scene_eq_tests {
969 use super::*;
970
971 #[test]
972 #[should_panic(expected = "entity count did not match")]
973 fn should_panic_when_entity_count_not_eq() {
974 let mut world = create_world();
975 let scene_a = DynamicScene::from_world(&world);
976
977 world.spawn(MyComponent {
978 foo: [1, 2, 3],
979 bar: (1.3, 3.7),
980 baz: MyEnum::Unit,
981 });
982
983 let scene_b = DynamicScene::from_world(&world);
984
985 assert_scene_eq(&scene_a, &scene_b);
986 }
987
988 #[test]
989 #[should_panic(expected = "components did not match")]
990 fn should_panic_when_components_not_eq() {
991 let mut world = create_world();
992
993 let entity = world
994 .spawn(MyComponent {
995 foo: [1, 2, 3],
996 bar: (1.3, 3.7),
997 baz: MyEnum::Unit,
998 })
999 .id();
1000
1001 let scene_a = DynamicScene::from_world(&world);
1002
1003 world.entity_mut(entity).insert(MyComponent {
1004 foo: [3, 2, 1],
1005 bar: (1.3, 3.7),
1006 baz: MyEnum::Unit,
1007 });
1008
1009 let scene_b = DynamicScene::from_world(&world);
1010
1011 assert_scene_eq(&scene_a, &scene_b);
1012 }
1013
1014 #[test]
1015 #[should_panic(expected = "missing component")]
1016 fn should_panic_when_missing_component() {
1017 let mut world = create_world();
1018
1019 let entity = world
1020 .spawn(MyComponent {
1021 foo: [1, 2, 3],
1022 bar: (1.3, 3.7),
1023 baz: MyEnum::Unit,
1024 })
1025 .id();
1026
1027 let scene_a = DynamicScene::from_world(&world);
1028
1029 world.entity_mut(entity).remove::<MyComponent>();
1030
1031 let scene_b = DynamicScene::from_world(&world);
1032
1033 assert_scene_eq(&scene_a, &scene_b);
1034 }
1035 }
1036}