1use crate::{DynamicEntity, DynamicScene};
4use bevy_ecs::entity::Entity;
5use bevy_platform::collections::HashSet;
6use bevy_reflect::{
7 serde::{
8 ReflectDeserializer, TypeRegistrationDeserializer, TypedReflectDeserializer,
9 TypedReflectSerializer,
10 },
11 PartialReflect, ReflectFromReflect, TypeRegistry,
12};
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, _)| *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<_>>::default();
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},
519 prelude::{Component, ReflectComponent, ReflectResource, Resource, World},
520 query::{With, Without},
521 reflect::AppTypeRegistry,
522 world::FromWorld,
523 };
524 use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
525 use serde::{de::DeserializeSeed, Deserialize, Serialize};
526 use std::io::BufReader;
527
528 #[derive(Component, Reflect, Default)]
529 #[reflect(Component)]
530 struct Foo(i32);
531 #[derive(Component, Reflect, Default)]
532 #[reflect(Component)]
533 struct Bar(i32);
534 #[derive(Component, Reflect, Default)]
535 #[reflect(Component)]
536 struct Baz(i32);
537
538 mod qux {
540 use serde::{de::Error, Deserialize, Deserializer, Serializer};
541
542 pub fn serialize<S>(value: &u32, serializer: S) -> Result<S::Ok, S::Error>
543 where
544 S: Serializer,
545 {
546 serializer.serialize_str(&format!("{value:X}"))
547 }
548
549 pub fn deserialize<'de, D>(deserializer: D) -> Result<u32, D::Error>
550 where
551 D: Deserializer<'de>,
552 {
553 u32::from_str_radix(<&str as Deserialize>::deserialize(deserializer)?, 16)
554 .map_err(Error::custom)
555 }
556 }
557
558 #[derive(Component, Copy, Clone, Reflect, Debug, PartialEq, Serialize, Deserialize)]
559 #[reflect(Component, Serialize, Deserialize)]
560 struct Qux(#[serde(with = "qux")] u32);
561
562 #[derive(Component, Reflect, Default)]
563 #[reflect(Component)]
564 struct MyComponent {
565 foo: [usize; 3],
566 bar: (f32, f32),
567 baz: MyEnum,
568 }
569
570 #[derive(Reflect, Default)]
571 enum MyEnum {
572 #[default]
573 Unit,
574 Tuple(String),
575 Struct {
576 value: u32,
577 },
578 }
579
580 #[derive(Resource, Reflect, Default)]
581 #[reflect(Resource)]
582 struct MyResource {
583 foo: i32,
584 }
585
586 #[derive(Clone, Component, Reflect, PartialEq)]
587 #[reflect(Component, PartialEq)]
588 struct MyEntityRef(#[entities] Entity);
589
590 impl FromWorld for MyEntityRef {
591 fn from_world(_world: &mut World) -> Self {
592 Self(Entity::PLACEHOLDER)
593 }
594 }
595
596 fn create_world() -> World {
597 let mut world = World::new();
598 let registry = AppTypeRegistry::default();
599 {
600 let mut registry = registry.write();
601 registry.register::<Foo>();
602 registry.register::<Bar>();
603 registry.register::<Baz>();
604 registry.register::<Qux>();
605 registry.register::<MyComponent>();
606 registry.register::<MyEnum>();
607 registry.register::<String>();
608 registry.register_type_data::<String, ReflectSerialize>();
609 registry.register::<[usize; 3]>();
610 registry.register::<(f32, f32)>();
611 registry.register::<MyEntityRef>();
612 registry.register::<Entity>();
613 registry.register::<MyResource>();
614 }
615 world.insert_resource(registry);
616 world
617 }
618
619 #[test]
620 fn should_serialize() {
621 let mut world = create_world();
622
623 let a = world.spawn(Foo(123)).id();
624 let b = world.spawn((Foo(123), Bar(345))).id();
625 let c = world.spawn((Foo(123), Bar(345), Baz(789))).id();
626
627 world.insert_resource(MyResource { foo: 123 });
628
629 let scene = DynamicSceneBuilder::from_world(&world)
630 .extract_entities([a, b, c].into_iter())
631 .extract_resources()
632 .build();
633
634 let expected = r#"(
635 resources: {
636 "bevy_scene::serde::tests::MyResource": (
637 foo: 123,
638 ),
639 },
640 entities: {
641 4294967293: (
642 components: {
643 "bevy_scene::serde::tests::Bar": (345),
644 "bevy_scene::serde::tests::Baz": (789),
645 "bevy_scene::serde::tests::Foo": (123),
646 },
647 ),
648 4294967294: (
649 components: {
650 "bevy_scene::serde::tests::Bar": (345),
651 "bevy_scene::serde::tests::Foo": (123),
652 },
653 ),
654 4294967295: (
655 components: {
656 "bevy_scene::serde::tests::Foo": (123),
657 },
658 ),
659 },
660)"#;
661 let output = scene
662 .serialize(&world.resource::<AppTypeRegistry>().read())
663 .unwrap();
664 assert_eq!(expected, output);
665 }
666
667 #[test]
668 fn should_deserialize() {
669 let world = create_world();
670
671 let input = r#"(
672 resources: {
673 "bevy_scene::serde::tests::MyResource": (
674 foo: 123,
675 ),
676 },
677 entities: {
678 8589934591: (
679 components: {
680 "bevy_scene::serde::tests::Foo": (123),
681 },
682 ),
683 8589934590: (
684 components: {
685 "bevy_scene::serde::tests::Foo": (123),
686 "bevy_scene::serde::tests::Bar": (345),
687 },
688 ),
689 8589934589: (
690 components: {
691 "bevy_scene::serde::tests::Foo": (123),
692 "bevy_scene::serde::tests::Bar": (345),
693 "bevy_scene::serde::tests::Baz": (789),
694 },
695 ),
696 },
697)"#;
698 let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
699 let scene_deserializer = SceneDeserializer {
700 type_registry: &world.resource::<AppTypeRegistry>().read(),
701 };
702 let scene = scene_deserializer.deserialize(&mut deserializer).unwrap();
703
704 assert_eq!(
705 1,
706 scene.resources.len(),
707 "expected `resources` to contain 1 resource"
708 );
709 assert_eq!(
710 3,
711 scene.entities.len(),
712 "expected `entities` to contain 3 entities"
713 );
714
715 let mut map = EntityHashMap::default();
716 let mut dst_world = create_world();
717 scene.write_to_world(&mut dst_world, &mut map).unwrap();
718
719 let my_resource = dst_world.get_resource::<MyResource>();
720 assert!(my_resource.is_some());
721 let my_resource = my_resource.unwrap();
722 assert_eq!(my_resource.foo, 123);
723
724 assert_eq!(3, dst_world.query::<&Foo>().iter(&dst_world).count());
725 assert_eq!(2, dst_world.query::<&Bar>().iter(&dst_world).count());
726 assert_eq!(1, dst_world.query::<&Baz>().iter(&dst_world).count());
727 }
728
729 fn roundtrip_ron(world: &World) -> (DynamicScene, DynamicScene) {
730 let scene = DynamicScene::from_world(world);
731 let registry = world.resource::<AppTypeRegistry>().read();
732 let serialized = scene.serialize(®istry).unwrap();
733 let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
734 let scene_deserializer = SceneDeserializer {
735 type_registry: ®istry,
736 };
737 let deserialized_scene = scene_deserializer.deserialize(&mut deserializer).unwrap();
738 (scene, deserialized_scene)
739 }
740
741 #[test]
742 fn should_roundtrip_with_later_generations_and_obsolete_references() {
743 let mut world = create_world();
744
745 world.spawn_empty().despawn();
746
747 let a = world.spawn_empty().id();
748 let foo = world.spawn(MyEntityRef(a)).insert(Foo(123)).id();
749 world.despawn(a);
750 world.spawn(MyEntityRef(foo)).insert(Bar(123));
751
752 let (scene, deserialized_scene) = roundtrip_ron(&world);
753
754 let mut map = EntityHashMap::default();
755 let mut dst_world = create_world();
756 deserialized_scene
757 .write_to_world(&mut dst_world, &mut map)
758 .unwrap();
759
760 assert_eq!(2, deserialized_scene.entities.len());
761 assert_scene_eq(&scene, &deserialized_scene);
762
763 let bar_to_foo = dst_world
764 .query_filtered::<&MyEntityRef, Without<Foo>>()
765 .single(&dst_world)
766 .cloned()
767 .unwrap();
768 let foo = dst_world
769 .query_filtered::<Entity, With<Foo>>()
770 .single(&dst_world)
771 .unwrap();
772
773 assert_eq!(foo, bar_to_foo.0);
774 assert!(dst_world
775 .query_filtered::<&MyEntityRef, With<Foo>>()
776 .iter(&dst_world)
777 .all(|r| world.get_entity(r.0).is_err()));
778 }
779
780 #[test]
781 fn should_roundtrip_with_custom_serialization() {
782 let mut world = create_world();
783 let qux = Qux(42);
784 world.spawn(qux);
785
786 let (scene, deserialized_scene) = roundtrip_ron(&world);
787
788 assert_eq!(1, deserialized_scene.entities.len());
789 assert_scene_eq(&scene, &deserialized_scene);
790
791 let mut world = create_world();
792 deserialized_scene
793 .write_to_world(&mut world, &mut EntityHashMap::default())
794 .unwrap();
795 assert_eq!(&qux, world.query::<&Qux>().single(&world).unwrap());
796 }
797
798 #[test]
799 fn should_roundtrip_postcard() {
800 let mut world = create_world();
801
802 world.spawn(MyComponent {
803 foo: [1, 2, 3],
804 bar: (1.3, 3.7),
805 baz: MyEnum::Tuple("Hello World!".to_string()),
806 });
807
808 let registry = world.resource::<AppTypeRegistry>();
809 let registry = ®istry.read();
810
811 let scene = DynamicScene::from_world(&world);
812
813 let scene_serializer = SceneSerializer::new(&scene, registry);
814 let serialized_scene = postcard::to_allocvec(&scene_serializer).unwrap();
815
816 assert_eq!(
817 vec![
818 0, 1, 255, 255, 255, 255, 15, 1, 37, 98, 101, 118, 121, 95, 115, 99, 101, 110, 101,
819 58, 58, 115, 101, 114, 100, 101, 58, 58, 116, 101, 115, 116, 115, 58, 58, 77, 121,
820 67, 111, 109, 112, 111, 110, 101, 110, 116, 1, 2, 3, 102, 102, 166, 63, 205, 204,
821 108, 64, 1, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33
822 ],
823 serialized_scene
824 );
825
826 let scene_deserializer = SceneDeserializer {
827 type_registry: registry,
828 };
829 let deserialized_scene = scene_deserializer
830 .deserialize(&mut postcard::Deserializer::from_bytes(&serialized_scene))
831 .unwrap();
832
833 assert_eq!(1, deserialized_scene.entities.len());
834 assert_scene_eq(&scene, &deserialized_scene);
835 }
836
837 #[test]
838 fn should_roundtrip_messagepack() {
839 let mut world = create_world();
840
841 world.spawn(MyComponent {
842 foo: [1, 2, 3],
843 bar: (1.3, 3.7),
844 baz: MyEnum::Tuple("Hello World!".to_string()),
845 });
846
847 let registry = world.resource::<AppTypeRegistry>();
848 let registry = ®istry.read();
849
850 let scene = DynamicScene::from_world(&world);
851
852 let scene_serializer = SceneSerializer::new(&scene, registry);
853 let mut buf = Vec::new();
854 let mut ser = rmp_serde::Serializer::new(&mut buf);
855 scene_serializer.serialize(&mut ser).unwrap();
856
857 assert_eq!(
858 vec![
859 146, 128, 129, 206, 255, 255, 255, 255, 145, 129, 217, 37, 98, 101, 118, 121, 95,
860 115, 99, 101, 110, 101, 58, 58, 115, 101, 114, 100, 101, 58, 58, 116, 101, 115,
861 116, 115, 58, 58, 77, 121, 67, 111, 109, 112, 111, 110, 101, 110, 116, 147, 147, 1,
862 2, 3, 146, 202, 63, 166, 102, 102, 202, 64, 108, 204, 205, 129, 165, 84, 117, 112,
863 108, 101, 172, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33
864 ],
865 buf
866 );
867
868 let scene_deserializer = SceneDeserializer {
869 type_registry: registry,
870 };
871 let mut reader = BufReader::new(buf.as_slice());
872
873 let deserialized_scene = scene_deserializer
874 .deserialize(&mut rmp_serde::Deserializer::new(&mut reader))
875 .unwrap();
876
877 assert_eq!(1, deserialized_scene.entities.len());
878 assert_scene_eq(&scene, &deserialized_scene);
879 }
880
881 #[test]
882 fn should_roundtrip_bincode() {
883 let mut world = create_world();
884
885 world.spawn(MyComponent {
886 foo: [1, 2, 3],
887 bar: (1.3, 3.7),
888 baz: MyEnum::Tuple("Hello World!".to_string()),
889 });
890
891 let registry = world.resource::<AppTypeRegistry>();
892 let registry = ®istry.read();
893
894 let scene = DynamicScene::from_world(&world);
895
896 let config = bincode::config::standard().with_fixed_int_encoding();
897 let scene_serializer = SceneSerializer::new(&scene, registry);
898 let serialized_scene = bincode::serde::encode_to_vec(&scene_serializer, config).unwrap();
899
900 assert_eq!(
901 vec![
902 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1,
903 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 98, 101, 118, 121, 95, 115, 99, 101,
904 110, 101, 58, 58, 115, 101, 114, 100, 101, 58, 58, 116, 101, 115, 116, 115, 58, 58,
905 77, 121, 67, 111, 109, 112, 111, 110, 101, 110, 116, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
906 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 102, 102, 166, 63, 205, 204, 108, 64, 1,
907 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108,
908 100, 33
909 ],
910 serialized_scene
911 );
912
913 let scene_deserializer = SceneDeserializer {
914 type_registry: registry,
915 };
916
917 let (deserialized_scene, _read_bytes) =
918 bincode::serde::seed_decode_from_slice(scene_deserializer, &serialized_scene, config)
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}