props: fix dynamic property deserialization

This commit is contained in:
Carter Anderson 2020-05-27 13:30:05 -07:00
parent 563a6fc57c
commit c03da2b728
4 changed files with 123 additions and 55 deletions

View File

@ -1,4 +1,4 @@
use crate::{impl_property, Properties, Property, PropertyIter, property_serde::{Serializable, SeqSerializer}}; use crate::{impl_property, Properties, Property, PropertyIter, property_serde::{Serializable, SeqSerializer}, PropertyType};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::{ use std::{
any::Any, any::Any,
@ -78,6 +78,10 @@ where
fn serializable(&self) -> Serializable { fn serializable(&self) -> Serializable {
Serializable::Owned(Box::new(SeqSerializer::new(self))) Serializable::Owned(Box::new(SeqSerializer::new(self)))
} }
fn property_type(&self) -> PropertyType {
PropertyType::Seq
}
} }
impl_property!(String); impl_property!(String);

View File

@ -161,6 +161,51 @@ impl<'a> Serialize for SeqValueSerializer<'a> {
} }
} }
pub struct DynamicPropertiesDeserializer<'a> {
registry: &'a PropertyTypeRegistry,
}
impl<'a> DynamicPropertiesDeserializer<'a> {
pub fn new(registry: &'a PropertyTypeRegistry) -> Self {
DynamicPropertiesDeserializer { registry }
}
}
impl<'a, 'de> DeserializeSeed<'de> for DynamicPropertiesDeserializer<'a> {
type Value = DynamicProperties;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(DynamicPropertiesVisiter {
registry: self.registry,
})
}
}
struct DynamicPropertiesVisiter<'a> {
registry: &'a PropertyTypeRegistry,
}
impl<'a, 'de> Visitor<'de> for DynamicPropertiesVisiter<'a> {
type Value = DynamicProperties;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("dynamic property")
}
fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'de>,
{
match visit_map(map, self.registry)? {
DynamicPropertiesOrProperty::DynamicProperties(value) => Ok(value),
_ => Err(de::Error::custom("Expected DynamicProperties"))
}
}
}
pub struct PropertyDeserializer<'a> { pub struct PropertyDeserializer<'a> {
type_name: Option<&'a str>, type_name: Option<&'a str>,
registry: &'a PropertyTypeRegistry, registry: &'a PropertyTypeRegistry,
@ -173,7 +218,7 @@ impl<'a, 'de> DeserializeSeed<'de> for PropertyDeserializer<'a> {
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
if let Some(type_name) = self.type_name { if let Some(type_name) = self.type_name {
let registration = self.registry.get_short(type_name).ok_or_else(|| { let registration = self.registry.get(type_name).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);
@ -233,9 +278,7 @@ pub struct MapPropertyDeserializer<'a> {
impl<'a> MapPropertyDeserializer<'a> { impl<'a> MapPropertyDeserializer<'a> {
pub fn new(registry: &'a PropertyTypeRegistry) -> Self { pub fn new(registry: &'a PropertyTypeRegistry) -> Self {
MapPropertyDeserializer { MapPropertyDeserializer { registry }
registry,
}
} }
} }
@ -379,7 +422,26 @@ impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> {
Ok(Box::new(v.to_string())) Ok(Box::new(v.to_string()))
} }
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'de>,
{
Ok(match visit_map(map, self.registry)? {
DynamicPropertiesOrProperty::DynamicProperties(value) => Box::new(value),
DynamicPropertiesOrProperty::Property(value) => value,
})
}
}
enum DynamicPropertiesOrProperty {
DynamicProperties(DynamicProperties),
Property(Box<dyn Property>),
}
fn visit_map<'de, V>(
mut map: V,
registry: &PropertyTypeRegistry,
) -> Result<DynamicPropertiesOrProperty, V::Error>
where where
V: MapAccess<'de>, V: MapAccess<'de>,
{ {
@ -394,9 +456,9 @@ impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> {
.take() .take()
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?; .ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
let mut dynamic_properties = let mut dynamic_properties =
map.next_value_seed(MapPropertyDeserializer { registry: self.registry })?; map.next_value_seed(MapPropertyDeserializer { registry })?;
dynamic_properties.type_name = type_name.to_string(); dynamic_properties.type_name = type_name.to_string();
return Ok(Box::new( return Ok(DynamicPropertiesOrProperty::DynamicProperties(
dynamic_properties, dynamic_properties,
)); ));
} }
@ -405,9 +467,9 @@ impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> {
.take() .take()
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?; .ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
let mut dynamic_properties = let mut dynamic_properties =
map.next_value_seed(SeqPropertyDeserializer { registry: self.registry })?; map.next_value_seed(SeqPropertyDeserializer { registry })?;
dynamic_properties.type_name = type_name; dynamic_properties.type_name = type_name;
return Ok(Box::new( return Ok(DynamicPropertiesOrProperty::DynamicProperties(
dynamic_properties, dynamic_properties,
)); ));
} }
@ -415,12 +477,12 @@ impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> {
let type_name = type_name let type_name = type_name
.take() .take()
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?; .ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
return map.next_value_seed( return Ok(DynamicPropertiesOrProperty::Property(map.next_value_seed(
PropertyDeserializer { PropertyDeserializer {
registry: self.registry, registry,
type_name: Some(&type_name), type_name: Some(&type_name),
}, },
); )?));
} }
_ => return Err(de::Error::unknown_field(key.as_str(), &[])), _ => return Err(de::Error::unknown_field(key.as_str(), &[])),
} }
@ -428,4 +490,3 @@ impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> {
Err(de::Error::custom("Maps in this location must have the \'type\' field and one of the following fields: \'map\', \'seq\', \'value\'")) Err(de::Error::custom("Maps in this location must have the \'type\' field and one of the following fields: \'map\', \'seq\', \'value\'"))
} }
}

View File

@ -1,4 +1,6 @@
use crate::{property_serde::MapPropertyDeserializer, DynamicProperties, PropertyTypeRegistry}; use crate::{
property_serde::DynamicPropertiesDeserializer, DynamicProperties, PropertyTypeRegistry,
};
use ron::de::Deserializer; use ron::de::Deserializer;
use serde::de::DeserializeSeed; use serde::de::DeserializeSeed;
@ -7,6 +9,7 @@ pub fn deserialize_dynamic_properties(
property_type_registry: &PropertyTypeRegistry, property_type_registry: &PropertyTypeRegistry,
) -> Result<DynamicProperties, ron::Error> { ) -> Result<DynamicProperties, ron::Error> {
let mut deserializer = Deserializer::from_str(&ron_string).unwrap(); let mut deserializer = Deserializer::from_str(&ron_string).unwrap();
let dynamic_properties_deserializer = MapPropertyDeserializer::new(&property_type_registry); let dynamic_properties_deserializer =
DynamicPropertiesDeserializer::new(&property_type_registry);
dynamic_properties_deserializer.deserialize(&mut deserializer) dynamic_properties_deserializer.deserialize(&mut deserializer)
} }

View File

@ -1,7 +1,7 @@
use crate::{Entity, Scene}; use crate::{Entity, Scene};
use anyhow::Result; use anyhow::Result;
use bevy_property::{ use bevy_property::{
property_serde::MapPropertyDeserializer, DynamicProperties, PropertyTypeRegistry, property_serde::DynamicPropertiesDeserializer, DynamicProperties, PropertyTypeRegistry,
}; };
use serde::{ use serde::{
de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor}, de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor},
@ -173,7 +173,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) = while let Some(entity) =
seq.next_element_seed(MapPropertyDeserializer::new(self.registry))? seq.next_element_seed(DynamicPropertiesDeserializer::new(self.registry))?
{ {
dynamic_properties.push(entity); dynamic_properties.push(entity);
} }