props: properties no longer directly implement the Serialize trait

This commit is contained in:
Carter Anderson 2020-05-27 00:14:57 -07:00
parent bb56b07973
commit da52b1b034
8 changed files with 117 additions and 32 deletions

View file

@ -147,17 +147,6 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
}
}
impl #impl_generics #bevy_property_path::serde::ser::Serialize for #struct_name#ty_generics {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: #bevy_property_path::serde::ser::Serializer,
{
use #bevy_property_path::serde::ser::SerializeMap;
use #bevy_property_path::serde::Serialize;
#bevy_property_path::MapSerializer::new(self).serialize(serializer)
}
}
impl #impl_generics #bevy_property_path::Property for #struct_name#ty_generics {
#[inline]
fn type_name(&self) -> &str {
@ -205,6 +194,10 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
fn as_properties(&self) -> Option<&dyn #bevy_property_path::Properties> {
Some(self)
}
fn serializable(&self) -> #bevy_property_path::Serializable {
#bevy_property_path::Serializable::Owned(Box::new(#bevy_property_path::MapSerializer::new(self)))
}
}
})
}
@ -256,6 +249,11 @@ pub fn derive_property(input: TokenStream) -> TokenStream {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
#[inline]
fn serializable(&self) -> #bevy_property_path::Serializable {
#bevy_property_path::Serializable::Borrowed(self)
}
}
})
}

View file

@ -1,6 +1,6 @@
use crate::{
Properties, PropertiesType, Property, PropertyIter, PropertyTypeRegistration,
PropertyTypeRegistry,
PropertyTypeRegistry, Serializable,
};
use de::SeqAccess;
use serde::{
@ -183,6 +183,10 @@ impl Property for DynamicProperties {
fn is_sequence(&self) -> bool {
self.properties_type == PropertiesType::Seq
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Serialize for DynamicProperties {
@ -219,14 +223,13 @@ impl<'a> Serialize for MapSerializer<'a> {
if property.is_sequence() {
state.serialize_entry(name, &SeqSerializer { property })?;
} else {
state.serialize_entry(name, property)?;
state.serialize_entry(name, property.serializable().borrow())?;
}
}
state.end()
}
}
// TODO: maybe you can return this as a type erased serializer as Prop::get_serializer()? This would remove the need for explicit Serialize impls
pub struct SeqSerializer<'a> {
pub property: &'a dyn Property,
}
@ -248,7 +251,7 @@ impl<'a> Serialize for SeqSerializer<'a> {
state.serialize_entry("data", &PropertiesSeqSerializer { properties })?;
} else {
state.serialize_entry("seq_value_type", self.property.type_name())?;
state.serialize_entry("data", self.property)?;
state.serialize_entry("data", self.property.serializable().borrow())?;
}
state.end()
}
@ -265,7 +268,7 @@ impl<'a> Serialize for PropertiesSeqSerializer<'a> {
{
let mut state = serializer.serialize_seq(Some(self.properties.prop_len()))?;
for prop in self.properties.iter_props() {
state.serialize_element(prop)?;
state.serialize_element(prop.serializable().borrow())?;
}
state.end()
}
@ -537,7 +540,7 @@ where
));
}
dynamic_properties = map.next_value_seed(PropSeqDeserializer {
property_type_registry: property_type_registry,
property_type_registry,
current_type_name: current_type_name.clone(),
})?;
break;

View file

@ -1,4 +1,4 @@
use crate::{impl_property, Property};
use crate::{impl_property, Property, Serializable};
use glam::{Mat3, Mat4, Quat, Vec2, Vec3};
impl_property!(Vec2);

View file

@ -1,4 +1,4 @@
use crate::{impl_property, Property};
use crate::{impl_property, Property, Serializable};
use legion::prelude::Entity;
impl_property!(Entity);

View file

@ -1,4 +1,4 @@
use crate::Property;
use crate::{Serializable, Property};
use serde::Serialize;
use smallvec::{Array, SmallVec};
use std::any::Any;
@ -39,4 +39,8 @@ where
*self = prop.clone();
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}

View file

@ -1,4 +1,4 @@
use crate::{impl_property, Properties, PropertiesType, Property, PropertyIter};
use crate::{impl_property, Properties, PropertiesType, Property, PropertyIter, SeqSerializer, Serializable};
use serde::Serialize;
use std::{
any::Any,
@ -9,7 +9,7 @@ use std::{
impl<T> Properties for Vec<T>
where
T: Property + Clone + Serialize,
T: Property + Clone,
{
fn prop(&self, _name: &str) -> Option<&dyn Property> {
None
@ -39,7 +39,7 @@ where
impl<T> Property for Vec<T>
where
T: Property + Clone + Serialize,
T: Property + Clone,
{
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
@ -81,6 +81,10 @@ where
fn is_sequence(&self) -> bool {
true
}
fn serializable(&self) -> Serializable {
Serializable::Owned(Box::new(SeqSerializer::new(self)))
}
}
impl_property!(String);
@ -150,6 +154,10 @@ impl Property for usize {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for u64 {
@ -204,6 +212,10 @@ impl Property for u64 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for u32 {
@ -258,6 +270,10 @@ impl Property for u32 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for u16 {
@ -312,6 +328,10 @@ impl Property for u16 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for u8 {
@ -366,6 +386,10 @@ impl Property for u8 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for isize {
@ -420,6 +444,10 @@ impl Property for isize {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for i64 {
@ -474,6 +502,10 @@ impl Property for i64 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for i32 {
@ -528,6 +560,10 @@ impl Property for i32 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for i16 {
@ -582,6 +618,10 @@ impl Property for i16 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for i8 {
@ -636,6 +676,10 @@ impl Property for i8 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for f32 {
@ -674,6 +718,10 @@ impl Property for f32 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
impl Property for f64 {
@ -712,4 +760,8 @@ impl Property for f64 {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}

View file

@ -1,7 +1,23 @@
use crate::Properties;
use std::any::Any;
use erased_serde::Serialize;
pub trait Property: erased_serde::Serialize + Send + Sync + Any + 'static {
pub enum Serializable<'a> {
Owned(Box<dyn Serialize + 'a>),
Borrowed(&'a dyn Serialize),
}
impl<'a> Serializable<'a> {
pub fn borrow(&self) -> &dyn Serialize {
match self {
Serializable::Borrowed(serialize) => serialize,
Serializable::Owned(serialize) => serialize,
}
}
}
pub trait Property: Send + Sync + Any + 'static {
fn type_name(&self) -> &str;
fn any(&self) -> &dyn Any;
fn any_mut(&mut self) -> &mut dyn Any;
@ -14,9 +30,9 @@ pub trait Property: erased_serde::Serialize + Send + Sync + Any + 'static {
fn is_sequence(&self) -> bool {
false
}
}
erased_serde::serialize_trait_object!(Property);
fn serializable(&self) -> Serializable;
}
pub trait PropertyVal {
fn val<T: 'static>(&self) -> Option<&T>;
@ -84,6 +100,10 @@ macro_rules! impl_property {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
};
(SEQUENCE, @$trait_:ident [$($args:ident,)*] where [$($preds:tt)+]) => {
@ -128,6 +148,10 @@ macro_rules! impl_property {
fn is_sequence(&self) -> bool {
true
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
}
};
@ -169,6 +193,10 @@ macro_rules! impl_property {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
}
};

View file

@ -4,7 +4,6 @@ use bevy::{
property::{ron::deserialize_dynamic_properties},
};
use serde::{Deserialize, Serialize};
use bevy_property::{PropertiesSeqSerializer, SeqSerializer};
fn main() {
App::build()
@ -57,8 +56,9 @@ fn setup(property_type_registry: Res<PropertyTypeRegistryContext>) {
test.apply(&patch);
assert_eq!(test.a, 4);
// Properties implement the serde Serialize trait. You don't need to derive it yourself!
let ron_string = serialize_ron(&test).unwrap();
// All properties can be serialized.
// If you #[derive(Properties)] your type doesn't even need to directly implement the Serde trait!
let ron_string = serialize_ron(&test.serializable().borrow()).unwrap();
println!("{}\n", ron_string);
// Dynamic properties can be deserialized
@ -73,20 +73,20 @@ fn setup(property_type_registry: Res<PropertyTypeRegistryContext>) {
// This means you can patch Properties with dynamic properties deserialized from a string
test.apply(&dynamic_properties);
// Properties can also be sequences. Std sequences (Vec, VecDeque) already implement the Properties trait
// Properties can also be sequences.
// Sequences from std::collections (Vec, VecDeque) already implement the Properties trait
let mut seq = vec![1u32, 2u32];
let mut patch = DynamicProperties::seq();
patch.push(Box::new(3u32), None);
seq.apply(&patch);
assert_eq!(seq[0], 3);
let ron_string = serialize_ron(&SeqSerializer { property: &patch} ).unwrap();
let ron_string = serialize_ron(&patch.serializable().borrow()).unwrap();
println!("{}\n", ron_string);
let dynamic_properties =
deserialize_dynamic_properties(&ron_string, &property_type_registry.value.read().unwrap())
.unwrap();
let round_tripped = serialize_ron(&dynamic_properties).unwrap();
println!("{}", round_tripped);
assert_eq!(ron_string, round_tripped);
}