remove tag serialization. round trip ron example

This commit is contained in:
Carter Anderson 2020-05-19 13:22:14 -07:00
parent 3710196fdb
commit fb140ce4b0
2 changed files with 46 additions and 123 deletions

View File

@ -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<T: Serialize
+ for<'de> Deserialize<'de>
+ PartialEq
+ Clone
+ Send
+ Sync
+ 'static,
>() -> Self {
Self {
ty: type_name::<T>(),
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::<T>() };
serialize_fn(&&*slice);
},
tag_deserialize_fn: |deserializer, tag_storage| {
// TODO implement visitor to avoid allocation of Vec
let tag_vec = <Vec<T> 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::<T>();
},
}
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct ComponentRegistration { pub struct ComponentRegistration {
ty: &'static str, ty: &'static str,
@ -154,8 +109,7 @@ pub struct ComponentRegistration {
} }
impl ComponentRegistration { impl ComponentRegistration {
pub fn of<T: Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static>() -> Self pub fn of<T: Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static>() -> Self {
{
Self { Self {
ty: type_name::<T>(), ty: type_name::<T>(),
comp_serialize_fn: |comp_storage, serialize_fn| { comp_serialize_fn: |comp_storage, serialize_fn| {
@ -178,7 +132,6 @@ impl ComponentRegistration {
} }
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct SerializedArchetypeDescription { struct SerializedArchetypeDescription {
tag_types: Vec<String>, tag_types: Vec<String>,
@ -186,7 +139,6 @@ struct SerializedArchetypeDescription {
} }
pub struct SerializeImpl { pub struct SerializeImpl {
pub tag_types: HashMap<String, TagRegistration>,
pub comp_types: HashMap<String, ComponentRegistration>, pub comp_types: HashMap<String, ComponentRegistration>,
pub entity_map: RefCell<HashMap<Entity, uuid::Bytes>>, pub entity_map: RefCell<HashMap<Entity, uuid::Bytes>>,
} }
@ -194,7 +146,6 @@ pub struct SerializeImpl {
impl SerializeImpl { impl SerializeImpl {
pub fn new( pub fn new(
component_registrations: &[ComponentRegistration], component_registrations: &[ComponentRegistration],
tag_registrations: &[TagRegistration],
) -> Self { ) -> Self {
SerializeImpl { SerializeImpl {
comp_types: HashMap::from_iter( comp_types: HashMap::from_iter(
@ -202,18 +153,12 @@ impl SerializeImpl {
.iter() .iter()
.map(|reg| (reg.ty.to_string(), reg.clone())), .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()), entity_map: RefCell::new(HashMap::new()),
} }
} }
pub fn new_with_map( pub fn new_with_map(
component_registrations: &[ComponentRegistration], component_registrations: &[ComponentRegistration],
tag_registrations: &[TagRegistration],
entity_map: HashMap<uuid::Bytes, Entity>, entity_map: HashMap<uuid::Bytes, Entity>,
) -> Self { ) -> Self {
SerializeImpl { SerializeImpl {
@ -222,11 +167,6 @@ impl SerializeImpl {
.iter() .iter()
.map(|reg| (reg.ty.to_string(), reg.clone())), .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: RefCell::new(HashMap::from_iter(
entity_map.into_iter().map(|(uuid, e)| (e, uuid)), entity_map.into_iter().map(|(uuid, e)| (e, uuid)),
)), )),
@ -235,8 +175,8 @@ impl SerializeImpl {
} }
impl legion::serialize::ser::WorldSerializer for SerializeImpl { impl legion::serialize::ser::WorldSerializer for SerializeImpl {
fn can_serialize_tag(&self, ty: &TagTypeId, _meta: &TagMeta) -> bool { fn can_serialize_tag(&self, _ty: &TagTypeId, _meta: &TagMeta) -> bool {
self.tag_types.get(ty.0).is_some() false
} }
fn can_serialize_component(&self, ty: &ComponentTypeId, _meta: &ComponentMeta) -> bool { fn can_serialize_component(&self, ty: &ComponentTypeId, _meta: &ComponentMeta) -> bool {
self.comp_types.get(ty.0).is_some() self.comp_types.get(ty.0).is_some()
@ -290,25 +230,11 @@ impl legion::serialize::ser::WorldSerializer for SerializeImpl {
} }
fn serialize_tags<S: Serializer>( fn serialize_tags<S: Serializer>(
&self, &self,
serializer: S, _serializer: S,
tag_type: &TagTypeId, tag_type: &TagTypeId,
_tag_meta: &TagMeta, _tag_meta: &TagMeta,
tags: &TagStorage, _tags: &TagStorage,
) -> Result<S::Ok, S::Error> { ) -> Result<S::Ok, S::Error> {
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!( panic!(
"received unserializable type {:?}, this should be filtered by can_serialize", "received unserializable type {:?}, this should be filtered by can_serialize",
tag_type tag_type
@ -328,20 +254,17 @@ impl legion::serialize::ser::WorldSerializer for SerializeImpl {
} }
} }
pub struct DeserializeImpl { pub struct DeserializeImpl<'a> {
pub tag_types: HashMap<String, TagRegistration>, pub comp_types: &'a HashMap<String, ComponentRegistration>,
pub comp_types: HashMap<String, ComponentRegistration>,
pub entity_map: RefCell<HashMap<uuid::Bytes, Entity>>, pub entity_map: RefCell<HashMap<uuid::Bytes, Entity>>,
} }
impl DeserializeImpl { impl<'a> DeserializeImpl<'a> {
pub fn new( pub fn new(
component_types: HashMap<String, ComponentRegistration>, component_types: &'a HashMap<String, ComponentRegistration>,
tag_types: HashMap<String, TagRegistration>,
entity_map: RefCell<HashMap<Entity, uuid::Bytes>>, entity_map: RefCell<HashMap<Entity, uuid::Bytes>>,
) -> Self { ) -> Self {
DeserializeImpl { DeserializeImpl {
tag_types,
comp_types: component_types, comp_types: component_types,
// re-use the entity-uuid mapping // re-use the entity-uuid mapping
entity_map: RefCell::new(HashMap::from_iter( 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>>( fn deserialize_archetype_description<'de, D: Deserializer<'de>>(
&self, &self,
deserializer: D, deserializer: D,
@ -362,11 +285,7 @@ impl legion::serialize::de::WorldDeserializer for DeserializeImpl {
let serialized_desc = let serialized_desc =
<SerializedArchetypeDescription as Deserialize>::deserialize(deserializer)?; <SerializedArchetypeDescription as Deserialize>::deserialize(deserializer)?;
let mut desc = ArchetypeDescription::default(); 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 { for comp in serialized_desc.component_types {
if let Some(reg) = self.comp_types.get(&comp) { if let Some(reg) = self.comp_types.get(&comp) {
(reg.register_comp_fn)(&mut desc); (reg.register_comp_fn)(&mut desc);
@ -393,17 +312,11 @@ impl legion::serialize::de::WorldDeserializer for DeserializeImpl {
fn deserialize_tags<'de, D: Deserializer<'de>>( fn deserialize_tags<'de, D: Deserializer<'de>>(
&self, &self,
deserializer: D, deserializer: D,
tag_type: &TagTypeId, _tag_type: &TagTypeId,
_tag_meta: &TagMeta, _tag_meta: &TagMeta,
tags: &mut TagStorage, _tags: &mut TagStorage,
) -> Result<(), <D as Deserializer<'de>>::Error> { ) -> Result<(), <D as Deserializer<'de>>::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(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)?;
} else {
<IgnoredAny>::deserialize(deserializer)?; <IgnoredAny>::deserialize(deserializer)?;
}
Ok(()) Ok(())
} }
fn deserialize_entities<'de, D: Deserializer<'de>>( fn deserialize_entities<'de, D: Deserializer<'de>>(

View File

@ -1,6 +1,7 @@
use bevy::{prelude::*, serialization::*}; use bevy::{prelude::*, serialization::*};
use legion::serialize::{de::deserialize, ser::serializable_world};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ron::ser::{to_string_pretty, PrettyConfig};
fn main() { fn main() {
App::build() App::build()
.add_plugin(ScheduleRunnerPlugin::run_once()) .add_plugin(ScheduleRunnerPlugin::run_once())
@ -19,38 +20,47 @@ fn setup(world: &mut World, resources: &mut Resources) {
let comp_registrations = [ComponentRegistration::of::<Test>()]; let comp_registrations = [ComponentRegistration::of::<Test>()];
let tag_registrations = []; let ser_helper = SerializeImpl::new(&comp_registrations);
let serializable = serializable_world(world, &ser_helper);
let ser_helper = SerializeImpl::new(&comp_registrations, &tag_registrations); println!("JSON");
let serializable = legion::serialize::ser::serializable_world(world, &ser_helper);
let serialized_data = serde_json::to_string(&serializable).unwrap(); let serialized_data = serde_json::to_string(&serializable).unwrap();
// println!("{}", serialized_data); println!("{}", serialized_data);
let pretty = PrettyConfig { println!();
println!("RON");
let pretty = ron::ser::PrettyConfig {
depth_limit: 2, depth_limit: 2,
separate_tuple_members: true, separate_tuple_members: true,
enumerate_arrays: true, enumerate_arrays: true,
..Default::default() ..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); println!("{}", s);
let de_helper = DeserializeImpl::new( println!();
ser_helper.comp_types,
ser_helper.tag_types,
ser_helper.entity_map,
);
let universe = resources.get_mut::<Universe>().unwrap(); let universe = resources.get_mut::<Universe>().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 new_world = universe.create_world();
let mut deserializer = serde_json::Deserializer::from_str(&serialized_data); let mut deserializer = serde_json::Deserializer::from_str(&serialized_data);
legion::serialize::de::deserialize(&mut new_world, &de_helper, &mut deserializer).unwrap(); deserialize(&mut new_world, &de_helper, &mut deserializer).unwrap();
let ser_helper = SerializeImpl::new_with_map( let round_trip_ser_helper =
&comp_registrations, SerializeImpl::new_with_map(&comp_registrations, de_helper.entity_map.into_inner());
&tag_registrations, let serializable = serializable_world(&new_world, &round_trip_ser_helper);
de_helper.entity_map.into_inner(),
);
let serializable = legion::serialize::ser::serializable_world(&new_world, &ser_helper);
let roundtrip_data = serde_json::to_string(&serializable).unwrap(); let roundtrip_data = serde_json::to_string(&serializable).unwrap();
// println!("{}", roundtrip_data); println!("{}", roundtrip_data);
assert_eq!(roundtrip_data, serialized_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);
} }