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)]
pub struct ComponentRegistration {
ty: &'static str,
@ -154,8 +109,7 @@ pub struct 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 {
ty: type_name::<T>(),
comp_serialize_fn: |comp_storage, serialize_fn| {
@ -178,7 +132,6 @@ impl ComponentRegistration {
}
}
#[derive(Serialize, Deserialize)]
struct SerializedArchetypeDescription {
tag_types: Vec<String>,
@ -186,7 +139,6 @@ struct SerializedArchetypeDescription {
}
pub struct SerializeImpl {
pub tag_types: HashMap<String, TagRegistration>,
pub comp_types: HashMap<String, ComponentRegistration>,
pub entity_map: RefCell<HashMap<Entity, uuid::Bytes>>,
}
@ -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<uuid::Bytes, Entity>,
) -> 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<S: Serializer>(
&self,
serializer: S,
_serializer: S,
tag_type: &TagTypeId,
_tag_meta: &TagMeta,
tags: &TagStorage,
_tags: &TagStorage,
) -> 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!(
"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<String, TagRegistration>,
pub comp_types: HashMap<String, ComponentRegistration>,
pub struct DeserializeImpl<'a> {
pub comp_types: &'a HashMap<String, ComponentRegistration>,
pub entity_map: RefCell<HashMap<uuid::Bytes, Entity>>,
}
impl DeserializeImpl {
impl<'a> DeserializeImpl<'a> {
pub fn new(
component_types: HashMap<String, ComponentRegistration>,
tag_types: HashMap<String, TagRegistration>,
component_types: &'a HashMap<String, ComponentRegistration>,
entity_map: RefCell<HashMap<Entity, uuid::Bytes>>,
) -> 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 =
<SerializedArchetypeDescription as Deserialize>::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<(), <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(())
}
fn deserialize_entities<'de, D: Deserializer<'de>>(

View file

@ -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::<Test>()];
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::<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 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);
}