mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30:19 +00:00
props: fix dynamic property deserialization
This commit is contained in:
parent
563a6fc57c
commit
c03da2b728
4 changed files with 123 additions and 55 deletions
|
@ -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 std::{
|
||||
any::Any,
|
||||
|
@ -78,6 +78,10 @@ where
|
|||
fn serializable(&self) -> Serializable {
|
||||
Serializable::Owned(Box::new(SeqSerializer::new(self)))
|
||||
}
|
||||
|
||||
fn property_type(&self) -> PropertyType {
|
||||
PropertyType::Seq
|
||||
}
|
||||
}
|
||||
|
||||
impl_property!(String);
|
||||
|
|
|
@ -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> {
|
||||
type_name: Option<&'a str>,
|
||||
registry: &'a PropertyTypeRegistry,
|
||||
|
@ -173,7 +218,7 @@ impl<'a, 'de> DeserializeSeed<'de> for PropertyDeserializer<'a> {
|
|||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
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))
|
||||
})?;
|
||||
let mut erased = erased_serde::Deserializer::erase(deserializer);
|
||||
|
@ -233,9 +278,7 @@ pub struct MapPropertyDeserializer<'a> {
|
|||
|
||||
impl<'a> MapPropertyDeserializer<'a> {
|
||||
pub fn new(registry: &'a PropertyTypeRegistry) -> Self {
|
||||
MapPropertyDeserializer {
|
||||
registry,
|
||||
}
|
||||
MapPropertyDeserializer { registry }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,53 +422,71 @@ impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> {
|
|||
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>,
|
||||
{
|
||||
let mut type_name: Option<String> = None;
|
||||
while let Some(key) = map.next_key::<String>()? {
|
||||
match key.as_str() {
|
||||
TYPE_FIELD => {
|
||||
type_name = Some(map.next_value()?);
|
||||
}
|
||||
MAP_FIELD => {
|
||||
let type_name = type_name
|
||||
.take()
|
||||
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
|
||||
let mut dynamic_properties =
|
||||
map.next_value_seed(MapPropertyDeserializer { registry: self.registry })?;
|
||||
dynamic_properties.type_name = type_name.to_string();
|
||||
return Ok(Box::new(
|
||||
dynamic_properties,
|
||||
));
|
||||
}
|
||||
SEQ_FIELD => {
|
||||
let type_name = type_name
|
||||
.take()
|
||||
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
|
||||
let mut dynamic_properties =
|
||||
map.next_value_seed(SeqPropertyDeserializer { registry: self.registry })?;
|
||||
dynamic_properties.type_name = type_name;
|
||||
return Ok(Box::new(
|
||||
dynamic_properties,
|
||||
));
|
||||
}
|
||||
VALUE_FIELD => {
|
||||
let type_name = type_name
|
||||
.take()
|
||||
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
|
||||
return map.next_value_seed(
|
||||
PropertyDeserializer {
|
||||
registry: self.registry,
|
||||
type_name: Some(&type_name),
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => return Err(de::Error::unknown_field(key.as_str(), &[])),
|
||||
}
|
||||
}
|
||||
|
||||
Err(de::Error::custom("Maps in this location must have the \'type\' field and one of the following fields: \'map\', \'seq\', \'value\'"))
|
||||
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
|
||||
V: MapAccess<'de>,
|
||||
{
|
||||
let mut type_name: Option<String> = None;
|
||||
while let Some(key) = map.next_key::<String>()? {
|
||||
match key.as_str() {
|
||||
TYPE_FIELD => {
|
||||
type_name = Some(map.next_value()?);
|
||||
}
|
||||
MAP_FIELD => {
|
||||
let type_name = type_name
|
||||
.take()
|
||||
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
|
||||
let mut dynamic_properties =
|
||||
map.next_value_seed(MapPropertyDeserializer { registry })?;
|
||||
dynamic_properties.type_name = type_name.to_string();
|
||||
return Ok(DynamicPropertiesOrProperty::DynamicProperties(
|
||||
dynamic_properties,
|
||||
));
|
||||
}
|
||||
SEQ_FIELD => {
|
||||
let type_name = type_name
|
||||
.take()
|
||||
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
|
||||
let mut dynamic_properties =
|
||||
map.next_value_seed(SeqPropertyDeserializer { registry })?;
|
||||
dynamic_properties.type_name = type_name;
|
||||
return Ok(DynamicPropertiesOrProperty::DynamicProperties(
|
||||
dynamic_properties,
|
||||
));
|
||||
}
|
||||
VALUE_FIELD => {
|
||||
let type_name = type_name
|
||||
.take()
|
||||
.ok_or_else(|| de::Error::missing_field(TYPE_FIELD))?;
|
||||
return Ok(DynamicPropertiesOrProperty::Property(map.next_value_seed(
|
||||
PropertyDeserializer {
|
||||
registry,
|
||||
type_name: Some(&type_name),
|
||||
},
|
||||
)?));
|
||||
}
|
||||
_ => return Err(de::Error::unknown_field(key.as_str(), &[])),
|
||||
}
|
||||
}
|
||||
|
||||
Err(de::Error::custom("Maps in this location must have the \'type\' field and one of the following fields: \'map\', \'seq\', \'value\'"))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{property_serde::MapPropertyDeserializer, DynamicProperties, PropertyTypeRegistry};
|
||||
use crate::{
|
||||
property_serde::DynamicPropertiesDeserializer, DynamicProperties, PropertyTypeRegistry,
|
||||
};
|
||||
use ron::de::Deserializer;
|
||||
use serde::de::DeserializeSeed;
|
||||
|
||||
|
@ -7,6 +9,7 @@ pub fn deserialize_dynamic_properties(
|
|||
property_type_registry: &PropertyTypeRegistry,
|
||||
) -> Result<DynamicProperties, ron::Error> {
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{Entity, Scene};
|
||||
use anyhow::Result;
|
||||
use bevy_property::{
|
||||
property_serde::MapPropertyDeserializer, DynamicProperties, PropertyTypeRegistry,
|
||||
property_serde::DynamicPropertiesDeserializer, DynamicProperties, PropertyTypeRegistry,
|
||||
};
|
||||
use serde::{
|
||||
de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor},
|
||||
|
@ -173,7 +173,7 @@ impl<'a, 'de> Visitor<'de> for ComponentSeqVisiter<'a> {
|
|||
{
|
||||
let mut dynamic_properties = Vec::new();
|
||||
while let Some(entity) =
|
||||
seq.next_element_seed(MapPropertyDeserializer::new(self.registry))?
|
||||
seq.next_element_seed(DynamicPropertiesDeserializer::new(self.registry))?
|
||||
{
|
||||
dynamic_properties.push(entity);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue