diff --git a/crates/bevy_serialization/src/world.rs b/crates/bevy_serialization/src/world.rs index 989d110d52..548e441a07 100644 --- a/crates/bevy_serialization/src/world.rs +++ b/crates/bevy_serialization/src/world.rs @@ -97,51 +97,6 @@ impl<'de, 'a, T: for<'b> Deserialize<'b> + 'static> Visitor<'de> } } -#[derive(Clone)] -pub struct TagRegistration { - ty: &'static str, - tag_serialize_fn: fn(&TagStorage, &mut dyn FnMut(&dyn erased_serde::Serialize)), - tag_deserialize_fn: fn( - deserializer: &mut dyn erased_serde::Deserializer, - &mut TagStorage, - ) -> Result<(), erased_serde::Error>, - register_tag_fn: fn(&mut ArchetypeDescription), -} - -impl TagRegistration { - pub fn of Deserialize<'de> - + PartialEq - + Clone - + Send - + Sync - + 'static, - >() -> Self { - Self { - ty: type_name::(), - tag_serialize_fn: |tag_storage, serialize_fn| { - // it's safe because we know this is the correct type due to lookup - let slice = unsafe { tag_storage.data_slice::() }; - serialize_fn(&&*slice); - }, - tag_deserialize_fn: |deserializer, tag_storage| { - // TODO implement visitor to avoid allocation of Vec - let tag_vec = as Deserialize>::deserialize(deserializer)?; - for tag in tag_vec { - // Tag types should line up, making this safe - unsafe { - tag_storage.push(tag); - } - } - Ok(()) - }, - register_tag_fn: |desc| { - desc.register_tag::(); - }, - } - } -} - #[derive(Clone)] pub struct ComponentRegistration { ty: &'static str, @@ -154,8 +109,7 @@ pub struct ComponentRegistration { } impl ComponentRegistration { - pub fn of Deserialize<'de> + Send + Sync + 'static>() -> Self - { + pub fn of Deserialize<'de> + Send + Sync + 'static>() -> Self { Self { ty: type_name::(), comp_serialize_fn: |comp_storage, serialize_fn| { @@ -178,7 +132,6 @@ impl ComponentRegistration { } } - #[derive(Serialize, Deserialize)] struct SerializedArchetypeDescription { tag_types: Vec, @@ -186,7 +139,6 @@ struct SerializedArchetypeDescription { } pub struct SerializeImpl { - pub tag_types: HashMap, pub comp_types: HashMap, pub entity_map: RefCell>, } @@ -194,7 +146,6 @@ pub struct SerializeImpl { impl SerializeImpl { pub fn new( component_registrations: &[ComponentRegistration], - tag_registrations: &[TagRegistration], ) -> Self { SerializeImpl { comp_types: HashMap::from_iter( @@ -202,18 +153,12 @@ impl SerializeImpl { .iter() .map(|reg| (reg.ty.to_string(), reg.clone())), ), - tag_types: HashMap::from_iter( - tag_registrations - .iter() - .map(|reg| (reg.ty.to_string(), reg.clone())), - ), entity_map: RefCell::new(HashMap::new()), } } pub fn new_with_map( component_registrations: &[ComponentRegistration], - tag_registrations: &[TagRegistration], entity_map: HashMap, ) -> Self { SerializeImpl { @@ -222,11 +167,6 @@ impl SerializeImpl { .iter() .map(|reg| (reg.ty.to_string(), reg.clone())), ), - tag_types: HashMap::from_iter( - tag_registrations - .iter() - .map(|reg| (reg.ty.to_string(), reg.clone())), - ), entity_map: RefCell::new(HashMap::from_iter( entity_map.into_iter().map(|(uuid, e)| (e, uuid)), )), @@ -235,8 +175,8 @@ impl SerializeImpl { } impl legion::serialize::ser::WorldSerializer for SerializeImpl { - fn can_serialize_tag(&self, ty: &TagTypeId, _meta: &TagMeta) -> bool { - self.tag_types.get(ty.0).is_some() + fn can_serialize_tag(&self, _ty: &TagTypeId, _meta: &TagMeta) -> bool { + false } fn can_serialize_component(&self, ty: &ComponentTypeId, _meta: &ComponentMeta) -> bool { self.comp_types.get(ty.0).is_some() @@ -290,25 +230,11 @@ impl legion::serialize::ser::WorldSerializer for SerializeImpl { } fn serialize_tags( &self, - serializer: S, + _serializer: S, tag_type: &TagTypeId, _tag_meta: &TagMeta, - tags: &TagStorage, + _tags: &TagStorage, ) -> Result { - if let Some(reg) = self.tag_types.get(tag_type.0) { - let result = RefCell::new(None); - let serializer = RefCell::new(Some(serializer)); - { - let mut result_ref = result.borrow_mut(); - (reg.tag_serialize_fn)(tags, &mut |serialize| { - result_ref.replace(erased_serde::serialize( - serialize, - serializer.borrow_mut().take().unwrap(), - )); - }); - } - return result.borrow_mut().take().unwrap(); - } panic!( "received unserializable type {:?}, this should be filtered by can_serialize", tag_type @@ -328,20 +254,17 @@ impl legion::serialize::ser::WorldSerializer for SerializeImpl { } } -pub struct DeserializeImpl { - pub tag_types: HashMap, - pub comp_types: HashMap, +pub struct DeserializeImpl<'a> { + pub comp_types: &'a HashMap, pub entity_map: RefCell>, } -impl DeserializeImpl { +impl<'a> DeserializeImpl<'a> { pub fn new( - component_types: HashMap, - tag_types: HashMap, + component_types: &'a HashMap, entity_map: RefCell>, ) -> Self { DeserializeImpl { - tag_types, comp_types: component_types, // re-use the entity-uuid mapping entity_map: RefCell::new(HashMap::from_iter( @@ -354,7 +277,7 @@ impl DeserializeImpl { } } -impl legion::serialize::de::WorldDeserializer for DeserializeImpl { +impl<'a> legion::serialize::de::WorldDeserializer for DeserializeImpl<'a> { fn deserialize_archetype_description<'de, D: Deserializer<'de>>( &self, deserializer: D, @@ -362,11 +285,7 @@ impl legion::serialize::de::WorldDeserializer for DeserializeImpl { let serialized_desc = ::deserialize(deserializer)?; let mut desc = ArchetypeDescription::default(); - for tag in serialized_desc.tag_types { - if let Some(reg) = self.tag_types.get(&tag) { - (reg.register_tag_fn)(&mut desc); - } - } + for comp in serialized_desc.component_types { if let Some(reg) = self.comp_types.get(&comp) { (reg.register_comp_fn)(&mut desc); @@ -393,17 +312,11 @@ impl legion::serialize::de::WorldDeserializer for DeserializeImpl { fn deserialize_tags<'de, D: Deserializer<'de>>( &self, deserializer: D, - tag_type: &TagTypeId, + _tag_type: &TagTypeId, _tag_meta: &TagMeta, - tags: &mut TagStorage, + _tags: &mut TagStorage, ) -> Result<(), >::Error> { - if let Some(reg) = self.tag_types.get(tag_type.0) { - let mut erased = erased_serde::Deserializer::erase(deserializer); - (reg.tag_deserialize_fn)(&mut erased, tags) - .map_err(<>::Error as serde::de::Error>::custom)?; - } else { - ::deserialize(deserializer)?; - } + ::deserialize(deserializer)?; Ok(()) } fn deserialize_entities<'de, D: Deserializer<'de>>( diff --git a/examples/serializing/serializing.rs b/examples/serializing/serializing.rs index 72c54744ba..bdb4c43cb2 100644 --- a/examples/serializing/serializing.rs +++ b/examples/serializing/serializing.rs @@ -1,6 +1,7 @@ use bevy::{prelude::*, serialization::*}; +use legion::serialize::{de::deserialize, ser::serializable_world}; use serde::{Deserialize, Serialize}; -use ron::ser::{to_string_pretty, PrettyConfig}; + fn main() { App::build() .add_plugin(ScheduleRunnerPlugin::run_once()) @@ -19,38 +20,47 @@ fn setup(world: &mut World, resources: &mut Resources) { let comp_registrations = [ComponentRegistration::of::()]; - let tag_registrations = []; - - let ser_helper = SerializeImpl::new(&comp_registrations, &tag_registrations); - let serializable = legion::serialize::ser::serializable_world(world, &ser_helper); + let ser_helper = SerializeImpl::new(&comp_registrations); + let serializable = serializable_world(world, &ser_helper); + println!("JSON"); let serialized_data = serde_json::to_string(&serializable).unwrap(); - // println!("{}", serialized_data); - let pretty = PrettyConfig { + println!("{}", serialized_data); + println!(); + + println!("RON"); + let pretty = ron::ser::PrettyConfig { depth_limit: 2, separate_tuple_members: true, enumerate_arrays: true, ..Default::default() }; - let s = to_string_pretty(&serializable, pretty).expect("Serialization failed"); + let s = ron::ser::to_string_pretty(&serializable, pretty.clone()).expect("Serialization failed"); println!("{}", s); - let de_helper = DeserializeImpl::new( - ser_helper.comp_types, - ser_helper.tag_types, - ser_helper.entity_map, - ); + println!(); + let universe = resources.get_mut::().unwrap(); + println!("JSON (Round Trip)"); + let de_helper = DeserializeImpl::new(&ser_helper.comp_types, ser_helper.entity_map.clone()); let mut new_world = universe.create_world(); let mut deserializer = serde_json::Deserializer::from_str(&serialized_data); - legion::serialize::de::deserialize(&mut new_world, &de_helper, &mut deserializer).unwrap(); - let ser_helper = SerializeImpl::new_with_map( - &comp_registrations, - &tag_registrations, - de_helper.entity_map.into_inner(), - ); - let serializable = legion::serialize::ser::serializable_world(&new_world, &ser_helper); - + deserialize(&mut new_world, &de_helper, &mut deserializer).unwrap(); + let round_trip_ser_helper = + SerializeImpl::new_with_map(&comp_registrations, de_helper.entity_map.into_inner()); + let serializable = serializable_world(&new_world, &round_trip_ser_helper); let roundtrip_data = serde_json::to_string(&serializable).unwrap(); - // println!("{}", roundtrip_data); + println!("{}", roundtrip_data); assert_eq!(roundtrip_data, serialized_data); + + println!("RON (Round Trip)"); + let de_helper = DeserializeImpl::new(&ser_helper.comp_types, ser_helper.entity_map.clone()); + let mut new_world = universe.create_world(); + let mut deserializer = ron::de::Deserializer::from_str(&s).unwrap(); + deserialize(&mut new_world, &de_helper, &mut deserializer).unwrap(); + let round_trip_ser_helper = + SerializeImpl::new_with_map(&comp_registrations, de_helper.entity_map.into_inner()); + let serializable = serializable_world(&new_world, &round_trip_ser_helper); + let roundtrip_data = ron::ser::to_string_pretty(&serializable, pretty).expect("Serialization failed"); + println!("{}", roundtrip_data); + assert_eq!(roundtrip_data, s); }