mirror of
https://github.com/bevyengine/bevy
synced 2024-11-29 16:10:19 +00:00
props: remove need for explicit serde::Deserialize impl. replace impl_property macro_rules with proc_macro_fn
This commit is contained in:
parent
4bc3772749
commit
76adb888d3
11 changed files with 224 additions and 231 deletions
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
use bevy_property::{Property, Properties};
|
use bevy_property::{Property, Properties, DeserializeProperty};
|
||||||
use legion::storage::Component;
|
use legion::storage::Component;
|
||||||
use serde::Deserialize;
|
|
||||||
use crate::{PropertyTypeRegistryContext, ComponentRegistryContext};
|
use crate::{PropertyTypeRegistryContext, ComponentRegistryContext};
|
||||||
use bevy_app::{FromResources, AppBuilder};
|
use bevy_app::{FromResources, AppBuilder};
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ pub trait RegisterComponent {
|
||||||
T: Properties + Component + FromResources;
|
T: Properties + Component + FromResources;
|
||||||
fn register_property_type<T>(&mut self) -> &mut Self
|
fn register_property_type<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Property + for<'de> Deserialize<'de>;
|
T: Property + DeserializeProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterComponent for AppBuilder {
|
impl RegisterComponent for AppBuilder {
|
||||||
|
@ -31,7 +30,7 @@ impl RegisterComponent for AppBuilder {
|
||||||
|
|
||||||
fn register_property_type<T>(&mut self) -> &mut Self
|
fn register_property_type<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Property + for<'de> Deserialize<'de>,
|
T: Property + DeserializeProperty,
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let registry_context = self
|
let registry_context = self
|
||||||
|
|
|
@ -5,8 +5,15 @@ mod modules;
|
||||||
use darling::FromMeta;
|
use darling::FromMeta;
|
||||||
use modules::{get_modules, get_path};
|
use modules::{get_modules, get_path};
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro_crate::crate_name;
|
||||||
use quote::quote;
|
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)]
|
#[derive(FromMeta, Debug, Default)]
|
||||||
struct PropAttributeArgs {
|
struct PropAttributeArgs {
|
||||||
|
@ -152,7 +159,7 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn any(&self) -> &dyn std::any::Any {
|
fn any(&self) -> &dyn std::any::Any {
|
||||||
self
|
self
|
||||||
|
@ -254,6 +261,144 @@ pub fn derive_property(input: TokenStream) -> TokenStream {
|
||||||
fn serializable(&self) -> #bevy_property_path::Serializable {
|
fn serializable(&self) -> #bevy_property_path::Serializable {
|
||||||
#bevy_property_path::Serializable::Borrowed(self)
|
#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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
Properties, PropertiesType, Property, PropertyIter, PropertyTypeRegistration,
|
Properties, PropertiesType, Property, PropertyIter,
|
||||||
PropertyTypeRegistry, Serializable,
|
PropertyTypeRegistry, Serializable,
|
||||||
};
|
};
|
||||||
use de::SeqAccess;
|
use de::SeqAccess;
|
||||||
|
@ -21,7 +21,7 @@ pub struct DynamicProperties {
|
||||||
impl DynamicProperties {
|
impl DynamicProperties {
|
||||||
pub fn map() -> Self {
|
pub fn map() -> Self {
|
||||||
DynamicProperties {
|
DynamicProperties {
|
||||||
type_name: Default::default(),
|
type_name: std::any::type_name::<Self>().to_string(),
|
||||||
props: Default::default(),
|
props: Default::default(),
|
||||||
prop_names: Default::default(),
|
prop_names: Default::default(),
|
||||||
prop_indices: Default::default(),
|
prop_indices: Default::default(),
|
||||||
|
@ -31,7 +31,7 @@ impl DynamicProperties {
|
||||||
|
|
||||||
pub fn seq() -> Self {
|
pub fn seq() -> Self {
|
||||||
DynamicProperties {
|
DynamicProperties {
|
||||||
type_name: Default::default(),
|
type_name: std::any::type_name::<Self>().to_string(),
|
||||||
props: Default::default(),
|
props: Default::default(),
|
||||||
prop_names: Default::default(),
|
prop_names: Default::default(),
|
||||||
prop_indices: Default::default(),
|
prop_indices: Default::default(),
|
||||||
|
@ -275,7 +275,7 @@ impl<'a> Serialize for PropertiesSeqSerializer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynamicPropertiesDeserializer<'a> {
|
pub struct DynamicPropertiesDeserializer<'a> {
|
||||||
pub property_type_registry: &'a PropertyTypeRegistry,
|
pub registry: &'a PropertyTypeRegistry,
|
||||||
pub current_type_name: Rc<RefCell<Option<String>>>,
|
pub current_type_name: Rc<RefCell<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,14 +286,14 @@ impl<'a, 'de> DeserializeSeed<'de> for DynamicPropertiesDeserializer<'a> {
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
deserializer.deserialize_map(DynamicPropertyMapVisiter {
|
deserializer.deserialize_map(DynamicPropertyMapVisiter {
|
||||||
property_type_registry: self.property_type_registry,
|
registry: self.registry,
|
||||||
current_type_name: self.current_type_name,
|
current_type_name: self.current_type_name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynamicPropertyMapVisiter<'a> {
|
pub struct DynamicPropertyMapVisiter<'a> {
|
||||||
property_type_registry: &'a PropertyTypeRegistry,
|
registry: &'a PropertyTypeRegistry,
|
||||||
current_type_name: Rc<RefCell<Option<String>>>,
|
current_type_name: Rc<RefCell<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,11 +307,11 @@ impl<'a, 'de> Visitor<'de> for DynamicPropertyMapVisiter<'a> {
|
||||||
where
|
where
|
||||||
V: MapAccess<'de>,
|
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 struct PropertyDeserializer<'a> {
|
||||||
pub property_type_registry: &'a PropertyTypeRegistry,
|
pub registry: &'a PropertyTypeRegistry,
|
||||||
pub current_type_name: Rc<RefCell<Option<String>>>,
|
pub current_type_name: Rc<RefCell<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,14 +322,14 @@ impl<'a, 'de> DeserializeSeed<'de> for PropertyDeserializer<'a> {
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
deserializer.deserialize_any(AnyPropVisiter {
|
deserializer.deserialize_any(AnyPropVisiter {
|
||||||
property_type_registry: self.property_type_registry,
|
property_type_registry: self.registry,
|
||||||
current_type_name: self.current_type_name,
|
current_type_name: self.current_type_name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PropSeqDeserializer<'a> {
|
pub struct PropSeqDeserializer<'a> {
|
||||||
property_type_registry: &'a PropertyTypeRegistry,
|
registry: &'a PropertyTypeRegistry,
|
||||||
current_type_name: Rc<RefCell<Option<String>>>,
|
current_type_name: Rc<RefCell<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,14 +340,14 @@ impl<'a, 'de> DeserializeSeed<'de> for PropSeqDeserializer<'a> {
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
deserializer.deserialize_seq(PropSeqVisiter {
|
deserializer.deserialize_seq(PropSeqVisiter {
|
||||||
property_type_registry: self.property_type_registry,
|
registry: self.registry,
|
||||||
current_type_name: self.current_type_name.clone(),
|
current_type_name: self.current_type_name.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PropSeqVisiter<'a> {
|
pub struct PropSeqVisiter<'a> {
|
||||||
property_type_registry: &'a PropertyTypeRegistry,
|
registry: &'a PropertyTypeRegistry,
|
||||||
current_type_name: Rc<RefCell<Option<String>>>,
|
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();
|
let mut dynamic_properties = DynamicProperties::seq();
|
||||||
while let Some(prop) = seq.next_element_seed(PropertyDeserializer {
|
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(),
|
current_type_name: self.current_type_name.clone(),
|
||||||
})? {
|
})? {
|
||||||
dynamic_properties.push(prop, None);
|
dynamic_properties.push(prop, None);
|
||||||
|
@ -373,7 +373,7 @@ impl<'a, 'de> Visitor<'de> for PropSeqVisiter<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MapValueDeserializer<'a> {
|
pub struct MapValueDeserializer<'a> {
|
||||||
property_type_registry: &'a PropertyTypeRegistry,
|
registry: &'a PropertyTypeRegistry,
|
||||||
current_type_name: Rc<RefCell<Option<String>>>,
|
current_type_name: Rc<RefCell<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,18 +387,18 @@ impl<'a, 'de> DeserializeSeed<'de> for MapValueDeserializer<'a> {
|
||||||
let registration = {
|
let registration = {
|
||||||
let current_type_name = self.current_type_name.borrow();
|
let current_type_name = self.current_type_name.borrow();
|
||||||
let type_name = current_type_name.as_ref().unwrap();
|
let type_name = current_type_name.as_ref().unwrap();
|
||||||
self.property_type_registry
|
self.registry
|
||||||
.get_short(type_name)
|
.get_short(type_name)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
de::Error::custom(format!("TypeRegistration is missing for {}", type_name))
|
de::Error::custom(format!("TypeRegistration is missing for {}", type_name))
|
||||||
})?
|
})?
|
||||||
};
|
};
|
||||||
let mut erased = erased_serde::Deserializer::erase(deserializer);
|
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)
|
.map_err(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)
|
||||||
} else {
|
} else {
|
||||||
deserializer.deserialize_any(AnyPropVisiter {
|
deserializer.deserialize_any(AnyPropVisiter {
|
||||||
property_type_registry: self.property_type_registry,
|
property_type_registry: self.registry,
|
||||||
current_type_name: self.current_type_name,
|
current_type_name: self.current_type_name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -540,13 +540,13 @@ where
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
dynamic_properties = map.next_value_seed(PropSeqDeserializer {
|
dynamic_properties = map.next_value_seed(PropSeqDeserializer {
|
||||||
property_type_registry,
|
registry: property_type_registry,
|
||||||
current_type_name: current_type_name.clone(),
|
current_type_name: current_type_name.clone(),
|
||||||
})?;
|
})?;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
let prop = map.next_value_seed(MapValueDeserializer {
|
let prop = map.next_value_seed(MapValueDeserializer {
|
||||||
property_type_registry: property_type_registry,
|
registry: property_type_registry,
|
||||||
current_type_name: current_type_name.clone(),
|
current_type_name: current_type_name.clone(),
|
||||||
})?;
|
})?;
|
||||||
dynamic_properties.set_box(&key, prop);
|
dynamic_properties.set_box(&key, prop);
|
||||||
|
@ -556,20 +556,4 @@ where
|
||||||
let type_name = type_name.ok_or_else(|| de::Error::missing_field("type"))?;
|
let type_name = type_name.ok_or_else(|| de::Error::missing_field("type"))?;
|
||||||
dynamic_properties.type_name = type_name.to_string();
|
dynamic_properties.type_name = type_name.to_string();
|
||||||
Ok(dynamic_properties)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{impl_property, Property, Serializable};
|
use crate::impl_property;
|
||||||
use glam::{Mat3, Mat4, Quat, Vec2, Vec3};
|
use glam::{Mat3, Mat4, Quat, Vec2, Vec3};
|
||||||
|
|
||||||
impl_property!(Vec2);
|
impl_property!(Vec2);
|
||||||
|
|
|
@ -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 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))))
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::{impl_property, Properties, PropertiesType, Property, PropertyIter, SeqSerializer, Serializable};
|
use crate::{impl_property, Properties, PropertiesType, Property, PropertyIter, SeqSerializer, Serializable};
|
||||||
use serde::Serialize;
|
use serde::{Serialize, Deserialize};
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
collections::{BTreeMap, HashMap, HashSet, VecDeque},
|
collections::{BTreeMap, HashMap, HashSet},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
};
|
};
|
||||||
|
@ -89,15 +89,15 @@ where
|
||||||
|
|
||||||
impl_property!(String);
|
impl_property!(String);
|
||||||
impl_property!(bool);
|
impl_property!(bool);
|
||||||
impl_property!(SEQUENCE, VecDeque<T> where T: Clone + Send + Sync + 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 + 'static);
|
impl_property!(HashSet<T> where T: Clone + Eq + Send + Sync + Hash + Serialize + for<'de> Deserialize<'de> + 'static);
|
||||||
impl_property!(HashMap<K, V> where
|
impl_property!(HashMap<K, V> where
|
||||||
K: Clone + Eq + Send + Sync + Hash + Serialize + 'static,
|
K: Clone + Eq + Send + Sync + Hash + Serialize + for<'de> Deserialize<'de> + 'static,
|
||||||
V: Clone + Send + Sync + Serialize + 'static,);
|
V: Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static,);
|
||||||
impl_property!(BTreeMap<K, V> where
|
impl_property!(BTreeMap<K, V> where
|
||||||
K: Clone + Ord + Send + Sync + Serialize + 'static,
|
K: Clone + Ord + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static,
|
||||||
V: Clone + Send + Sync + Serialize + 'static);
|
V: Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static);
|
||||||
impl_property!(Range<T> where T: Clone + Send + Sync + Serialize + '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"
|
// TODO: Implement lossless primitive types in RON and remove all of these primitive "cast checks"
|
||||||
|
|
|
@ -18,4 +18,5 @@ pub use impl_property_smallvec::*;
|
||||||
pub use impl_property_legion::*;
|
pub use impl_property_legion::*;
|
||||||
|
|
||||||
pub use bevy_property_derive::*;
|
pub use bevy_property_derive::*;
|
||||||
pub use serde;
|
pub use serde;
|
||||||
|
pub use erased_serde;
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::Properties;
|
use crate::{PropertyTypeRegistry, Properties};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use erased_serde::Serialize;
|
use erased_serde::{Deserializer, Serialize};
|
||||||
|
|
||||||
|
|
||||||
pub enum Serializable<'a> {
|
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 {
|
pub trait Property: Send + Sync + Any + 'static {
|
||||||
fn type_name(&self) -> &str;
|
fn type_name(&self) -> &str;
|
||||||
fn any(&self) -> &dyn Any;
|
fn any(&self) -> &dyn Any;
|
||||||
|
@ -34,6 +35,10 @@ pub trait Property: Send + Sync + Any + 'static {
|
||||||
fn serializable(&self) -> Serializable;
|
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 {
|
pub trait PropertyVal {
|
||||||
fn val<T: 'static>(&self) -> Option<&T>;
|
fn val<T: 'static>(&self) -> Option<&T>;
|
||||||
fn set_val<T: 'static>(&mut self, value: 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>());
|
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)*] }
|
|
||||||
};
|
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@ pub fn deserialize_dynamic_properties(ron_string: &str, property_type_registry:
|
||||||
deserializer.set_callback(&mut callback);
|
deserializer.set_callback(&mut callback);
|
||||||
let dynamic_properties_deserializer = DynamicPropertiesDeserializer {
|
let dynamic_properties_deserializer = DynamicPropertiesDeserializer {
|
||||||
current_type_name: last_type_name.clone(),
|
current_type_name: last_type_name.clone(),
|
||||||
property_type_registry: &property_type_registry,
|
registry: &property_type_registry,
|
||||||
};
|
};
|
||||||
dynamic_properties_deserializer.deserialize(&mut deserializer)
|
dynamic_properties_deserializer.deserialize(&mut deserializer)
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::Property;
|
use crate::{DeserializeProperty, Property};
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{any::TypeId, collections::HashMap};
|
use std::{any::TypeId, collections::HashMap};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -11,7 +10,7 @@ pub struct PropertyTypeRegistry {
|
||||||
impl PropertyTypeRegistry {
|
impl PropertyTypeRegistry {
|
||||||
pub fn register<T>(&mut self)
|
pub fn register<T>(&mut self)
|
||||||
where
|
where
|
||||||
T: Property + for<'de> Deserialize<'de>,
|
T: Property + DeserializeProperty,
|
||||||
{
|
{
|
||||||
let registration = PropertyTypeRegistration::of::<T>();
|
let registration = PropertyTypeRegistration::of::<T>();
|
||||||
self.short_names
|
self.short_names
|
||||||
|
@ -36,19 +35,19 @@ pub struct PropertyTypeRegistration {
|
||||||
pub ty: TypeId,
|
pub ty: TypeId,
|
||||||
pub deserialize: fn(
|
pub deserialize: fn(
|
||||||
deserializer: &mut dyn erased_serde::Deserializer,
|
deserializer: &mut dyn erased_serde::Deserializer,
|
||||||
|
property_type_registry: &PropertyTypeRegistry,
|
||||||
) -> Result<Box<dyn Property>, erased_serde::Error>,
|
) -> Result<Box<dyn Property>, erased_serde::Error>,
|
||||||
pub short_name: &'static str,
|
pub short_name: &'static str,
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropertyTypeRegistration {
|
impl PropertyTypeRegistration {
|
||||||
pub fn of<T: Property + for<'de> Deserialize<'de>>() -> Self {
|
pub fn of<T: Property + DeserializeProperty>() -> Self {
|
||||||
let ty = TypeId::of::<T>();
|
let ty = TypeId::of::<T>();
|
||||||
Self {
|
Self {
|
||||||
ty,
|
ty,
|
||||||
deserialize: |deserializer: &mut dyn erased_serde::Deserializer| {
|
deserialize: |deserializer: &mut dyn erased_serde::Deserializer, property_type_registry: &PropertyTypeRegistry| {
|
||||||
let property = <T as Deserialize>::deserialize(deserializer)?;
|
T::deserialize(deserializer, property_type_registry)
|
||||||
Ok(Box::new(property))
|
|
||||||
},
|
},
|
||||||
name: std::any::type_name::<T>(),
|
name: std::any::type_name::<T>(),
|
||||||
short_name: std::any::type_name::<T>().split("::").last().unwrap(),
|
short_name: std::any::type_name::<T>().split("::").last().unwrap(),
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl<'a, 'de> Visitor<'de> for SceneEntityVisiter<'a> {
|
||||||
|
|
||||||
components = Some(map.next_value_seed(ComponentVecDeserializer {
|
components = Some(map.next_value_seed(ComponentVecDeserializer {
|
||||||
current_type_name: self.current_type_name.clone(),
|
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 struct ComponentVecDeserializer<'a> {
|
||||||
pub property_type_registry: &'a PropertyTypeRegistry,
|
pub registry: &'a PropertyTypeRegistry,
|
||||||
pub current_type_name: Rc<RefCell<Option<String>>>,
|
pub current_type_name: Rc<RefCell<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,14 +160,14 @@ impl<'a, 'de> DeserializeSeed<'de> for ComponentVecDeserializer<'a> {
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
deserializer.deserialize_seq(ComponentSeqVisiter {
|
deserializer.deserialize_seq(ComponentSeqVisiter {
|
||||||
property_type_registry: self.property_type_registry,
|
registry: self.registry,
|
||||||
current_type_name: self.current_type_name,
|
current_type_name: self.current_type_name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ComponentSeqVisiter<'a> {
|
struct ComponentSeqVisiter<'a> {
|
||||||
pub property_type_registry: &'a PropertyTypeRegistry,
|
pub registry: &'a PropertyTypeRegistry,
|
||||||
pub current_type_name: Rc<RefCell<Option<String>>>,
|
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();
|
let mut dynamic_properties = Vec::new();
|
||||||
while let Some(entity) = seq.next_element_seed(DynamicPropertiesDeserializer {
|
while let Some(entity) = seq.next_element_seed(DynamicPropertiesDeserializer {
|
||||||
current_type_name: self.current_type_name.clone(),
|
current_type_name: self.current_type_name.clone(),
|
||||||
property_type_registry: self.property_type_registry,
|
registry: self.registry,
|
||||||
})? {
|
})? {
|
||||||
dynamic_properties.push(entity);
|
dynamic_properties.push(entity);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue