mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30: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 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
|
||||
|
|
|
@ -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 {
|
||||
|
@ -255,5 +262,143 @@ pub fn derive_property(input: TokenStream) -> TokenStream {
|
|||
#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::{
|
||||
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);
|
||||
|
@ -557,19 +557,3 @@ where
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{impl_property, Property, Serializable};
|
||||
use crate::impl_property;
|
||||
use glam::{Mat3, Mat4, Quat, Vec2, Vec3};
|
||||
|
||||
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 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 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"
|
||||
|
|
|
@ -19,3 +19,4 @@ pub use impl_property_legion::*;
|
|||
|
||||
pub use bevy_property_derive::*;
|
||||
pub use serde;
|
||||
pub use erased_serde;
|
|
@ -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);
|
||||
|
@ -54,164 +59,3 @@ impl PropertyVal for dyn Property {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
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)
|
||||
}
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue