diff --git a/crates/bevy_property/bevy_property_derive/src/lib.rs b/crates/bevy_property/bevy_property_derive/src/lib.rs index c57cf1b4d4..8e2f7f9e85 100644 --- a/crates/bevy_property/bevy_property_derive/src/lib.rs +++ b/crates/bevy_property/bevy_property_derive/src/lib.rs @@ -203,7 +203,7 @@ pub fn derive_properties(input: TokenStream) -> TokenStream { } fn serializable(&self) -> #bevy_property_path::Serializable { - #bevy_property_path::Serializable::Owned(Box::new(#bevy_property_path::MapSerializer::new(self))) + #bevy_property_path::Serializable::Owned(Box::new(#bevy_property_path::property_serde::MapSerializer::new(self))) } } }) diff --git a/crates/bevy_property/src/dynamic_properties.rs b/crates/bevy_property/src/dynamic_properties.rs index 21b80ad5e5..b635eb7a29 100644 --- a/crates/bevy_property/src/dynamic_properties.rs +++ b/crates/bevy_property/src/dynamic_properties.rs @@ -1,14 +1,5 @@ -use crate::{ - Properties, PropertiesType, Property, PropertyIter, - PropertyTypeRegistry, Serializable, -}; -use de::SeqAccess; -use serde::{ - de::{self, DeserializeSeed, MapAccess, Visitor}, - ser::{SerializeMap, SerializeSeq}, - Serialize, -}; -use std::{any::Any, borrow::Cow, cell::RefCell, collections::HashMap, rc::Rc}; +use crate::{Properties, PropertiesType, Property, PropertyIter, Serializable}; +use std::{any::Any, borrow::Cow, collections::HashMap}; pub struct DynamicProperties { pub type_name: String, @@ -188,372 +179,3 @@ impl Property for DynamicProperties { Serializable::Borrowed(self) } } - -impl Serialize for DynamicProperties { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self.properties_type { - PropertiesType::Map => MapSerializer::new(self).serialize(serializer), - PropertiesType::Seq => SeqSerializer::new(self).serialize(serializer), - } - } -} - -pub struct MapSerializer<'a> { - pub properties: &'a dyn Properties, -} - -impl<'a> MapSerializer<'a> { - pub fn new(properties: &'a dyn Properties) -> Self { - MapSerializer { properties } - } -} - -impl<'a> Serialize for MapSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_map(Some(self.properties.prop_len()))?; - state.serialize_entry("type", self.properties.type_name())?; - for (index, property) in self.properties.iter_props().enumerate() { - let name = self.properties.prop_name(index).unwrap(); - if property.is_sequence() { - state.serialize_entry(name, &SeqSerializer { property })?; - } else { - state.serialize_entry(name, property.serializable().borrow())?; - } - } - state.end() - } -} - -pub struct SeqSerializer<'a> { - pub property: &'a dyn Property, -} - -impl<'a> SeqSerializer<'a> { - pub fn new(property: &'a dyn Property) -> Self { - SeqSerializer { property } - } -} - -impl<'a> Serialize for SeqSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_map(Some(2))?; - if let Some(properties) = self.property.as_properties() { - state.serialize_entry("seq_type", self.property.type_name())?; - state.serialize_entry("data", &PropertiesSeqSerializer { properties })?; - } else { - state.serialize_entry("seq_value_type", self.property.type_name())?; - state.serialize_entry("data", self.property.serializable().borrow())?; - } - state.end() - } -} - -pub struct PropertiesSeqSerializer<'a> { - pub properties: &'a dyn Properties, -} - -impl<'a> Serialize for PropertiesSeqSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_seq(Some(self.properties.prop_len()))?; - for prop in self.properties.iter_props() { - state.serialize_element(prop.serializable().borrow())?; - } - state.end() - } -} - -pub struct DynamicPropertiesDeserializer<'a> { - pub registry: &'a PropertyTypeRegistry, - pub current_type_name: Rc>>, -} - -impl<'a, 'de> DeserializeSeed<'de> for DynamicPropertiesDeserializer<'a> { - type Value = DynamicProperties; - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_map(DynamicPropertyMapVisiter { - registry: self.registry, - current_type_name: self.current_type_name, - }) - } -} - -pub struct DynamicPropertyMapVisiter<'a> { - registry: &'a PropertyTypeRegistry, - current_type_name: Rc>>, -} - -impl<'a, 'de> Visitor<'de> for DynamicPropertyMapVisiter<'a> { - type Value = DynamicProperties; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("properties map") - } - - fn visit_map(self, map: V) -> Result - where - V: MapAccess<'de>, - { - visit_map(map, self.registry, self.current_type_name) - } -} -pub struct PropertyDeserializer<'a> { - pub registry: &'a PropertyTypeRegistry, - pub current_type_name: Rc>>, -} - -impl<'a, 'de> DeserializeSeed<'de> for PropertyDeserializer<'a> { - type Value = Box; - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(AnyPropVisiter { - property_type_registry: self.registry, - current_type_name: self.current_type_name, - }) - } -} - -pub struct PropSeqDeserializer<'a> { - registry: &'a PropertyTypeRegistry, - current_type_name: Rc>>, -} - -impl<'a, 'de> DeserializeSeed<'de> for PropSeqDeserializer<'a> { - type Value = DynamicProperties; - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_seq(PropSeqVisiter { - registry: self.registry, - current_type_name: self.current_type_name.clone(), - }) - } -} - -pub struct PropSeqVisiter<'a> { - registry: &'a PropertyTypeRegistry, - current_type_name: Rc>>, -} - -impl<'a, 'de> Visitor<'de> for PropSeqVisiter<'a> { - type Value = DynamicProperties; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("property value") - } - - fn visit_seq(self, mut seq: V) -> Result - where - V: SeqAccess<'de>, - { - let mut dynamic_properties = DynamicProperties::seq(); - while let Some(prop) = seq.next_element_seed(PropertyDeserializer { - registry: self.registry, - current_type_name: self.current_type_name.clone(), - })? { - dynamic_properties.push(prop, None); - } - Ok(dynamic_properties) - } -} - -pub struct MapValueDeserializer<'a> { - registry: &'a PropertyTypeRegistry, - current_type_name: Rc>>, -} - -impl<'a, 'de> DeserializeSeed<'de> for MapValueDeserializer<'a> { - type Value = Box; - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - if self.current_type_name.borrow().is_some() { - let registration = { - let current_type_name = self.current_type_name.borrow(); - let type_name = current_type_name.as_ref().unwrap(); - self.registry - .get_short(type_name) - .ok_or_else(|| { - de::Error::custom(format!("TypeRegistration is missing for {}", type_name)) - })? - }; - let mut erased = erased_serde::Deserializer::erase(deserializer); - (registration.deserialize)(&mut erased, self.registry) - .map_err(<>::Error as serde::de::Error>::custom) - } else { - deserializer.deserialize_any(AnyPropVisiter { - property_type_registry: self.registry, - current_type_name: self.current_type_name, - }) - } - } -} - -struct AnyPropVisiter<'a> { - property_type_registry: &'a PropertyTypeRegistry, - current_type_name: Rc>>, -} - -impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> { - type Value = Box; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("property value") - } - - fn visit_u8(self, v: u8) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_bool(self, v: bool) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_u16(self, v: u16) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_u32(self, v: u32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_u64(self, v: u64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_i8(self, v: i8) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_i16(self, v: i16) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_i32(self, v: i32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_i64(self, v: i64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_f32(self, v: f32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_f64(self, v: f64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_string(self, v: String) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } - - fn visit_str(self, v: &str) -> Result - where - E: de::Error, - { - Ok(Box::new(v.to_string())) - } - - fn visit_map(self, map: V) -> Result - where - V: MapAccess<'de>, - { - Ok(Box::new(visit_map(map, self.property_type_registry, self.current_type_name)?)) - } -} - -fn visit_map<'a, 'de, V>( - mut map: V, - property_type_registry: &'a PropertyTypeRegistry, - current_type_name: Rc>>, -) -> Result -where - V: MapAccess<'de>, -{ - let mut dynamic_properties = DynamicProperties::map(); - let mut type_name: Option = None; - let mut is_seq = false; - // TODO: support seq_value_type - while let Some(key) = map.next_key::()? { - if key == "type" { - type_name = Some(map.next_value()?); - } else if key == "seq_type" { - type_name = Some(map.next_value()?); - is_seq = true; - } else if is_seq { - if key != "data" { - return Err(de::Error::custom( - "seq_type must be immediately followed by a data field", - )); - } - dynamic_properties = map.next_value_seed(PropSeqDeserializer { - registry: property_type_registry, - current_type_name: current_type_name.clone(), - })?; - break; - } else { - let prop = map.next_value_seed(MapValueDeserializer { - registry: property_type_registry, - current_type_name: current_type_name.clone(), - })?; - dynamic_properties.set_box(&key, prop); - } - } - - let type_name = type_name.ok_or_else(|| de::Error::missing_field("type"))?; - dynamic_properties.type_name = type_name.to_string(); - Ok(dynamic_properties) -} \ No newline at end of file diff --git a/crates/bevy_property/src/impl_property_std.rs b/crates/bevy_property/src/impl_property_std.rs index 91e5fccab7..aa5455eed9 100644 --- a/crates/bevy_property/src/impl_property_std.rs +++ b/crates/bevy_property/src/impl_property_std.rs @@ -1,4 +1,4 @@ -use crate::{impl_property, Properties, PropertiesType, Property, PropertyIter, SeqSerializer, Serializable}; +use crate::{impl_property, Properties, PropertiesType, Property, PropertyIter, Serializable, property_serde::SeqSerializer}; use serde::{Serialize, Deserialize}; use std::{ any::Any, diff --git a/crates/bevy_property/src/lib.rs b/crates/bevy_property/src/lib.rs index b70d1bed85..9512e936e0 100644 --- a/crates/bevy_property/src/lib.rs +++ b/crates/bevy_property/src/lib.rs @@ -7,6 +7,7 @@ mod impl_property_smallvec; mod impl_property_glam; mod impl_property_legion; pub mod ron; +pub mod property_serde; pub use property::*; pub use properties::*; diff --git a/crates/bevy_property/src/property_serde.rs b/crates/bevy_property/src/property_serde.rs new file mode 100644 index 0000000000..98f18c6839 --- /dev/null +++ b/crates/bevy_property/src/property_serde.rs @@ -0,0 +1,380 @@ +use crate::{DynamicProperties, Properties, PropertiesType, Property, PropertyTypeRegistry}; +use de::SeqAccess; +use serde::{ + de::{self, DeserializeSeed, MapAccess, Visitor}, + ser::{SerializeMap, SerializeSeq}, + Serialize, +}; +use std::{cell::RefCell, rc::Rc}; + +impl Serialize for DynamicProperties { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self.properties_type { + PropertiesType::Map => MapSerializer::new(self).serialize(serializer), + PropertiesType::Seq => SeqSerializer::new(self).serialize(serializer), + } + } +} + +pub struct DynamicPropertiesDeserializer<'a> { + pub registry: &'a PropertyTypeRegistry, + pub current_type_name: Rc>>, +} + +impl<'a, 'de> DeserializeSeed<'de> for DynamicPropertiesDeserializer<'a> { + type Value = DynamicProperties; + fn deserialize(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_map(DynamicPropertyMapVisiter { + registry: self.registry, + current_type_name: self.current_type_name, + }) + } +} + +pub struct DynamicPropertyMapVisiter<'a> { + registry: &'a PropertyTypeRegistry, + current_type_name: Rc>>, +} + +impl<'a, 'de> Visitor<'de> for DynamicPropertyMapVisiter<'a> { + type Value = DynamicProperties; + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("properties map") + } + + fn visit_map(self, map: V) -> Result + where + V: MapAccess<'de>, + { + visit_map(map, self.registry, self.current_type_name) + } +} + +pub struct MapSerializer<'a> { + pub properties: &'a dyn Properties, +} + +impl<'a> MapSerializer<'a> { + pub fn new(properties: &'a dyn Properties) -> Self { + MapSerializer { properties } + } +} + +impl<'a> Serialize for MapSerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_map(Some(self.properties.prop_len()))?; + state.serialize_entry("type", self.properties.type_name())?; + for (index, property) in self.properties.iter_props().enumerate() { + let name = self.properties.prop_name(index).unwrap(); + if property.is_sequence() { + state.serialize_entry(name, &SeqSerializer { property })?; + } else { + state.serialize_entry(name, property.serializable().borrow())?; + } + } + state.end() + } +} + +pub struct SeqSerializer<'a> { + pub property: &'a dyn Property, +} + +impl<'a> SeqSerializer<'a> { + pub fn new(property: &'a dyn Property) -> Self { + SeqSerializer { property } + } +} + +impl<'a> Serialize for SeqSerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_map(Some(2))?; + if let Some(properties) = self.property.as_properties() { + state.serialize_entry("seq_type", self.property.type_name())?; + state.serialize_entry("data", &PropertiesSeqSerializer { properties })?; + } else { + state.serialize_entry("seq_value_type", self.property.type_name())?; + state.serialize_entry("data", self.property.serializable().borrow())?; + } + state.end() + } +} + +pub struct PropertiesSeqSerializer<'a> { + pub properties: &'a dyn Properties, +} + +impl<'a> Serialize for PropertiesSeqSerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_seq(Some(self.properties.prop_len()))?; + for prop in self.properties.iter_props() { + state.serialize_element(prop.serializable().borrow())?; + } + state.end() + } +} + +pub struct PropertyDeserializer<'a> { + pub registry: &'a PropertyTypeRegistry, + pub current_type_name: Rc>>, +} + +impl<'a, 'de> DeserializeSeed<'de> for PropertyDeserializer<'a> { + type Value = Box; + fn deserialize(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_any(AnyPropVisiter { + property_type_registry: self.registry, + current_type_name: self.current_type_name, + }) + } +} + +pub struct PropSeqDeserializer<'a> { + registry: &'a PropertyTypeRegistry, + current_type_name: Rc>>, +} + +impl<'a, 'de> DeserializeSeed<'de> for PropSeqDeserializer<'a> { + type Value = DynamicProperties; + fn deserialize(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_seq(PropSeqVisiter { + registry: self.registry, + current_type_name: self.current_type_name.clone(), + }) + } +} + +pub struct PropSeqVisiter<'a> { + registry: &'a PropertyTypeRegistry, + current_type_name: Rc>>, +} + +impl<'a, 'de> Visitor<'de> for PropSeqVisiter<'a> { + type Value = DynamicProperties; + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("property value") + } + + fn visit_seq(self, mut seq: V) -> Result + where + V: SeqAccess<'de>, + { + let mut dynamic_properties = DynamicProperties::seq(); + while let Some(prop) = seq.next_element_seed(PropertyDeserializer { + registry: self.registry, + current_type_name: self.current_type_name.clone(), + })? { + dynamic_properties.push(prop, None); + } + Ok(dynamic_properties) + } +} + +pub struct MapValueDeserializer<'a> { + registry: &'a PropertyTypeRegistry, + current_type_name: Rc>>, +} + +impl<'a, 'de> DeserializeSeed<'de> for MapValueDeserializer<'a> { + type Value = Box; + fn deserialize(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + if self.current_type_name.borrow().is_some() { + let registration = { + let current_type_name = self.current_type_name.borrow(); + let type_name = current_type_name.as_ref().unwrap(); + self.registry.get_short(type_name).ok_or_else(|| { + de::Error::custom(format!("TypeRegistration is missing for {}", type_name)) + })? + }; + let mut erased = erased_serde::Deserializer::erase(deserializer); + (registration.deserialize)(&mut erased, self.registry) + .map_err(<>::Error as serde::de::Error>::custom) + } else { + deserializer.deserialize_any(AnyPropVisiter { + property_type_registry: self.registry, + current_type_name: self.current_type_name, + }) + } + } +} + +struct AnyPropVisiter<'a> { + property_type_registry: &'a PropertyTypeRegistry, + current_type_name: Rc>>, +} + +impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> { + type Value = Box; + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("property value") + } + + fn visit_u8(self, v: u8) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_bool(self, v: bool) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_u16(self, v: u16) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_u32(self, v: u32) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_u64(self, v: u64) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_i8(self, v: i8) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_i16(self, v: i16) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_i32(self, v: i32) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_i64(self, v: i64) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_f32(self, v: f32) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_f64(self, v: f64) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_string(self, v: String) -> Result + where + E: de::Error, + { + Ok(Box::new(v)) + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Ok(Box::new(v.to_string())) + } + + fn visit_map(self, map: V) -> Result + where + V: MapAccess<'de>, + { + Ok(Box::new(visit_map( + map, + self.property_type_registry, + self.current_type_name, + )?)) + } +} + +fn visit_map<'a, 'de, V>( + mut map: V, + property_type_registry: &'a PropertyTypeRegistry, + current_type_name: Rc>>, +) -> Result +where + V: MapAccess<'de>, +{ + let mut dynamic_properties = DynamicProperties::map(); + let mut type_name: Option = None; + let mut is_seq = false; + // TODO: support seq_value_type + while let Some(key) = map.next_key::()? { + if key == "type" { + type_name = Some(map.next_value()?); + } else if key == "seq_type" { + type_name = Some(map.next_value()?); + is_seq = true; + } else if is_seq { + if key != "data" { + return Err(de::Error::custom( + "seq_type must be immediately followed by a data field", + )); + } + dynamic_properties = map.next_value_seed(PropSeqDeserializer { + registry: property_type_registry, + current_type_name: current_type_name.clone(), + })?; + break; + } else { + let prop = map.next_value_seed(MapValueDeserializer { + registry: property_type_registry, + current_type_name: current_type_name.clone(), + })?; + dynamic_properties.set_box(&key, prop); + } + } + + let type_name = type_name.ok_or_else(|| de::Error::missing_field("type"))?; + dynamic_properties.type_name = type_name.to_string(); + Ok(dynamic_properties) +} diff --git a/crates/bevy_property/src/ron.rs b/crates/bevy_property/src/ron.rs index cd6ef798a5..ed9d5742b0 100644 --- a/crates/bevy_property/src/ron.rs +++ b/crates/bevy_property/src/ron.rs @@ -1,9 +1,14 @@ +use crate::{ + property_serde::DynamicPropertiesDeserializer, DynamicProperties, PropertyTypeRegistry, +}; use ron::de::Deserializer; -use std::{cell::RefCell, rc::Rc}; -use crate::{DynamicPropertiesDeserializer, PropertyTypeRegistry, DynamicProperties}; use serde::de::DeserializeSeed; +use std::{cell::RefCell, rc::Rc}; -pub fn deserialize_dynamic_properties(ron_string: &str, property_type_registry: &PropertyTypeRegistry) -> Result { +pub fn deserialize_dynamic_properties( + ron_string: &str, + property_type_registry: &PropertyTypeRegistry, +) -> Result { let mut deserializer = Deserializer::from_str(&ron_string).unwrap(); let last_type_name = Rc::new(RefCell::new(None)); let mut callback = |ident: &Option<&[u8]>| { @@ -16,4 +21,4 @@ pub fn deserialize_dynamic_properties(ron_string: &str, property_type_registry: registry: &property_type_registry, }; dynamic_properties_deserializer.deserialize(&mut deserializer) -} \ No newline at end of file +} diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index d1402a8f65..ba25a669ba 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -1,6 +1,6 @@ use crate::{Entity, Scene}; use anyhow::Result; -use bevy_property::{DynamicProperties, DynamicPropertiesDeserializer, PropertyTypeRegistry}; +use bevy_property::{DynamicProperties, PropertyTypeRegistry, property_serde::DynamicPropertiesDeserializer}; use serde::{ de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor}, Deserialize, Serialize,