props: remove need for explicit serde::Deserialize impl. replace impl_property macro_rules with proc_macro_fn

This commit is contained in:
Carter Anderson 2020-05-27 11:13:57 -07:00
parent 4bc3772749
commit 76adb888d3
11 changed files with 224 additions and 231 deletions

View file

@ -1,7 +1,6 @@
use bevy_property::{Property, Properties};
use bevy_property::{Property, Properties, DeserializeProperty};
use legion::storage::Component;
use serde::Deserialize;
use crate::{PropertyTypeRegistryContext, ComponentRegistryContext};
use bevy_app::{FromResources, AppBuilder};
@ -11,7 +10,7 @@ pub trait RegisterComponent {
T: Properties + Component + FromResources;
fn register_property_type<T>(&mut self) -> &mut Self
where
T: Property + for<'de> Deserialize<'de>;
T: Property + DeserializeProperty;
}
impl RegisterComponent for AppBuilder {
@ -31,7 +30,7 @@ impl RegisterComponent for AppBuilder {
fn register_property_type<T>(&mut self) -> &mut Self
where
T: Property + for<'de> Deserialize<'de>,
T: Property + DeserializeProperty,
{
{
let registry_context = self

View file

@ -5,8 +5,15 @@ mod modules;
use darling::FromMeta;
use modules::{get_modules, get_path};
use proc_macro::TokenStream;
use proc_macro_crate::crate_name;
use quote::quote;
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Index, Member, punctuated::Punctuated};
use syn::{
parse::Parse,
parse_macro_input,
punctuated::Punctuated,
token::{Comma, Where},
Data, DataStruct, DeriveInput, Field, Fields, Generics, Ident, Index, Member,
};
#[derive(FromMeta, Debug, Default)]
struct PropAttributeArgs {
@ -152,7 +159,7 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
#[inline]
fn any(&self) -> &dyn std::any::Any {
self
@ -254,6 +261,144 @@ pub fn derive_property(input: TokenStream) -> TokenStream {
fn serializable(&self) -> #bevy_property_path::Serializable {
#bevy_property_path::Serializable::Borrowed(self)
}
}
impl #impl_generics #bevy_property_path::DeserializeProperty for #struct_name#ty_generics {
fn deserialize(
deserializer: &mut dyn #bevy_property_path::erased_serde::Deserializer,
property_type_registry: &#bevy_property_path::PropertyTypeRegistry) ->
Result<Box<dyn #bevy_property_path::Property>, #bevy_property_path::erased_serde::Error> {
let property = <#struct_name#ty_generics as Deserialize>::deserialize(deserializer)?;
Ok(Box::new(property))
}
}
})
}
#[derive(Debug)]
struct PropertyDef {
type_name: Ident,
generics: Generics,
serialize_fn: Option<Ident>,
deserialize_fn: Option<Ident>,
}
impl Parse for PropertyDef {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let type_ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let mut lookahead = input.lookahead1();
let mut where_clause = None;
if lookahead.peek(Where) {
where_clause = Some(input.parse()?);
lookahead = input.lookahead1();
}
let mut serialize_fn = None;
if lookahead.peek(Comma) {
input.parse::<Comma>()?;
serialize_fn = Some(input.parse::<Ident>()?);
lookahead = input.lookahead1();
}
let mut deserialize_fn = None;
if lookahead.peek(Comma) {
input.parse::<Comma>()?;
deserialize_fn = Some(input.parse::<Ident>()?);
}
Ok(PropertyDef {
type_name: type_ident,
generics: Generics {
where_clause,
..generics
},
serialize_fn,
deserialize_fn,
})
}
}
#[proc_macro]
pub fn impl_property(input: TokenStream) -> TokenStream {
let property_def = parse_macro_input!(input as PropertyDef);
let bevy_property_path = get_path(if crate_name("bevy").is_ok() {
"bevy::property"
} else if crate_name("bevy_property").is_ok() {
"bevy_property"
} else {
"crate"
});
let (impl_generics, ty_generics, where_clause) = property_def.generics.split_for_impl();
let ty = &property_def.type_name;
let serialize_fn = if let Some(serialize_fn) = property_def.serialize_fn {
quote! { #serialize_fn(self) }
} else {
quote! {
#bevy_property_path::Serializable::Borrowed(self)
}
};
let deserialize_fn = if let Some(deserialize_fn) = property_def.deserialize_fn {
quote! { #deserialize_fn(deserializer, property_type_registry) }
} else {
quote! {
let property = <#ty#ty_generics as #bevy_property_path::serde::Deserialize>::deserialize(deserializer)?;
Ok(Box::new(property))
}
};
TokenStream::from(quote! {
impl #impl_generics #bevy_property_path::Property for #ty#ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
#[inline]
fn any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn #bevy_property_path::Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn #bevy_property_path::Property) {
self.set(value);
}
#[inline]
fn set(&mut self, value: &dyn #bevy_property_path::Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = prop.clone();
} else {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
#[inline]
fn serializable(&self) -> #bevy_property_path::Serializable {
#serialize_fn
}
}
impl #impl_generics #bevy_property_path::DeserializeProperty for #ty#ty_generics #where_clause {
fn deserialize(
deserializer: &mut dyn #bevy_property_path::erased_serde::Deserializer,
property_type_registry: &#bevy_property_path::PropertyTypeRegistry) ->
Result<Box<dyn #bevy_property_path::Property>, #bevy_property_path::erased_serde::Error> {
#deserialize_fn
}
}
})
}

View file

@ -1,5 +1,5 @@
use crate::{
Properties, PropertiesType, Property, PropertyIter, PropertyTypeRegistration,
Properties, PropertiesType, Property, PropertyIter,
PropertyTypeRegistry, Serializable,
};
use de::SeqAccess;
@ -21,7 +21,7 @@ pub struct DynamicProperties {
impl DynamicProperties {
pub fn map() -> Self {
DynamicProperties {
type_name: Default::default(),
type_name: std::any::type_name::<Self>().to_string(),
props: Default::default(),
prop_names: Default::default(),
prop_indices: Default::default(),
@ -31,7 +31,7 @@ impl DynamicProperties {
pub fn seq() -> Self {
DynamicProperties {
type_name: Default::default(),
type_name: std::any::type_name::<Self>().to_string(),
props: Default::default(),
prop_names: Default::default(),
prop_indices: Default::default(),
@ -275,7 +275,7 @@ impl<'a> Serialize for PropertiesSeqSerializer<'a> {
}
pub struct DynamicPropertiesDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
@ -286,14 +286,14 @@ impl<'a, 'de> DeserializeSeed<'de> for DynamicPropertiesDeserializer<'a> {
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(DynamicPropertyMapVisiter {
property_type_registry: self.property_type_registry,
registry: self.registry,
current_type_name: self.current_type_name,
})
}
}
pub struct DynamicPropertyMapVisiter<'a> {
property_type_registry: &'a PropertyTypeRegistry,
registry: &'a PropertyTypeRegistry,
current_type_name: Rc<RefCell<Option<String>>>,
}
@ -307,11 +307,11 @@ impl<'a, 'de> Visitor<'de> for DynamicPropertyMapVisiter<'a> {
where
V: MapAccess<'de>,
{
visit_map(map, self.property_type_registry, self.current_type_name)
visit_map(map, self.registry, self.current_type_name)
}
}
pub struct PropertyDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
@ -322,14 +322,14 @@ impl<'a, 'de> DeserializeSeed<'de> for PropertyDeserializer<'a> {
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(AnyPropVisiter {
property_type_registry: self.property_type_registry,
property_type_registry: self.registry,
current_type_name: self.current_type_name,
})
}
}
pub struct PropSeqDeserializer<'a> {
property_type_registry: &'a PropertyTypeRegistry,
registry: &'a PropertyTypeRegistry,
current_type_name: Rc<RefCell<Option<String>>>,
}
@ -340,14 +340,14 @@ impl<'a, 'de> DeserializeSeed<'de> for PropSeqDeserializer<'a> {
D: serde::Deserializer<'de>,
{
deserializer.deserialize_seq(PropSeqVisiter {
property_type_registry: self.property_type_registry,
registry: self.registry,
current_type_name: self.current_type_name.clone(),
})
}
}
pub struct PropSeqVisiter<'a> {
property_type_registry: &'a PropertyTypeRegistry,
registry: &'a PropertyTypeRegistry,
current_type_name: Rc<RefCell<Option<String>>>,
}
@ -363,7 +363,7 @@ impl<'a, 'de> Visitor<'de> for PropSeqVisiter<'a> {
{
let mut dynamic_properties = DynamicProperties::seq();
while let Some(prop) = seq.next_element_seed(PropertyDeserializer {
property_type_registry: self.property_type_registry,
registry: self.registry,
current_type_name: self.current_type_name.clone(),
})? {
dynamic_properties.push(prop, None);
@ -373,7 +373,7 @@ impl<'a, 'de> Visitor<'de> for PropSeqVisiter<'a> {
}
pub struct MapValueDeserializer<'a> {
property_type_registry: &'a PropertyTypeRegistry,
registry: &'a PropertyTypeRegistry,
current_type_name: Rc<RefCell<Option<String>>>,
}
@ -387,18 +387,18 @@ impl<'a, 'de> DeserializeSeed<'de> for MapValueDeserializer<'a> {
let registration = {
let current_type_name = self.current_type_name.borrow();
let type_name = current_type_name.as_ref().unwrap();
self.property_type_registry
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)
(registration.deserialize)(&mut erased, self.registry)
.map_err(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)
} else {
deserializer.deserialize_any(AnyPropVisiter {
property_type_registry: self.property_type_registry,
property_type_registry: self.registry,
current_type_name: self.current_type_name,
})
}
@ -540,13 +540,13 @@ where
));
}
dynamic_properties = map.next_value_seed(PropSeqDeserializer {
property_type_registry,
registry: property_type_registry,
current_type_name: current_type_name.clone(),
})?;
break;
} else {
let prop = map.next_value_seed(MapValueDeserializer {
property_type_registry: property_type_registry,
registry: property_type_registry,
current_type_name: current_type_name.clone(),
})?;
dynamic_properties.set_box(&key, prop);
@ -556,20 +556,4 @@ where
let type_name = type_name.ok_or_else(|| de::Error::missing_field("type"))?;
dynamic_properties.type_name = type_name.to_string();
Ok(dynamic_properties)
}
struct PropertyTypeDeserializer<'a> {
registration: &'a PropertyTypeRegistration,
}
impl<'a, 'de> DeserializeSeed<'de> for PropertyTypeDeserializer<'a> {
type Value = Box<dyn Property>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut erased = erased_serde::Deserializer::erase(deserializer);
(self.registration.deserialize)(&mut erased)
.map_err(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)
}
}
}

View file

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

View file

@ -1,4 +1,25 @@
use crate::{impl_property, Property, Serializable};
use crate::{impl_property, Property, PropertyTypeRegistry, Serializable};
use erased_serde::Deserializer;
use legion::prelude::Entity;
use serde::Deserialize;
use std::num::Wrapping;
impl_property!(Entity);
impl_property!(Entity, serialize_entity, deserialize_entity);
mod private {
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub(super) struct Entity(pub(super) u32);
}
fn serialize_entity(entity: &Entity) -> Serializable {
Serializable::Owned(Box::new(private::Entity(entity.index())))
}
fn deserialize_entity(
deserializer: &mut dyn Deserializer,
_registry: &PropertyTypeRegistry,
) -> Result<Box<dyn Property>, erased_serde::Error> {
let entity = private::Entity::deserialize(deserializer)?;
Ok(Box::new(Entity::new(entity.0, Wrapping(1))))
}

View file

@ -1,8 +1,8 @@
use crate::{impl_property, Properties, PropertiesType, Property, PropertyIter, SeqSerializer, Serializable};
use serde::Serialize;
use serde::{Serialize, Deserialize};
use std::{
any::Any,
collections::{BTreeMap, HashMap, HashSet, VecDeque},
collections::{BTreeMap, HashMap, HashSet},
hash::Hash,
ops::Range,
};
@ -89,15 +89,15 @@ where
impl_property!(String);
impl_property!(bool);
impl_property!(SEQUENCE, VecDeque<T> where T: Clone + Send + Sync + Serialize + 'static);
impl_property!(HashSet<T> where T: Clone + Eq + Send + Sync + Hash + Serialize + 'static);
// impl_property!(SEQUENCE, VecDeque<T> where T: Clone + Send + Sync + Serialize + 'static);
impl_property!(HashSet<T> where T: Clone + Eq + Send + Sync + Hash + Serialize + for<'de> Deserialize<'de> + 'static);
impl_property!(HashMap<K, V> where
K: Clone + Eq + Send + Sync + Hash + Serialize + 'static,
V: Clone + Send + Sync + Serialize + 'static,);
K: Clone + Eq + Send + Sync + Hash + Serialize + for<'de> Deserialize<'de> + 'static,
V: Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static,);
impl_property!(BTreeMap<K, V> where
K: Clone + Ord + Send + Sync + Serialize + 'static,
V: Clone + Send + Sync + Serialize + 'static);
impl_property!(Range<T> where T: Clone + Send + Sync + Serialize + 'static);
K: Clone + Ord + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static,
V: Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static);
impl_property!(Range<T> where T: Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static);
// TODO: Implement lossless primitive types in RON and remove all of these primitive "cast checks"

View file

@ -18,4 +18,5 @@ pub use impl_property_smallvec::*;
pub use impl_property_legion::*;
pub use bevy_property_derive::*;
pub use serde;
pub use serde;
pub use erased_serde;

View file

@ -1,6 +1,6 @@
use crate::Properties;
use crate::{PropertyTypeRegistry, Properties};
use std::any::Any;
use erased_serde::Serialize;
use erased_serde::{Deserializer, Serialize};
pub enum Serializable<'a> {
@ -17,6 +17,7 @@ impl<'a> Serializable<'a> {
}
}
// TODO: consider removing send + sync requirements
pub trait Property: Send + Sync + Any + 'static {
fn type_name(&self) -> &str;
fn any(&self) -> &dyn Any;
@ -34,6 +35,10 @@ pub trait Property: Send + Sync + Any + 'static {
fn serializable(&self) -> Serializable;
}
pub trait DeserializeProperty {
fn deserialize(deserializer: &mut dyn Deserializer, property_type_registry: &PropertyTypeRegistry) -> Result<Box<dyn Property>, erased_serde::Error>;
}
pub trait PropertyVal {
fn val<T: 'static>(&self) -> Option<&T>;
fn set_val<T: 'static>(&mut self, value: T);
@ -53,165 +58,4 @@ impl PropertyVal for dyn Property {
panic!("prop value is not {}", std::any::type_name::<T>());
}
}
}
// used by impl_property
#[allow(unused_macros)]
macro_rules! as_item {
($i:item) => {
$i
};
}
#[macro_export]
macro_rules! impl_property {
($ty:ident) => {
impl Property for $ty {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
#[inline]
fn any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = prop.clone();
} else {
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)+]) => {
impl_property! {
@as_item
impl<$($args),*> Property for $trait_<$($args),*> where $($args: ::std::any::Any + 'static,)*
$($preds)* {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
#[inline]
fn any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = prop.clone();
} else {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn is_sequence(&self) -> bool {
true
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
}
};
(@$trait_:ident [$($args:ident,)*] where [$($preds:tt)+]) => {
impl_property! {
@as_item
impl<$($args),*> Property for $trait_<$($args),*> where $($args: ::std::any::Any + 'static,)*
$($preds)* {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
#[inline]
fn any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = prop.clone();
} else {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn serializable(&self) -> Serializable {
Serializable::Borrowed(self)
}
}
}
};
(@as_item $i:item) => { $i };
(
SEQUENCE, $trait_:ident < $($args:ident),* $(,)* >
where $($preds:tt)+
) => {
impl_property! {SEQUENCE, @$trait_ [$($args,)*] where [$($preds)*] }
};
(
$trait_:ident < $($args:ident),* $(,)* >
where $($preds:tt)+
) => {
impl_property! { @$trait_ [$($args,)*] where [$($preds)*] }
};
}

View file

@ -13,7 +13,7 @@ pub fn deserialize_dynamic_properties(ron_string: &str, property_type_registry:
deserializer.set_callback(&mut callback);
let dynamic_properties_deserializer = DynamicPropertiesDeserializer {
current_type_name: last_type_name.clone(),
property_type_registry: &property_type_registry,
registry: &property_type_registry,
};
dynamic_properties_deserializer.deserialize(&mut deserializer)
}

View file

@ -1,5 +1,4 @@
use crate::Property;
use serde::Deserialize;
use crate::{DeserializeProperty, Property};
use std::{any::TypeId, collections::HashMap};
#[derive(Default)]
@ -11,7 +10,7 @@ pub struct PropertyTypeRegistry {
impl PropertyTypeRegistry {
pub fn register<T>(&mut self)
where
T: Property + for<'de> Deserialize<'de>,
T: Property + DeserializeProperty,
{
let registration = PropertyTypeRegistration::of::<T>();
self.short_names
@ -36,19 +35,19 @@ pub struct PropertyTypeRegistration {
pub ty: TypeId,
pub deserialize: fn(
deserializer: &mut dyn erased_serde::Deserializer,
property_type_registry: &PropertyTypeRegistry,
) -> Result<Box<dyn Property>, erased_serde::Error>,
pub short_name: &'static str,
pub name: &'static str,
}
impl PropertyTypeRegistration {
pub fn of<T: Property + for<'de> Deserialize<'de>>() -> Self {
pub fn of<T: Property + DeserializeProperty>() -> Self {
let ty = TypeId::of::<T>();
Self {
ty,
deserialize: |deserializer: &mut dyn erased_serde::Deserializer| {
let property = <T as Deserialize>::deserialize(deserializer)?;
Ok(Box::new(property))
deserialize: |deserializer: &mut dyn erased_serde::Deserializer, property_type_registry: &PropertyTypeRegistry| {
T::deserialize(deserializer, property_type_registry)
},
name: std::any::type_name::<T>(),
short_name: std::any::type_name::<T>().split("::").last().unwrap(),

View file

@ -128,7 +128,7 @@ impl<'a, 'de> Visitor<'de> for SceneEntityVisiter<'a> {
components = Some(map.next_value_seed(ComponentVecDeserializer {
current_type_name: self.current_type_name.clone(),
property_type_registry: self.property_type_registry,
registry: self.property_type_registry,
})?);
}
}
@ -149,7 +149,7 @@ impl<'a, 'de> Visitor<'de> for SceneEntityVisiter<'a> {
}
pub struct ComponentVecDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
@ -160,14 +160,14 @@ impl<'a, 'de> DeserializeSeed<'de> for ComponentVecDeserializer<'a> {
D: serde::Deserializer<'de>,
{
deserializer.deserialize_seq(ComponentSeqVisiter {
property_type_registry: self.property_type_registry,
registry: self.registry,
current_type_name: self.current_type_name,
})
}
}
struct ComponentSeqVisiter<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
@ -184,7 +184,7 @@ impl<'a, 'de> Visitor<'de> for ComponentSeqVisiter<'a> {
let mut dynamic_properties = Vec::new();
while let Some(entity) = seq.next_element_seed(DynamicPropertiesDeserializer {
current_type_name: self.current_type_name.clone(),
property_type_registry: self.property_type_registry,
registry: self.registry,
})? {
dynamic_properties.push(entity);
}