remove tag serialization. round trip ron example
This commit is contained in:
parent
3710196fdb
commit
fb140ce4b0
@ -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) {
|
<IgnoredAny>::deserialize(deserializer)?;
|
||||||
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)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn deserialize_entities<'de, D: Deserializer<'de>>(
|
fn deserialize_entities<'de, D: Deserializer<'de>>(
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user