From 4825a02d3f4a815651e55084482f0cfd45241d2d Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 19 Mar 2022 18:46:49 -0700 Subject: [PATCH 01/24] Simplified reflection ser/de --- crates/bevy_reflect/src/lib.rs | 11 +- crates/bevy_reflect/src/serde/de.rs | 1023 ++++++++++++++++---------- crates/bevy_reflect/src/serde/mod.rs | 8 - crates/bevy_reflect/src/serde/ser.rs | 430 +++++------ 4 files changed, 817 insertions(+), 655 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 5f35d27e4e5a3..dcba7d8323a5a 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -472,12 +472,17 @@ mod tests { let mut registry = TypeRegistry::default(); registry.register::(); - registry.register::(); + registry.register::(); + registry.register::(); registry.register::(); + registry.register::(); + registry.register::(); registry.register::(); registry.register::(); - registry.register::(); - registry.register::(); + registry.register::>(); + registry.register::>(); + registry.register::<(i32, Vec, Bar)>(); + registry.register::<[u32; 2]>(); let serializer = ReflectSerializer::new(&foo, ®istry); let serialized = to_string_pretty(&serializer, PrettyConfig::default()).unwrap(); diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index ad24185de15f3..ae276feae4426 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,9 +1,13 @@ use crate::{ - serde::type_fields, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, - DynamicTuple, DynamicTupleStruct, Map, Reflect, ReflectDeserialize, TypeRegistry, + serde::type_fields, ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, + DynamicStruct, DynamicTuple, DynamicTupleStruct, EnumInfo, ListInfo, Map, MapInfo, NamedField, + Reflect, ReflectDeserialize, StructInfo, StructVariantInfo, Tuple, TupleInfo, TupleStruct, + TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistry, UnnamedField, VariantInfo, }; use erased_serde::Deserializer; use serde::de::{self, DeserializeSeed, Error, MapAccess, SeqAccess, Visitor}; +use std::any::TypeId; +use std::fmt::Formatter; pub trait DeserializeValue { fn deserialize( @@ -12,313 +16,383 @@ pub trait DeserializeValue { ) -> Result, erased_serde::Error>; } -pub struct ReflectDeserializer<'a> { - registry: &'a TypeRegistry, +trait StructLikeInfo { + fn get_name(&self) -> &str; + fn get_field(&self, name: &str) -> Option<&NamedField>; } -impl<'a> ReflectDeserializer<'a> { - pub fn new(registry: &'a TypeRegistry) -> Self { - ReflectDeserializer { registry } - } +trait TupleLikeInfo { + fn get_name(&self) -> &str; + fn get_field(&self, index: usize) -> Option<&UnnamedField>; + fn get_field_len(&self) -> usize; } -impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { - type Value = Box; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(ReflectVisitor { - registry: self.registry, - }) +impl StructLikeInfo for StructInfo { + fn get_name(&self) -> &str { + self.type_name() } -} -struct ReflectVisitor<'a> { - registry: &'a TypeRegistry, + fn get_field(&self, name: &str) -> Option<&NamedField> { + self.field(name) + } } -impl<'a, 'de> Visitor<'de> for ReflectVisitor<'a> { - type Value = Box; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("reflect value") +impl StructLikeInfo for StructVariantInfo { + fn get_name(&self) -> &str { + self.name() } - fn visit_u8(self, v: u8) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field(&self, name: &str) -> Option<&NamedField> { + self.field(name) } +} - fn visit_bool(self, v: bool) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) +impl TupleLikeInfo for TupleInfo { + fn get_name(&self) -> &str { + self.type_name() } - fn visit_u16(self, v: u16) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field(&self, index: usize) -> Option<&UnnamedField> { + self.field_at(index) } - fn visit_u32(self, v: u32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field_len(&self) -> usize { + self.field_len() } +} - fn visit_u64(self, v: u64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) +impl TupleLikeInfo for TupleVariantInfo { + fn get_name(&self) -> &str { + self.name() } - fn visit_i8(self, v: i8) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field(&self, index: usize) -> Option<&UnnamedField> { + self.field_at(index) } - fn visit_i16(self, v: i16) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field_len(&self) -> usize { + self.field_len() } +} - fn visit_i32(self, v: i32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } +/// A general purpose deserializer for reflected types. +/// +/// For non-value types, this will return the dynamic equivalent. For example, a +/// deserialized struct will return a [`DynamicStruct`] and a `Vec` will return a +/// [`DynamicList`]. +/// +/// The serialized data must take the form of a map containing the following entries: +/// 1. `type`: The _full_ [type name] +/// 2. `value`: The serialized value of the reflected type +/// +/// > Note: The ordering is important here. `type` _must_ come before `value`. +/// +/// [`DynamicStruct`]: crate::DynamicStruct +/// [`DynamicList`]: crate::DynamicList +/// [type name]: std::any::type_name +pub struct ReflectDeserializer<'a> { + registry: &'a TypeRegistry, +} - fn visit_i64(self, v: i64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) +impl<'a> ReflectDeserializer<'a> { + pub fn new(registry: &'a TypeRegistry) -> Self { + ReflectDeserializer { registry } } +} - fn visit_f32(self, v: f32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } +impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { + type Value = Box; - fn visit_f64(self, v: f64) -> Result + fn deserialize(self, deserializer: D) -> Result where - E: de::Error, + D: serde::Deserializer<'de>, { - Ok(Box::new(v)) + deserializer.deserialize_any(ReflectDeserializerVisitor { + registry: self.registry, + }) } +} - fn visit_string(self, v: String) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) - } +struct ReflectDeserializerVisitor<'a> { + registry: &'a TypeRegistry, +} - fn visit_str(self, v: &str) -> Result - where - E: de::Error, - { - Ok(Box::new(v.to_string())) +impl<'a, 'de> Visitor<'de> for ReflectDeserializerVisitor<'a> { + type Value = Box; + + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + formatter.write_str("map containing `type` and `value` entries for the reflected value") } - fn visit_map(self, mut map: V) -> Result + fn visit_map(self, mut map: A) -> Result where - V: MapAccess<'de>, + A: MapAccess<'de>, { - let mut type_name: Option = None; - while let Some(key) = map.next_key::()? { - match key.as_str() { - type_fields::TYPE => { - type_name = Some(map.next_value()?); - } - type_fields::MAP => { - let _type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let map = map.next_value_seed(MapDeserializer { - registry: self.registry, - })?; - return Ok(Box::new(map)); - } - type_fields::STRUCT => { - let type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let mut dynamic_struct = map.next_value_seed(StructDeserializer { - registry: self.registry, - })?; - dynamic_struct.set_name(type_name); - return Ok(Box::new(dynamic_struct)); - } - type_fields::TUPLE_STRUCT => { - let type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let mut tuple_struct = map.next_value_seed(TupleStructDeserializer { - registry: self.registry, - })?; - tuple_struct.set_name(type_name); - return Ok(Box::new(tuple_struct)); - } - type_fields::TUPLE => { - let _type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let tuple = map.next_value_seed(TupleDeserializer { - registry: self.registry, - })?; - return Ok(Box::new(tuple)); - } - type_fields::LIST => { - let _type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let list = map.next_value_seed(ListDeserializer { - registry: self.registry, - })?; - return Ok(Box::new(list)); - } - type_fields::ARRAY => { - let _type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let array = map.next_value_seed(ArrayDeserializer { - registry: self.registry, - })?; - return Ok(Box::new(array)); - } - type_fields::ENUM => { - let type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let mut dynamic_enum = map.next_value_seed(EnumDeserializer { - registry: self.registry, - })?; - dynamic_enum.set_name(type_name); - return Ok(Box::new(dynamic_enum)); - } - type_fields::VALUE => { - let type_name = type_name - .take() - .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; - let registration = - self.registry.get_with_name(&type_name).ok_or_else(|| { - de::Error::custom(format_args!( - "No registration found for {}", - type_name - )) - })?; - let deserialize_reflect = - registration.data::().ok_or_else(|| { - de::Error::custom(format_args!( - "The TypeRegistration for {} doesn't have DeserializeReflect", - type_name - )) - })?; - let value = map.next_value_seed(DeserializeReflectDeserializer { - reflect_deserialize: deserialize_reflect, - })?; - return Ok(value); - } - _ => return Err(de::Error::unknown_field(key.as_str(), &[])), + let type_name = match map.next_key::<&str>()? { + Some(type_fields::TYPE) => map.next_value::<&str>()?, + Some(type_fields::VALUE) => { + // `type` must come before `value`. + return Err(de::Error::missing_field(type_fields::TYPE)); } - } + Some(field) => { + return Err(de::Error::unknown_field(field, &[type_fields::TYPE])); + } + None => { + return Err(de::Error::invalid_length( + 0, + &"two entries: `type` and `value`", + )); + } + }; - Err(de::Error::custom("Maps in this location must have the \'type\' field and one of the following fields: \'map\', \'seq\', \'value\'")) + match map.next_key::<&str>()? { + Some(type_fields::VALUE) => { + let registration = self.registry.get_with_name(&type_name).ok_or_else(|| { + de::Error::custom(format_args!("No registration found for {}", type_name)) + })?; + let type_info = registration.type_info(); + let value = map.next_value_seed(TypedReflectDeserializer { + type_info, + registry: self.registry, + })?; + Ok(value) + } + Some(type_fields::TYPE) => Err(de::Error::duplicate_field(type_fields::TYPE)), + Some(field) => Err(de::Error::unknown_field(field, &[type_fields::VALUE])), + None => { + return Err(de::Error::invalid_length( + 0, + &"two entries: `type` and `value`", + )); + } + } } } -struct DeserializeReflectDeserializer<'a> { - reflect_deserialize: &'a ReflectDeserialize, +/// A deserializer for reflected types whose [`TypeInfo`] is known. +/// +/// For non-value types, this will return the dynamic equivalent. For example, a +/// deserialized struct will return a [`DynamicStruct`] and a `Vec` will return a +/// [`DynamicList`]. +/// +/// [`TypeInfo`]: crate::TypeInfo +/// [`DynamicStruct`]: crate::DynamicStruct +/// [`DynamicList`]: crate::DynamicList +pub struct TypedReflectDeserializer<'a> { + type_info: &'a TypeInfo, + registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for DeserializeReflectDeserializer<'a> { +impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { type Value = Box; fn deserialize(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { - self.reflect_deserialize.deserialize(deserializer) + // Handle both Value case and types that have a custom `ReflectDeserialize` + let type_id = self.type_info.type_id(); + let type_name = self.type_info.type_name(); + let registration = self.registry.get(type_id).ok_or_else(|| { + de::Error::custom(format_args!("no registration found for {}", type_name)) + })?; + + if let Some(deserialize_reflect) = registration.data::() { + let value = deserialize_reflect.deserialize(deserializer)?; + return Ok(value); + } + + match self.type_info { + TypeInfo::Struct(struct_info) => { + let mut dynamic_struct = deserializer.deserialize_map(StructVisitor { + struct_info, + registry: self.registry, + })?; + dynamic_struct.set_name(struct_info.type_name().to_string()); + Ok(Box::new(dynamic_struct)) + } + TypeInfo::TupleStruct(tuple_struct_info) => { + let mut dynamic_tuple_struct = deserializer.deserialize_tuple( + tuple_struct_info.field_len(), + TupleStructVisitor { + tuple_struct_info, + registry: self.registry, + }, + )?; + dynamic_tuple_struct.set_name(tuple_struct_info.type_name().to_string()); + Ok(Box::new(dynamic_tuple_struct)) + } + TypeInfo::List(list_info) => { + let mut dynamic_list = deserializer.deserialize_seq(ListVisitor { + list_info, + registry: self.registry, + })?; + dynamic_list.set_name(list_info.type_name().to_string()); + Ok(Box::new(dynamic_list)) + } + TypeInfo::Array(array_info) => { + let mut dynamic_array = deserializer.deserialize_tuple( + array_info.capacity(), + ArrayVisitor { + array_info, + registry: self.registry, + }, + )?; + dynamic_array.set_name(array_info.type_name().to_string()); + Ok(Box::new(dynamic_array)) + } + TypeInfo::Map(map_info) => { + let mut dynamic_map = deserializer.deserialize_map(MapVisitor { + map_info, + registry: self.registry, + })?; + dynamic_map.set_name(map_info.type_name().to_string()); + Ok(Box::new(dynamic_map)) + } + TypeInfo::Tuple(tuple_info) => { + let mut dynamic_tuple = deserializer.deserialize_tuple( + tuple_info.field_len(), + TupleVisitor { + tuple_info, + registry: self.registry, + }, + )?; + dynamic_tuple.set_name(tuple_info.type_name().to_string()); + Ok(Box::new(dynamic_tuple)) + } + TypeInfo::Enum(enum_info) => { + let mut dynamic_enum = deserializer.deserialize_map(EnumVisitor { + enum_info, + registry: self.registry, + })?; + dynamic_enum.set_name(enum_info.type_name().to_string()); + Ok(Box::new(dynamic_enum)) + } + TypeInfo::Value(_) => { + // This case should already be handled + Err(de::Error::custom(format_args!( + "the TypeRegistration for {} doesn't have ReflectDeserialize", + type_name + ))) + } + TypeInfo::Dynamic(_) => { + // We could potentially allow this but we'd have no idea what the actual types of the + // fields are and would rely on the deserializer to determine them (e.g. `i32` vs `i64`) + Err(de::Error::custom(format_args!( + "cannot deserialize arbitrary dynamic type {}", + type_name + ))) + } + } } } -struct ListDeserializer<'a> { +struct StructVisitor<'a> { + struct_info: &'a StructInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for ListDeserializer<'a> { - type Value = DynamicList; +impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { + type Value = DynamicStruct; - fn deserialize(self, deserializer: D) -> Result + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("reflected struct value") + } + + fn visit_map(self, mut map: V) -> Result where - D: serde::Deserializer<'de>, + V: MapAccess<'de>, { - deserializer.deserialize_seq(ListVisitor { - registry: self.registry, - }) + visit_struct(&mut map, self.struct_info, self.registry) } } -struct ListVisitor<'a> { +struct TupleStructVisitor<'a> { + tuple_struct_info: &'a TupleStructInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { - type Value = DynamicList; +impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { + type Value = DynamicTupleStruct; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("list value") + formatter.write_str("reflected tuple struct value") } fn visit_seq(self, mut seq: V) -> Result where V: SeqAccess<'de>, { - let mut list = DynamicList::default(); - while let Some(value) = seq.next_element_seed(ReflectDeserializer { + let mut index = 0usize; + let mut tuple_struct = DynamicTupleStruct::default(); + + let get_field_info = |index: usize| -> Result<&'a TypeInfo, V::Error> { + let field = self.tuple_struct_info.field_at(index).ok_or_else(|| { + de::Error::custom(format_args!( + "no field at index {} on tuple {}", + index, + self.tuple_struct_info.type_name(), + )) + })?; + get_type_info(field.type_id(), field.type_name(), self.registry) + }; + + while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { + type_info: get_field_info(index)?, registry: self.registry, })? { - list.push_box(value); + tuple_struct.insert_boxed(value); + index += 1; + if index >= self.tuple_struct_info.field_len() { + break; + } } - Ok(list) + + if tuple_struct.field_len() != self.tuple_struct_info.field_len() { + return Err(Error::invalid_length( + tuple_struct.field_len(), + &self.tuple_struct_info.field_len().to_string().as_str(), + )); + } + + Ok(tuple_struct) } } -struct ArrayDeserializer<'a> { +struct ListVisitor<'a> { + list_info: &'a ListInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for ArrayDeserializer<'a> { - type Value = DynamicArray; +impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { + type Value = DynamicList; - fn deserialize(self, deserializer: D) -> Result + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("reflected list value") + } + + fn visit_seq(self, mut seq: V) -> Result where - D: serde::Deserializer<'de>, + V: SeqAccess<'de>, { - deserializer.deserialize_seq(ArrayVisitor { + let mut list = DynamicList::default(); + let type_info = get_type_info( + self.list_info.item_type_id(), + self.list_info.item_type_name(), + self.registry, + )?; + while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { + type_info, registry: self.registry, - }) + })? { + list.push_box(value); + } + Ok(list) } } struct ArrayVisitor<'a> { + array_info: &'a ArrayInfo, registry: &'a TypeRegistry, } @@ -326,7 +400,7 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { type Value = DynamicArray; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("array value") + formatter.write_str("reflected array value") } fn visit_seq(self, mut seq: V) -> Result @@ -334,34 +408,31 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { V: SeqAccess<'de>, { let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default()); - while let Some(value) = seq.next_element_seed(ReflectDeserializer { + let type_info = get_type_info( + self.array_info.item_type_id(), + self.array_info.item_type_name(), + self.registry, + )?; + while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { + type_info, registry: self.registry, })? { vec.push(value); } - Ok(DynamicArray::new(Box::from(vec))) - } -} - -struct MapDeserializer<'a> { - registry: &'a TypeRegistry, -} - -impl<'a, 'de> DeserializeSeed<'de> for MapDeserializer<'a> { - type Value = DynamicMap; + if vec.len() != self.array_info.capacity() { + return Err(Error::invalid_length( + vec.len(), + &self.array_info.capacity().to_string().as_str(), + )); + } - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_map(MapVisitor { - registry: self.registry, - }) + Ok(DynamicArray::new(vec.into_boxed_slice())) } } struct MapVisitor<'a> { + map_info: &'a MapInfo, registry: &'a TypeRegistry, } @@ -369,7 +440,7 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { type Value = DynamicMap; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("map value") + formatter.write_str("reflected map value") } fn visit_map(self, mut map: V) -> Result @@ -377,10 +448,22 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { V: MapAccess<'de>, { let mut dynamic_map = DynamicMap::default(); - while let Some(key) = map.next_key_seed(ReflectDeserializer { + let key_type_info = get_type_info( + self.map_info.key_type_id(), + self.map_info.key_type_name(), + self.registry, + )?; + let value_type_info = get_type_info( + self.map_info.value_type_id(), + self.map_info.value_type_name(), + self.registry, + )?; + while let Some(key) = map.next_key_seed(TypedReflectDeserializer { + type_info: key_type_info, registry: self.registry, })? { - let value = map.next_value_seed(ReflectDeserializer { + let value = map.next_value_seed(TypedReflectDeserializer { + type_info: value_type_info, registry: self.registry, })?; dynamic_map.insert_boxed(key, value); @@ -390,220 +473,305 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { } } -struct StructDeserializer<'a> { +struct TupleVisitor<'a> { + tuple_info: &'a TupleInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for StructDeserializer<'a> { - type Value = DynamicStruct; +impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { + type Value = DynamicTuple; - fn deserialize(self, deserializer: D) -> Result + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("reflected tuple value") + } + + fn visit_seq(self, mut seq: V) -> Result where - D: serde::Deserializer<'de>, + V: SeqAccess<'de>, { - deserializer.deserialize_map(StructVisitor { - registry: self.registry, - }) + visit_tuple(&mut seq, self.tuple_info, self.registry) } } -struct StructVisitor<'a> { +struct EnumVisitor<'a> { + enum_info: &'a EnumInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { - type Value = DynamicStruct; +impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { + type Value = DynamicEnum; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("struct value") + formatter.write_str("reflected enum value") } fn visit_map(self, mut map: V) -> Result where V: MapAccess<'de>, { - let mut dynamic_struct = DynamicStruct::default(); - while let Some(key) = map.next_key::()? { - let value = map.next_value_seed(ReflectDeserializer { - registry: self.registry, - })?; - dynamic_struct.insert_boxed(&key, value); + let variant_name = map + .next_key::<&str>()? + .ok_or_else(|| Error::missing_field("the variant name of the enum"))?; + + let variant_info = self + .enum_info + .variant(variant_name) + .ok_or_else(|| Error::custom(format_args!("unknown variant {}", variant_name)))?; + + let mut dynamic_enum = DynamicEnum::default(); + + match variant_info { + VariantInfo::Struct(struct_info) => { + let dynamic_struct = map.next_value_seed(StructVariantDeserializer { + struct_info, + registry: self.registry, + })?; + dynamic_enum.set_variant(variant_name, dynamic_struct); + } + VariantInfo::Tuple(tuple_info) => { + let dynamic_tuple = map.next_value_seed(TupleVariantDeserializer { + tuple_info, + registry: self.registry, + })?; + dynamic_enum.set_variant(variant_name, dynamic_tuple); + } + VariantInfo::Unit(..) => { + map.next_value::<()>()?; + dynamic_enum.set_variant(variant_name, ()); + } } - Ok(dynamic_struct) + Ok(dynamic_enum) } } -struct TupleStructDeserializer<'a> { +struct StructVariantDeserializer<'a> { + struct_info: &'a StructVariantInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for TupleStructDeserializer<'a> { - type Value = DynamicTupleStruct; +impl<'a, 'de> DeserializeSeed<'de> for StructVariantDeserializer<'a> { + type Value = DynamicStruct; fn deserialize(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { - deserializer.deserialize_seq(TupleStructVisitor { + deserializer.deserialize_map(StructVariantVisitor { + struct_info: self.struct_info, registry: self.registry, }) } } -struct TupleStructVisitor<'a> { +struct StructVariantVisitor<'a> { + struct_info: &'a StructVariantInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { - type Value = DynamicTupleStruct; +impl<'a, 'de> Visitor<'de> for StructVariantVisitor<'a> { + type Value = DynamicStruct; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("tuple struct value") + formatter.write_str("reflected struct variant value") } - fn visit_seq(self, mut seq: V) -> Result + fn visit_map(self, mut map: V) -> Result where - V: SeqAccess<'de>, + V: MapAccess<'de>, { - let mut tuple_struct = DynamicTupleStruct::default(); - while let Some(value) = seq.next_element_seed(ReflectDeserializer { - registry: self.registry, - })? { - tuple_struct.insert_boxed(value); - } - Ok(tuple_struct) + visit_struct(&mut map, self.struct_info, self.registry) } } -struct TupleDeserializer<'a> { +struct TupleVariantDeserializer<'a> { + tuple_info: &'a TupleVariantInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for TupleDeserializer<'a> { +impl<'a, 'de> DeserializeSeed<'de> for TupleVariantDeserializer<'a> { type Value = DynamicTuple; fn deserialize(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { - deserializer.deserialize_seq(TupleVisitor { - registry: self.registry, - }) + deserializer.deserialize_tuple( + self.tuple_info.field_len(), + TupleVariantVisitor { + tuple_info: self.tuple_info, + registry: self.registry, + }, + ) } } -struct TupleVisitor<'a> { +struct TupleVariantVisitor<'a> { + tuple_info: &'a TupleVariantInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { +impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'a> { type Value = DynamicTuple; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("tuple value") + formatter.write_str("reflected tuple variant value") } fn visit_seq(self, mut seq: V) -> Result where V: SeqAccess<'de>, { - let mut tuple = DynamicTuple::default(); - while let Some(value) = seq.next_element_seed(ReflectDeserializer { - registry: self.registry, - })? { - tuple.insert_boxed(value); + visit_tuple(&mut seq, self.tuple_info, self.registry) + } +} + +fn visit_struct<'de, T, V>( + map: &mut V, + info: &T, + registry: &TypeRegistry, +) -> Result +where + T: StructLikeInfo, + V: MapAccess<'de>, +{ + let mut dynamic_struct = DynamicStruct::default(); + while let Some(key) = map.next_key::()? { + let field = info.get_field(&key).ok_or_else(|| { + Error::custom(format_args!( + "no field named {} on struct {}", + key, + info.get_name(), + )) + })?; + let type_info = get_type_info(field.type_id(), field.type_name(), registry)?; + let value = map.next_value_seed(TypedReflectDeserializer { + type_info, + registry, + })?; + dynamic_struct.insert_boxed(&key, value); + } + + Ok(dynamic_struct) +} + +fn visit_tuple<'de, T, V>( + seq: &mut V, + info: &T, + registry: &TypeRegistry, +) -> Result +where + T: TupleLikeInfo, + V: SeqAccess<'de>, +{ + let mut tuple = DynamicTuple::default(); + let mut index = 0usize; + + let get_field_info = |index: usize| -> Result<&TypeInfo, V::Error> { + let field = info.get_field(index).ok_or_else(|| { + Error::custom(format_args!( + "no field at index {} on tuple {}", + index, + info.get_name(), + )) + })?; + get_type_info(field.type_id(), field.type_name(), registry) + }; + + while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { + type_info: get_field_info(index)?, + registry, + })? { + tuple.insert_boxed(value); + index += 1; + if index >= info.get_field_len() { + break; } - Ok(tuple) } -} -struct EnumDeserializer<'a> { - registry: &'a TypeRegistry, -} + let len = info.get_field_len(); -impl<'a, 'de> DeserializeSeed<'de> for EnumDeserializer<'a> { - type Value = DynamicEnum; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_map(EnumVisitor { - registry: self.registry, - }) + if tuple.field_len() != len { + return Err(Error::invalid_length( + tuple.field_len(), + &len.to_string().as_str(), + )); } -} -struct EnumVisitor<'a> { - registry: &'a TypeRegistry, + Ok(tuple) } -impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { - type Value = DynamicEnum; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("enum value") - } - - fn visit_map(self, mut map: V) -> Result - where - V: MapAccess<'de>, - { - let key = map.next_key::()?; - match key.as_deref() { - Some(type_fields::VARIANT) => {} - Some(key) => return Err(V::Error::unknown_field(key, &[type_fields::VARIANT])), - _ => { - return Err(V::Error::missing_field(type_fields::VARIANT)); - } - } - - let variant_name = map.next_value::()?; - - let mut dynamic_enum = DynamicEnum::default(); - - let key = map.next_key::()?; - match key.as_deref() { - Some(type_fields::STRUCT) => { - let dynamic_struct = map.next_value_seed(StructDeserializer { - registry: self.registry, - })?; - dynamic_enum.set_variant(variant_name, dynamic_struct); - } - Some(type_fields::TUPLE) => { - let dynamic_tuple = map.next_value_seed(TupleDeserializer { - registry: self.registry, - })?; - dynamic_enum.set_variant(variant_name, dynamic_tuple); - } - Some(invalid_key) => { - return Err(V::Error::unknown_field( - invalid_key, - &[type_fields::STRUCT, type_fields::TUPLE], - )); - } - None => dynamic_enum.set_variant(variant_name, ()), - } - - Ok(dynamic_enum) - } +fn get_type_info<'a, E: de::Error>( + type_id: TypeId, + type_name: &'a str, + registry: &'a TypeRegistry, +) -> Result<&'a TypeInfo, E> { + let registration = registry.get(type_id).ok_or_else(|| { + de::Error::custom(format_args!("no registration found for type {}", type_name)) + })?; + Ok(registration.type_info()) } #[cfg(test)] mod tests { - use super::ReflectDeserializer; use crate as bevy_reflect; - use crate::prelude::*; - use crate::{DynamicEnum, TypeRegistry}; - use ::serde::de::DeserializeSeed; + use crate::serde::ReflectDeserializer; + use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry}; + use bevy_utils::HashMap; + use serde::de::DeserializeSeed; + use serde::Deserialize; + + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct MyStruct { + primitive_value: i8, + option_value: Option, + tuple_value: (f32, usize), + list_value: Vec, + array_value: [i32; 5], + map_value: HashMap, + struct_value: SomeStruct, + tuple_struct_value: SomeTupleStruct, + custom_deserialize: CustomDeserialize, + } + + #[derive(Reflect, FromReflect, Debug, PartialEq, Deserialize)] + struct SomeStruct { + foo: i64, + } + + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct SomeTupleStruct(String); + + /// Implements a custom deserialize using #[reflect(Deserialize)]. + /// + /// For testing purposes, this is just the auto-generated one from deriving. + #[derive(Reflect, FromReflect, Debug, PartialEq, Deserialize)] + #[reflect(Deserialize)] + struct CustomDeserialize { + value: usize, + #[serde(rename = "renamed")] + inner_struct: SomeStruct, + } fn get_registry() -> TypeRegistry { let mut registry = TypeRegistry::default(); - registry.register::(); - registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); registry.register::(); - registry.register::<(f32, f32)>(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::<(f32, usize)>(); + registry.register::<[i32; 5]>(); + registry.register::>(); + registry.register::>(); + registry.register::>(); + registry.register_type_data::, ReflectDeserialize>(); registry } @@ -622,11 +790,11 @@ mod tests { // === Unit Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "enum": { - "variant": "Unit", - }, -}"#; + "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", + "value": { + "Unit": (), + }, + }"#; let reflect_deserializer = ReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -636,17 +804,11 @@ mod tests { // === NewType Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "enum": { - "variant": "NewType", - "tuple": [ - { - "type": "usize", - "value": 123, + "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", + "value": { + "NewType": (123), }, - ], - }, -}"#; + }"#; let reflect_deserializer = ReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -656,21 +818,11 @@ mod tests { // === Tuple Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "enum": { - "variant": "Tuple", - "tuple": [ - { - "type": "f32", - "value": 1.23, - }, - { - "type": "f32", - "value": 3.21, + "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", + "value": { + "Tuple": (1.23, 3.21), }, - ], - }, -}"#; + }"#; let reflect_deserializer = ReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -680,17 +832,13 @@ mod tests { // === Struct Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "enum": { - "variant": "Struct", - "struct": { + "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", "value": { - "type": "alloc::string::String", - "value": "I <3 Enums", + "Struct": { + "value": "I <3 Enums", + }, }, - }, - }, -}"#; + }"#; let reflect_deserializer = ReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -700,4 +848,75 @@ mod tests { }); assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); } + + #[test] + fn should_deserialize() { + let mut map = HashMap::new(); + map.insert(64, 32); + + // TODO: Add test for standard tuples (requires https://github.com/bevyengine/bevy/pull/4226) + let expected = MyStruct { + primitive_value: 123, + option_value: Some(String::from("Hello world!")), + tuple_value: (3.14, 1337), + list_value: vec![-2, -1, 0, 1, 2], + array_value: [-2, -1, 0, 1, 2], + map_value: map, + struct_value: SomeStruct { foo: 999999999 }, + tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")), + custom_deserialize: CustomDeserialize { + value: 100, + inner_struct: SomeStruct { foo: 101 }, + }, + }; + + let input = r#"{ + "type": "bevy_reflect::serde::de::tests::MyStruct", + "value": { + "primitive_value": 123, + "option_value": Some("Hello world!"), + "tuple_value": ( + 3.14, + 1337, + ), + "list_value": [ + -2, + -1, + 0, + 1, + 2, + ], + "array_value": ( + -2, + -1, + 0, + 1, + 2, + ), + "map_value": { + 64: 32, + }, + "struct_value": { + "foo": 999999999, + }, + "tuple_struct_value": ("Tuple Struct"), + "custom_deserialize": ( + value: 100, + renamed: ( + foo: 101, + ), + ) + }, + }"#; + + let registry = get_registry(); + let reflect_deserializer = ReflectDeserializer::new(®istry); + let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let dynamic_output = reflect_deserializer + .deserialize(&mut ron_deserializer) + .unwrap(); + + let output = ::from_reflect(dynamic_output.as_ref()).unwrap(); + assert_eq!(expected, output); + } } diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index 7c7c18f4ea954..882ddbe8f0995 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -6,13 +6,5 @@ pub use ser::*; pub(crate) mod type_fields { pub const TYPE: &str = "type"; - pub const MAP: &str = "map"; - pub const STRUCT: &str = "struct"; - pub const TUPLE_STRUCT: &str = "tuple_struct"; - pub const ENUM: &str = "enum"; - pub const VARIANT: &str = "variant"; - pub const TUPLE: &str = "tuple"; - pub const LIST: &str = "list"; - pub const ARRAY: &str = "array"; pub const VALUE: &str = "value"; } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 0dd239d6305a7..74e0190bee665 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -2,7 +2,7 @@ use crate::{ serde::type_fields, Array, Enum, List, Map, Reflect, ReflectRef, ReflectSerialize, Struct, Tuple, TupleStruct, TypeRegistry, VariantType, }; -use serde::ser::Error; +use serde::ser::SerializeTuple; use serde::{ ser::{SerializeMap, SerializeSeq}, Serialize, Serializer, @@ -38,6 +38,13 @@ fn get_serializable<'a, E: serde::ser::Error>( Ok(reflect_serialize.get_serializable(reflect_value)) } +/// A general purpose serializer for reflected types. +/// +/// The serialized data will take the form of a map containing the following entries: +/// 1. `type`: The _full_ [type name] +/// 2. `value`: The serialized value of the reflected type +/// +/// [type name]: std::any::type_name pub struct ReflectSerializer<'a> { pub value: &'a dyn Reflect, pub registry: &'a TypeRegistry, @@ -54,6 +61,40 @@ impl<'a> Serialize for ReflectSerializer<'a> { where S: serde::Serializer, { + let mut state = serializer.serialize_map(Some(2))?; + state.serialize_entry(type_fields::TYPE, self.value.type_name())?; + state.serialize_entry( + type_fields::VALUE, + &TypedReflectSerializer::new(self.value, self.registry), + )?; + state.end() + } +} + +/// A serializer for reflected types whose type is known and does not require +/// serialization to include other metadata about it. +pub struct TypedReflectSerializer<'a> { + pub value: &'a dyn Reflect, + pub registry: &'a TypeRegistry, +} + +impl<'a> TypedReflectSerializer<'a> { + pub fn new(value: &'a dyn Reflect, registry: &'a TypeRegistry) -> Self { + TypedReflectSerializer { value, registry } + } +} + +impl<'a> Serialize for TypedReflectSerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + // Handle both Value case and types that have a custom `Serialize` + let serializable = get_serializable::(self.value, self.registry); + if let Ok(serializable) = serializable { + return serializable.borrow().serialize(serializer); + } + match self.value.reflect_ref() { ReflectRef::Struct(value) => StructSerializer { struct_value: value, @@ -90,11 +131,7 @@ impl<'a> Serialize for ReflectSerializer<'a> { registry: self.registry, } .serialize(serializer), - ReflectRef::Value(value) => ReflectValueSerializer { - registry: self.registry, - value, - } - .serialize(serializer), + ReflectRef::Value(_) => Err(serializable.err().unwrap()), } } } @@ -109,13 +146,9 @@ impl<'a> Serialize for ReflectValueSerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_map(Some(2))?; - state.serialize_entry(type_fields::TYPE, self.value.type_name())?; - state.serialize_entry( - type_fields::VALUE, - get_serializable::(self.value, self.registry)?.borrow(), - )?; - state.end() + get_serializable::(self.value, self.registry)? + .borrow() + .serialize(serializer) } } @@ -125,30 +158,6 @@ pub struct StructSerializer<'a> { } impl<'a> Serialize for StructSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_map(Some(2))?; - - state.serialize_entry(type_fields::TYPE, self.struct_value.type_name())?; - state.serialize_entry( - type_fields::STRUCT, - &StructValueSerializer { - struct_value: self.struct_value, - registry: self.registry, - }, - )?; - state.end() - } -} - -pub struct StructValueSerializer<'a> { - pub struct_value: &'a dyn Struct, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for StructValueSerializer<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -156,7 +165,7 @@ impl<'a> Serialize for StructValueSerializer<'a> { let mut state = serializer.serialize_map(Some(self.struct_value.field_len()))?; for (index, value) in self.struct_value.iter_fields().enumerate() { let key = self.struct_value.name_at(index).unwrap(); - state.serialize_entry(key, &ReflectSerializer::new(value, self.registry))?; + state.serialize_entry(key, &TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -172,33 +181,9 @@ impl<'a> Serialize for TupleStructSerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_map(Some(2))?; - - state.serialize_entry(type_fields::TYPE, self.tuple_struct.type_name())?; - state.serialize_entry( - type_fields::TUPLE_STRUCT, - &TupleStructValueSerializer { - tuple_struct: self.tuple_struct, - registry: self.registry, - }, - )?; - state.end() - } -} - -pub struct TupleStructValueSerializer<'a> { - pub tuple_struct: &'a dyn TupleStruct, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for TupleStructValueSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_seq(Some(self.tuple_struct.field_len()))?; + let mut state = serializer.serialize_tuple(self.tuple_struct.field_len())?; for value in self.tuple_struct.iter_fields() { - state.serialize_element(&ReflectSerializer::new(value, self.registry))?; + state.serialize_element(&TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -214,11 +199,9 @@ impl<'a> Serialize for EnumSerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_map(Some(2))?; - - state.serialize_entry(type_fields::TYPE, self.enum_value.type_name())?; + let mut state = serializer.serialize_map(Some(1))?; state.serialize_entry( - type_fields::ENUM, + self.enum_value.variant_name(), &EnumValueSerializer { enum_value: self.enum_value, registry: self.registry, @@ -238,36 +221,26 @@ impl<'a> Serialize for EnumValueSerializer<'a> { where S: serde::Serializer, { - let variant_type = self.enum_value.variant_type(); - let variant_name = self.enum_value.variant_name(); - - let mut state = if matches!(variant_type, VariantType::Unit) { - serializer.serialize_map(Some(1))? - } else { - serializer.serialize_map(Some(2))? - }; - - state.serialize_entry(type_fields::VARIANT, variant_name)?; - match self.enum_value.variant_type() { VariantType::Struct => { - state.serialize_key(type_fields::STRUCT)?; - state.serialize_value(&StructVariantSerializer { - enum_value: self.enum_value, - registry: self.registry, - })?; + let mut state = serializer.serialize_map(Some(self.enum_value.field_len()))?; + for field in self.enum_value.iter_fields() { + let key = field.name().expect("named field"); + let value = TypedReflectSerializer::new(field.value(), self.registry); + state.serialize_entry(key, &value)?; + } + state.end() } VariantType::Tuple => { - state.serialize_key(type_fields::TUPLE)?; - state.serialize_value(&TupleVariantSerializer { - enum_value: self.enum_value, - registry: self.registry, - })?; + let mut state = serializer.serialize_tuple(self.enum_value.field_len())?; + for field in self.enum_value.iter_fields() { + let value = TypedReflectSerializer::new(field.value(), self.registry); + state.serialize_element(&value)?; + } + state.end() } - _ => {} + VariantType::Unit => serializer.serialize_unit(), } - - state.end() } } @@ -281,10 +254,10 @@ impl<'a> Serialize for TupleVariantSerializer<'a> { where S: Serializer, { - let field_len = self.enum_value.field_len(); - let mut state = serializer.serialize_seq(Some(field_len))?; + let mut state = serializer.serialize_tuple(self.enum_value.field_len())?; for field in self.enum_value.iter_fields() { - state.serialize_element(&ReflectSerializer::new(field.value(), self.registry))?; + let value = TypedReflectSerializer::new(field.value(), self.registry); + state.serialize_element(&value)?; } state.end() } @@ -300,16 +273,11 @@ impl<'a> Serialize for StructVariantSerializer<'a> { where S: Serializer, { - let field_len = self.enum_value.field_len(); - let mut state = serializer.serialize_map(Some(field_len))?; - for (index, field) in self.enum_value.iter_fields().enumerate() { - let name = field.name().ok_or_else(|| { - S::Error::custom(format_args!( - "struct variant missing name for field at index {}", - index - )) - })?; - state.serialize_entry(name, &ReflectSerializer::new(field.value(), self.registry))?; + let mut state = serializer.serialize_map(Some(self.enum_value.field_len()))?; + for field in self.enum_value.iter_fields() { + let key = field.name().expect("named field"); + let value = TypedReflectSerializer::new(field.value(), self.registry); + state.serialize_entry(key, &value)?; } state.end() } @@ -325,33 +293,9 @@ impl<'a> Serialize for TupleSerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_map(Some(2))?; - - state.serialize_entry(type_fields::TYPE, self.tuple.type_name())?; - state.serialize_entry( - type_fields::TUPLE, - &TupleValueSerializer { - tuple: self.tuple, - registry: self.registry, - }, - )?; - state.end() - } -} - -pub struct TupleValueSerializer<'a> { - pub tuple: &'a dyn Tuple, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for TupleValueSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_seq(Some(self.tuple.field_len()))?; + let mut state = serializer.serialize_tuple(self.tuple.field_len())?; for value in self.tuple.iter_fields() { - state.serialize_element(&ReflectSerializer::new(value, self.registry))?; + state.serialize_element(&TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -363,30 +307,6 @@ pub struct MapSerializer<'a> { } impl<'a> Serialize for MapSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_map(Some(2))?; - - state.serialize_entry(type_fields::TYPE, self.map.type_name())?; - state.serialize_entry( - type_fields::MAP, - &MapValueSerializer { - map: self.map, - registry: self.registry, - }, - )?; - state.end() - } -} - -pub struct MapValueSerializer<'a> { - pub map: &'a dyn Map, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for MapValueSerializer<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -394,8 +314,8 @@ impl<'a> Serialize for MapValueSerializer<'a> { let mut state = serializer.serialize_map(Some(self.map.len()))?; for (key, value) in self.map.iter() { state.serialize_entry( - &ReflectSerializer::new(key, self.registry), - &ReflectSerializer::new(value, self.registry), + &TypedReflectSerializer::new(key, self.registry), + &TypedReflectSerializer::new(value, self.registry), )?; } state.end() @@ -408,36 +328,13 @@ pub struct ListSerializer<'a> { } impl<'a> Serialize for ListSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_map(Some(2))?; - state.serialize_entry(type_fields::TYPE, self.list.type_name())?; - state.serialize_entry( - type_fields::LIST, - &ListValueSerializer { - list: self.list, - registry: self.registry, - }, - )?; - state.end() - } -} - -pub struct ListValueSerializer<'a> { - pub list: &'a dyn List, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for ListValueSerializer<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { let mut state = serializer.serialize_seq(Some(self.list.len()))?; for value in self.list.iter() { - state.serialize_element(&ReflectSerializer::new(value, self.registry))?; + state.serialize_element(&TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -453,32 +350,9 @@ impl<'a> Serialize for ArraySerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_map(Some(2))?; - state.serialize_entry(type_fields::TYPE, self.array.type_name())?; - state.serialize_entry( - type_fields::ARRAY, - &ArrayValueSerializer { - array: self.array, - registry: self.registry, - }, - )?; - state.end() - } -} - -pub struct ArrayValueSerializer<'a> { - pub array: &'a dyn Array, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for ArrayValueSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_seq(Some(self.array.len()))?; + let mut state = serializer.serialize_tuple(self.array.len())?; for value in self.array.iter() { - state.serialize_element(&ReflectSerializer::new(value, self.registry))?; + state.serialize_element(&TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -486,21 +360,113 @@ impl<'a> Serialize for ArrayValueSerializer<'a> { #[cfg(test)] mod tests { - use super::ReflectSerializer; use crate as bevy_reflect; - use crate::prelude::*; - use crate::TypeRegistry; + use crate::serde::ReflectSerializer; + use crate::{Reflect, ReflectSerialize, TypeRegistry}; + use bevy_utils::HashMap; use ron::ser::PrettyConfig; + use serde::Serialize; + + #[derive(Reflect, Debug, PartialEq)] + struct MyStruct { + primitive_value: i8, + option_value: Option, + tuple_value: (f32, usize), + list_value: Vec, + array_value: [i32; 5], + map_value: HashMap, + struct_value: SomeStruct, + tuple_struct_value: SomeTupleStruct, + custom_serialize: CustomSerialize, + } + + #[derive(Reflect, Debug, PartialEq, Serialize)] + struct SomeStruct { + foo: i64, + } + + #[derive(Reflect, Debug, PartialEq)] + struct SomeTupleStruct(String); + + /// Implements a custom serialize using #[reflect(Serialize)]. + /// + /// For testing purposes, this is just the auto-generated one from deriving. + #[derive(Reflect, Debug, PartialEq, Serialize)] + #[reflect(Serialize)] + struct CustomSerialize { + value: usize, + #[serde(rename = "renamed")] + inner_struct: SomeStruct, + } fn get_registry() -> TypeRegistry { let mut registry = TypeRegistry::default(); - registry.register::(); - registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); registry.register::(); - registry.register::<(f32, f32)>(); + registry.register::>(); + registry.register_type_data::, ReflectSerialize>(); registry } + #[test] + fn should_serialize() { + let mut map = HashMap::new(); + map.insert(64, 32); + + let input = MyStruct { + primitive_value: 123, + option_value: Some(String::from("Hello world!")), + tuple_value: (3.14, 1337), + list_value: vec![-2, -1, 0, 1, 2], + array_value: [-2, -1, 0, 1, 2], + map_value: map, + struct_value: SomeStruct { foo: 999999999 }, + tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")), + custom_serialize: CustomSerialize { + value: 100, + inner_struct: SomeStruct { foo: 101 }, + }, + }; + + let registry = get_registry(); + let serializer = ReflectSerializer::new(&input, ®istry); + + let output = ron::ser::to_string_pretty(&serializer, Default::default()).unwrap(); + let expected = r#"{ + "type": "bevy_reflect::serde::ser::tests::MyStruct", + "value": { + "primitive_value": 123, + "option_value": Some("Hello world!"), + "tuple_value": (3.14, 1337), + "list_value": [ + -2, + -1, + 0, + 1, + 2, + ], + "array_value": (-2, -1, 0, 1, 2), + "map_value": { + 64: 32, + }, + "struct_value": { + "foo": 999999999, + }, + "tuple_struct_value": ("Tuple Struct"), + "custom_serialize": ( + value: 100, + renamed: ( + foo: 101, + ), + ), + }, +}"#; + assert_eq!(expected, output); + } + #[test] fn enum_should_serialize() { #[derive(Reflect)] @@ -522,8 +488,8 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "enum": { - "variant": "Unit", + "value": { + "Unit": (), }, }"#; assert_eq!(expected, output); @@ -534,14 +500,8 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "enum": { - "variant": "NewType", - "tuple": [ - { - "type": "usize", - "value": 123, - }, - ], + "value": { + "NewType": (123), }, }"#; assert_eq!(expected, output); @@ -552,18 +512,8 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "enum": { - "variant": "Tuple", - "tuple": [ - { - "type": "f32", - "value": 1.23, - }, - { - "type": "f32", - "value": 3.21, - }, - ], + "value": { + "Tuple": (1.23, 3.21), }, }"#; assert_eq!(expected, output); @@ -576,16 +526,12 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "enum": { - "variant": "Struct", - "struct": { - "value": { - "type": "alloc::string::String", - "value": "I <3 Enums", - }, + "value": { + "Struct": { + "value": "I <3 Enums", }, }, }"#; - assert_eq!(expected, output.replace('\r', "")); + assert_eq!(expected, output); } } From a6d24cd858bfa585a3dd9c2300ca2657f1db4970 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Fri, 22 Apr 2022 12:45:42 -0700 Subject: [PATCH 02/24] Cleanup comment --- crates/bevy_reflect/src/serde/ser.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 74e0190bee665..23ea2f65d25fe 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -388,9 +388,9 @@ mod tests { #[derive(Reflect, Debug, PartialEq)] struct SomeTupleStruct(String); - /// Implements a custom serialize using #[reflect(Serialize)]. + /// Implements a custom serialize using `#[reflect(Serialize)]`. /// - /// For testing purposes, this is just the auto-generated one from deriving. + /// For testing purposes, this just uses the generated one from deriving Serialize. #[derive(Reflect, Debug, PartialEq, Serialize)] #[reflect(Serialize)] struct CustomSerialize { From a73d70e135832f944b16ddaa7f8a99c7805f322b Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Fri, 22 Apr 2022 13:38:18 -0700 Subject: [PATCH 03/24] Updated example scene file --- assets/scenes/load_scene_example.scn.ron | 49 +++++++----------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/assets/scenes/load_scene_example.scn.ron b/assets/scenes/load_scene_example.scn.ron index 338084e9671b6..c40f968f48874 100644 --- a/assets/scenes/load_scene_example.scn.ron +++ b/assets/scenes/load_scene_example.scn.ron @@ -1,44 +1,27 @@ [ + ( entity: 0, components: [ { "type": "bevy_transform::components::transform::Transform", - "struct": { - "translation": { - "type": "glam::f32::vec3::Vec3", - "value": (0.0, 0.0, 0.0), - }, - "rotation": { - "type": "glam::f32::sse2::quat::Quat", - "value": (0.0, 0.0, 0.0, 1.0), - }, - "scale": { - "type": "glam::f32::vec3::Vec3", - "value": (1.0, 1.0, 1.0), - }, + "value": { + "translation": (0.0, 0.0, 0.0), + "rotation": (0.0, 0.0, 0.0, 1.0), + "scale": (1.0, 1.0, 1.0), }, }, { "type": "scene::ComponentB", - "struct": { - "value": { - "type": "alloc::string::String", - "value": "hello", - }, + "value": { + "value": "hello", }, }, { "type": "scene::ComponentA", - "struct": { - "x": { - "type": "f32", - "value": 1.0, - }, - "y": { - "type": "f32", - "value": 2.0, - }, + "value": { + "x": 1.0, + "y": 2.0, }, }, ], @@ -48,15 +31,9 @@ components: [ { "type": "scene::ComponentA", - "struct": { - "x": { - "type": "f32", - "value": 3.0, - }, - "y": { - "type": "f32", - "value": 4.0, - }, + "value": { + "x": 3.0, + "y": 4.0, }, }, ], From 58bd1e5bf2c69215cff9d3fb11e1a3771a6c38eb Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 1 Jun 2022 00:11:49 -0700 Subject: [PATCH 04/24] Fix clippy --- crates/bevy_reflect/src/serde/de.rs | 17 ++++++++--------- crates/bevy_reflect/src/serde/ser.rs | 5 +++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index ae276feae4426..d92ef672a80c6 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -147,7 +147,7 @@ impl<'a, 'de> Visitor<'de> for ReflectDeserializerVisitor<'a> { match map.next_key::<&str>()? { Some(type_fields::VALUE) => { - let registration = self.registry.get_with_name(&type_name).ok_or_else(|| { + let registration = self.registry.get_with_name(type_name).ok_or_else(|| { de::Error::custom(format_args!("No registration found for {}", type_name)) })?; let type_info = registration.type_info(); @@ -159,12 +159,10 @@ impl<'a, 'de> Visitor<'de> for ReflectDeserializerVisitor<'a> { } Some(type_fields::TYPE) => Err(de::Error::duplicate_field(type_fields::TYPE)), Some(field) => Err(de::Error::unknown_field(field, &[type_fields::VALUE])), - None => { - return Err(de::Error::invalid_length( - 0, - &"two entries: `type` and `value`", - )); - } + None => Err(de::Error::invalid_length( + 0, + &"two entries: `type` and `value`", + )), } } } @@ -720,6 +718,7 @@ mod tests { use bevy_utils::HashMap; use serde::de::DeserializeSeed; use serde::Deserialize; + use std::f32::consts::PI; #[derive(Reflect, FromReflect, Debug, PartialEq)] struct MyStruct { @@ -858,7 +857,7 @@ mod tests { let expected = MyStruct { primitive_value: 123, option_value: Some(String::from("Hello world!")), - tuple_value: (3.14, 1337), + tuple_value: (PI, 1337), list_value: vec![-2, -1, 0, 1, 2], array_value: [-2, -1, 0, 1, 2], map_value: map, @@ -876,7 +875,7 @@ mod tests { "primitive_value": 123, "option_value": Some("Hello world!"), "tuple_value": ( - 3.14, + 3.1415927, 1337, ), "list_value": [ diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 23ea2f65d25fe..d108d39b29cd4 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -366,6 +366,7 @@ mod tests { use bevy_utils::HashMap; use ron::ser::PrettyConfig; use serde::Serialize; + use std::f32::consts::PI; #[derive(Reflect, Debug, PartialEq)] struct MyStruct { @@ -419,7 +420,7 @@ mod tests { let input = MyStruct { primitive_value: 123, option_value: Some(String::from("Hello world!")), - tuple_value: (3.14, 1337), + tuple_value: (PI, 1337), list_value: vec![-2, -1, 0, 1, 2], array_value: [-2, -1, 0, 1, 2], map_value: map, @@ -440,7 +441,7 @@ mod tests { "value": { "primitive_value": 123, "option_value": Some("Hello world!"), - "tuple_value": (3.14, 1337), + "tuple_value": (3.1415927, 1337), "list_value": [ -2, -1, From 02c28f2a15bd3d2399c0051519e6d140ddc1fd50 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 1 Jun 2022 00:30:04 -0700 Subject: [PATCH 05/24] Fix glam tests --- crates/bevy_reflect/src/impls/glam.rs | 26 ++++++++++++------------- crates/bevy_reflect/src/lib.rs | 28 +++++++++++++++++++++------ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/crates/bevy_reflect/src/impls/glam.rs b/crates/bevy_reflect/src/impls/glam.rs index c84fcbffaaf27..9dfcc8293ce23 100644 --- a/crates/bevy_reflect/src/impls/glam.rs +++ b/crates/bevy_reflect/src/impls/glam.rs @@ -6,14 +6,14 @@ use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_struct, impl_ref use glam::*; impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct IVec2 { x: i32, y: i32, } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct IVec3 { x: i32, y: i32, @@ -21,7 +21,7 @@ impl_reflect_struct!( } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct IVec4 { x: i32, y: i32, @@ -31,14 +31,14 @@ impl_reflect_struct!( ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct UVec2 { x: u32, y: u32, } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct UVec3 { x: u32, y: u32, @@ -46,7 +46,7 @@ impl_reflect_struct!( } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct UVec4 { x: u32, y: u32, @@ -56,14 +56,14 @@ impl_reflect_struct!( ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct Vec2 { x: f32, y: f32, } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct Vec3 { x: f32, y: f32, @@ -71,7 +71,7 @@ impl_reflect_struct!( } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct Vec3A { x: f32, y: f32, @@ -79,7 +79,7 @@ impl_reflect_struct!( } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct Vec4 { x: f32, y: f32, @@ -114,14 +114,14 @@ impl_reflect_struct!( ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct DVec2 { x: f64, y: f64, } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct DVec3 { x: f64, y: f64, @@ -129,7 +129,7 @@ impl_reflect_struct!( } ); impl_reflect_struct!( - #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[reflect(Debug, PartialEq, Default)] struct DVec4 { x: f64, y: f64, diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index dcba7d8323a5a..4419a16978747 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -957,17 +957,33 @@ bevy_reflect::tests::should_reflect_debug::Test { let ser = ReflectSerializer::new(&v, ®istry); - let result = ron::to_string(&ser).expect("Failed to serialize to string"); + let output = to_string_pretty(&ser, Default::default()).unwrap(); + let expected = r#" +{ + "type": "glam::f32::vec3::Vec3", + "value": { + "x": 12.0, + "y": 3.0, + "z": -6.9, + }, +} +"#; - assert_eq!( - result, - r#"{"type":"glam::f32::vec3::Vec3","struct":{"x":{"type":"f32","value":12.0},"y":{"type":"f32","value":3.0},"z":{"type":"f32","value":-6.9}}}"# - ); + assert_eq!(expected, format!("\n{}\n", output)); } #[test] fn vec3_deserialization() { - let data = r#"{"type":"glam::vec3::Vec3","struct":{"x":{"type":"f32","value":12},"y":{"type":"f32","value":3},"z":{"type":"f32","value":-6.9}}}"#; + let data = r#" +{ + "type": "glam::f32::vec3::Vec3", + "value": { + "x": 12, + "y": 3, + "z": -6.9, + }, +} +"#; let mut registry = TypeRegistry::default(); registry.add_registration(Vec3::get_type_registration()); From f68e970174a538631c82f4de30d5e0864bd48e48 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 1 Jun 2022 00:41:16 -0700 Subject: [PATCH 06/24] Fixed tests --- crates/bevy_reflect/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 4419a16978747..f574ff2055389 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -93,7 +93,7 @@ pub mod __macro_exports { mod tests { #[cfg(feature = "glam")] use ::glam::{vec3, Vec3}; - use ::serde::de::DeserializeSeed; + use ::serde::{de::DeserializeSeed, Deserialize, Serialize}; use bevy_utils::HashMap; use ron::{ ser::{to_string_pretty, PrettyConfig}, @@ -451,7 +451,8 @@ mod tests { h: [u32; 2], } - #[derive(Reflect)] + #[derive(Reflect, Serialize, Deserialize)] + #[reflect(Serialize, Deserialize)] struct Bar { x: u32, } From dbee98a973da23e5e4a6bde370ab973caaf137a3 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 11 Jun 2022 16:54:07 -0700 Subject: [PATCH 07/24] Remove TODO comment --- crates/bevy_reflect/src/serde/de.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index d92ef672a80c6..3cf53956f8031 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -853,7 +853,6 @@ mod tests { let mut map = HashMap::new(); map.insert(64, 32); - // TODO: Add test for standard tuples (requires https://github.com/bevyengine/bevy/pull/4226) let expected = MyStruct { primitive_value: 123, option_value: Some(String::from("Hello world!")), From 3dcc3f67948b7ccf2122250df1ac1366e1782fe7 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 11 Jun 2022 16:54:30 -0700 Subject: [PATCH 08/24] Fix test for CI --- crates/bevy_reflect/src/serde/ser.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index d108d39b29cd4..e10854d7403ed 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -435,7 +435,9 @@ mod tests { let registry = get_registry(); let serializer = ReflectSerializer::new(&input, ®istry); - let output = ron::ser::to_string_pretty(&serializer, Default::default()).unwrap(); + let config = PrettyConfig::default().new_line(String::from("\n")); + + let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ "type": "bevy_reflect::serde::ser::tests::MyStruct", "value": { From 3acdf85fb05831e1bd616bcfb174b0801ca9d3c4 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 11 Jun 2022 17:20:44 -0700 Subject: [PATCH 09/24] Fix CI test for glam serialization --- crates/bevy_reflect/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index f574ff2055389..8fb5af97f6182 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -958,7 +958,8 @@ bevy_reflect::tests::should_reflect_debug::Test { let ser = ReflectSerializer::new(&v, ®istry); - let output = to_string_pretty(&ser, Default::default()).unwrap(); + let config = PrettyConfig::default().new_line(String::from("\n")); + let output = to_string_pretty(&ser, config).unwrap(); let expected = r#" { "type": "glam::f32::vec3::Vec3", From 0bacaf320c1971494ec8f115d2aabc4ce2f230d0 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 26 Jun 2022 19:24:38 -0700 Subject: [PATCH 10/24] Replace deserialize_any with deserialize_map --- crates/bevy_reflect/src/serde/de.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 3cf53956f8031..99cdd2c00ee7a 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -107,7 +107,7 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { where D: serde::Deserializer<'de>, { - deserializer.deserialize_any(ReflectDeserializerVisitor { + deserializer.deserialize_map(ReflectDeserializerVisitor { registry: self.registry, }) } From 0a20f4fb9934088d693c735ae62a922a4f68048c Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 26 Jun 2022 19:25:54 -0700 Subject: [PATCH 11/24] Remove unnecessary paths --- crates/bevy_reflect/src/serde/de.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 99cdd2c00ee7a..93f2aae35f9e9 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -293,7 +293,7 @@ struct StructVisitor<'a> { impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { type Value = DynamicStruct; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("reflected struct value") } @@ -313,7 +313,7 @@ struct TupleStructVisitor<'a> { impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { type Value = DynamicTupleStruct; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("reflected tuple struct value") } @@ -365,7 +365,7 @@ struct ListVisitor<'a> { impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { type Value = DynamicList; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("reflected list value") } @@ -397,7 +397,7 @@ struct ArrayVisitor<'a> { impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { type Value = DynamicArray; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("reflected array value") } @@ -437,7 +437,7 @@ struct MapVisitor<'a> { impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { type Value = DynamicMap; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("reflected map value") } @@ -479,7 +479,7 @@ struct TupleVisitor<'a> { impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { type Value = DynamicTuple; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("reflected tuple value") } From b1692437a365aa9704aee10bd78abb2c337897d9 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 26 Jun 2022 19:44:59 -0700 Subject: [PATCH 12/24] Fix PrettyConfig for tests --- crates/bevy_reflect/src/lib.rs | 17 +++++++++-------- crates/bevy_reflect/src/serde/ser.rs | 5 ++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 8fb5af97f6182..d034a23ea8c81 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -958,7 +958,10 @@ bevy_reflect::tests::should_reflect_debug::Test { let ser = ReflectSerializer::new(&v, ®istry); - let config = PrettyConfig::default().new_line(String::from("\n")); + let config = PrettyConfig::default() + .new_line(String::from("\n")) + .decimal_floats(true) + .indentor(String::from(" ")); let output = to_string_pretty(&ser, config).unwrap(); let expected = r#" { @@ -968,10 +971,9 @@ bevy_reflect::tests::should_reflect_debug::Test { "y": 3.0, "z": -6.9, }, -} -"#; +}"#; - assert_eq!(expected, format!("\n{}\n", output)); + assert_eq!(expected, format!("\n{}", output)); } #[test] @@ -980,12 +982,11 @@ bevy_reflect::tests::should_reflect_debug::Test { { "type": "glam::f32::vec3::Vec3", "value": { - "x": 12, - "y": 3, + "x": 12.0, + "y": 3.0, "z": -6.9, }, -} -"#; +}"#; let mut registry = TypeRegistry::default(); registry.add_registration(Vec3::get_type_registration()); diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index e10854d7403ed..a82c1606548b2 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -435,7 +435,10 @@ mod tests { let registry = get_registry(); let serializer = ReflectSerializer::new(&input, ®istry); - let config = PrettyConfig::default().new_line(String::from("\n")); + let config = PrettyConfig::default() + .new_line(String::from("\n")) + .decimal_floats(true) + .indentor(String::from(" ")); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ From d323c0d6d029ba731cc4be9df4bdb11ec0868abd Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 22:43:31 -0700 Subject: [PATCH 13/24] Rename ReflectDeserializer -> UntypedReflectDeserializer --- crates/bevy_reflect/src/lib.rs | 6 ++-- crates/bevy_reflect/src/serde/de.rs | 56 +++++++++++++++++++---------- crates/bevy_scene/src/serde.rs | 4 +-- examples/reflection/reflection.rs | 4 +-- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index d034a23ea8c81..89852745f6cd0 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -104,7 +104,7 @@ mod tests { use super::prelude::*; use super::*; use crate as bevy_reflect; - use crate::serde::{ReflectDeserializer, ReflectSerializer}; + use crate::serde::{UntypedReflectDeserializer, ReflectSerializer}; #[test] fn reflect_struct() { @@ -489,7 +489,7 @@ mod tests { let serialized = to_string_pretty(&serializer, PrettyConfig::default()).unwrap(); let mut deserializer = Deserializer::from_str(&serialized).unwrap(); - let reflect_deserializer = ReflectDeserializer::new(®istry); + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); let dynamic_struct = value.take::().unwrap(); @@ -992,7 +992,7 @@ bevy_reflect::tests::should_reflect_debug::Test { registry.add_registration(Vec3::get_type_registration()); registry.add_registration(f32::get_type_registration()); - let de = ReflectDeserializer::new(®istry); + let de = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(data).expect("Failed to acquire deserializer"); diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 93f2aae35f9e9..a642caa38210f 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -77,47 +77,56 @@ impl TupleLikeInfo for TupleVariantInfo { /// A general purpose deserializer for reflected types. /// -/// For non-value types, this will return the dynamic equivalent. For example, a +/// This will return a [`Box`] containing the deserialized data. +/// For non-value types, this `Box` will contain the dynamic equivalent. For example, a /// deserialized struct will return a [`DynamicStruct`] and a `Vec` will return a -/// [`DynamicList`]. +/// [`DynamicList`]. For value types, this `Box` will contain the actual value. +/// For example, an `f32` will contain the actual `f32` type. /// -/// The serialized data must take the form of a map containing the following entries: +/// This means that converting to any concrete instance will require the use of +/// [`FromReflect`], or downcasting for value types. +/// +/// Because the type isn't known ahead of time, the serialized data must take the form of +/// a map containing the following entries (in order): /// 1. `type`: The _full_ [type name] /// 2. `value`: The serialized value of the reflected type /// -/// > Note: The ordering is important here. `type` _must_ come before `value`. +/// If the type is already known and the [`TypeInfo`] for it can be retrieved, +/// [`TypedReflectDeserializer`] may be used instead to avoid requiring these entries. /// +/// [`Box`]: crate::Reflect /// [`DynamicStruct`]: crate::DynamicStruct /// [`DynamicList`]: crate::DynamicList +/// [`FromReflect`]: crate::FromReflect /// [type name]: std::any::type_name -pub struct ReflectDeserializer<'a> { +pub struct UntypedReflectDeserializer<'a> { registry: &'a TypeRegistry, } -impl<'a> ReflectDeserializer<'a> { +impl<'a> UntypedReflectDeserializer<'a> { pub fn new(registry: &'a TypeRegistry) -> Self { - ReflectDeserializer { registry } + Self { registry } } } -impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { +impl<'a, 'de> DeserializeSeed<'de> for UntypedReflectDeserializer<'a> { type Value = Box; fn deserialize(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { - deserializer.deserialize_map(ReflectDeserializerVisitor { + deserializer.deserialize_map(UntypedReflectDeserializerVisitor { registry: self.registry, }) } } -struct ReflectDeserializerVisitor<'a> { +struct UntypedReflectDeserializerVisitor<'a> { registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for ReflectDeserializerVisitor<'a> { +impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { type Value = Box; fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { @@ -169,13 +178,22 @@ impl<'a, 'de> Visitor<'de> for ReflectDeserializerVisitor<'a> { /// A deserializer for reflected types whose [`TypeInfo`] is known. /// -/// For non-value types, this will return the dynamic equivalent. For example, a +/// This will return a [`Box`] containing the deserialized data. +/// For non-value types, this `Box` will contain the dynamic equivalent. For example, a /// deserialized struct will return a [`DynamicStruct`] and a `Vec` will return a -/// [`DynamicList`]. +/// [`DynamicList`]. For value types, this `Box` will contain the actual value. +/// For example, an `f32` will contain the actual `f32` type. +/// +/// This means that converting to any concrete instance will require the use of +/// [`FromReflect`], or downcasting for value types. +/// +/// If the type is not known ahead of time, use [`UntypedReflectDeserializer`] instead. /// /// [`TypeInfo`]: crate::TypeInfo +/// [`Box`]: crate::Reflect /// [`DynamicStruct`]: crate::DynamicStruct /// [`DynamicList`]: crate::DynamicList +/// [`FromReflect`]: crate::FromReflect pub struct TypedReflectDeserializer<'a> { type_info: &'a TypeInfo, registry: &'a TypeRegistry, @@ -713,7 +731,7 @@ fn get_type_info<'a, E: de::Error>( #[cfg(test)] mod tests { use crate as bevy_reflect; - use crate::serde::ReflectDeserializer; + use crate::serde::UntypedReflectDeserializer; use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry}; use bevy_utils::HashMap; use serde::de::DeserializeSeed; @@ -794,7 +812,7 @@ mod tests { "Unit": (), }, }"#; - let reflect_deserializer = ReflectDeserializer::new(®istry); + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -808,7 +826,7 @@ mod tests { "NewType": (123), }, }"#; - let reflect_deserializer = ReflectDeserializer::new(®istry); + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -822,7 +840,7 @@ mod tests { "Tuple": (1.23, 3.21), }, }"#; - let reflect_deserializer = ReflectDeserializer::new(®istry); + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -838,7 +856,7 @@ mod tests { }, }, }"#; - let reflect_deserializer = ReflectDeserializer::new(®istry); + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); @@ -908,7 +926,7 @@ mod tests { }"#; let registry = get_registry(); - let reflect_deserializer = ReflectDeserializer::new(®istry); + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap(); let dynamic_output = reflect_deserializer .deserialize(&mut ron_deserializer) diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index e55a5fd4b592b..6ca5f1e924cb9 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -1,7 +1,7 @@ use crate::{DynamicEntity, DynamicScene}; use anyhow::Result; use bevy_reflect::{ - serde::{ReflectDeserializer, ReflectSerializer}, + serde::{UntypedReflectDeserializer, ReflectSerializer}, Reflect, TypeRegistry, TypeRegistryArc, }; use serde::{ @@ -242,7 +242,7 @@ impl<'a, 'de> Visitor<'de> for ComponentSeqVisitor<'a> { A: SeqAccess<'de>, { let mut dynamic_properties = Vec::new(); - while let Some(entity) = seq.next_element_seed(ReflectDeserializer::new(self.registry))? { + while let Some(entity) = seq.next_element_seed(UntypedReflectDeserializer::new(self.registry))? { dynamic_properties.push(entity); } diff --git a/examples/reflection/reflection.rs b/examples/reflection/reflection.rs index ca93c76b7f71d..447db38a3e743 100644 --- a/examples/reflection/reflection.rs +++ b/examples/reflection/reflection.rs @@ -7,7 +7,7 @@ use bevy::{ prelude::*, reflect::{ - serde::{ReflectDeserializer, ReflectSerializer}, + serde::{ReflectSerializer, UntypedReflectDeserializer}, DynamicStruct, }, }; @@ -81,7 +81,7 @@ fn setup(type_registry: Res) { info!("{}\n", ron_string); // Dynamic properties can be deserialized - let reflect_deserializer = ReflectDeserializer::new(&type_registry); + let reflect_deserializer = UntypedReflectDeserializer::new(&type_registry); let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap(); let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); From c74977336d1de5167d65420a59291e0748abc008 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:01:08 -0700 Subject: [PATCH 14/24] Add constructor to TypedReflectDeserializer Also added test --- crates/bevy_reflect/src/serde/de.rs | 47 ++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index a642caa38210f..80b8b18369163 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -199,6 +199,15 @@ pub struct TypedReflectDeserializer<'a> { registry: &'a TypeRegistry, } +impl<'a> TypedReflectDeserializer<'a> { + pub fn new(type_info: &'a TypeInfo, registry: &'a TypeRegistry) -> Self { + Self { + type_info, + registry, + } + } +} + impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { type Value = Box; @@ -730,13 +739,16 @@ fn get_type_info<'a, E: de::Error>( #[cfg(test)] mod tests { - use crate as bevy_reflect; - use crate::serde::UntypedReflectDeserializer; - use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry}; - use bevy_utils::HashMap; + use std::f32::consts::PI; + use serde::de::DeserializeSeed; use serde::Deserialize; - use std::f32::consts::PI; + + use bevy_utils::HashMap; + + use crate as bevy_reflect; + use crate::serde::{TypedReflectDeserializer, UntypedReflectDeserializer}; + use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry, Typed}; #[derive(Reflect, FromReflect, Debug, PartialEq)] struct MyStruct { @@ -935,4 +947,29 @@ mod tests { let output = ::from_reflect(dynamic_output.as_ref()).unwrap(); assert_eq!(expected, output); } + + #[test] + fn should_deserialized_typed() { + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct Foo { + bar: i32, + } + + let expected = Foo { bar: 123 }; + + let input = r#"{ + "bar": 123 + }"#; + + let mut registry = get_registry(); + registry.register::(); + let reflect_deserializer = TypedReflectDeserializer::new(Foo::type_info(), ®istry); + let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let dynamic_output = reflect_deserializer + .deserialize(&mut ron_deserializer) + .unwrap(); + + let output = ::from_reflect(dynamic_output.as_ref()).unwrap(); + assert_eq!(expected, output); + } } From 631a9ae052681dd64dc9b1fa6bc21ee9326602e1 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:02:14 -0700 Subject: [PATCH 15/24] Added test for simple value types --- crates/bevy_reflect/src/serde/de.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 80b8b18369163..783195e28a005 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -948,6 +948,23 @@ mod tests { assert_eq!(expected, output); } + #[test] + fn should_deserialize_value() { + let input = r#"{ + "type": "f32", + "value": 1.23, + }"#; + + let registry = get_registry(); + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); + let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let dynamic_output = reflect_deserializer + .deserialize(&mut ron_deserializer) + .unwrap(); + let output = dynamic_output.take::().expect("underlying type should be f32"); + assert_eq!(1.23, output); + } + #[test] fn should_deserialized_typed() { #[derive(Reflect, FromReflect, Debug, PartialEq)] From 85b357e43a6110a5aa9f4932fe779d6562dbe4bf Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:03:56 -0700 Subject: [PATCH 16/24] Reorganize Visitor impls --- crates/bevy_reflect/src/serde/de.rs | 84 +++++++++++++++-------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 783195e28a005..6f9da313a726b 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -384,35 +384,23 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { } } -struct ListVisitor<'a> { - list_info: &'a ListInfo, +struct TupleVisitor<'a> { + tuple_info: &'a TupleInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { - type Value = DynamicList; +impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { + type Value = DynamicTuple; fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { - formatter.write_str("reflected list value") + formatter.write_str("reflected tuple value") } fn visit_seq(self, mut seq: V) -> Result - where - V: SeqAccess<'de>, + where + V: SeqAccess<'de>, { - let mut list = DynamicList::default(); - let type_info = get_type_info( - self.list_info.item_type_id(), - self.list_info.item_type_name(), - self.registry, - )?; - while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { - type_info, - registry: self.registry, - })? { - list.push_box(value); - } - Ok(list) + visit_tuple(&mut seq, self.tuple_info, self.registry) } } @@ -456,6 +444,38 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { } } +struct ListVisitor<'a> { + list_info: &'a ListInfo, + registry: &'a TypeRegistry, +} + +impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { + type Value = DynamicList; + + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + formatter.write_str("reflected list value") + } + + fn visit_seq(self, mut seq: V) -> Result + where + V: SeqAccess<'de>, + { + let mut list = DynamicList::default(); + let type_info = get_type_info( + self.list_info.item_type_id(), + self.list_info.item_type_name(), + self.registry, + )?; + while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { + type_info, + registry: self.registry, + })? { + list.push_box(value); + } + Ok(list) + } +} + struct MapVisitor<'a> { map_info: &'a MapInfo, registry: &'a TypeRegistry, @@ -498,26 +518,6 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { } } -struct TupleVisitor<'a> { - tuple_info: &'a TupleInfo, - registry: &'a TypeRegistry, -} - -impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { - type Value = DynamicTuple; - - fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { - formatter.write_str("reflected tuple value") - } - - fn visit_seq(self, mut seq: V) -> Result - where - V: SeqAccess<'de>, - { - visit_tuple(&mut seq, self.tuple_info, self.registry) - } -} - struct EnumVisitor<'a> { enum_info: &'a EnumInfo, registry: &'a TypeRegistry, @@ -961,7 +961,9 @@ mod tests { let dynamic_output = reflect_deserializer .deserialize(&mut ron_deserializer) .unwrap(); - let output = dynamic_output.take::().expect("underlying type should be f32"); + let output = dynamic_output + .take::() + .expect("underlying type should be f32"); assert_eq!(1.23, output); } From d23699d77e45f2cbc5c7c3703c3d251b012c5208 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:05:11 -0700 Subject: [PATCH 17/24] Formatting --- crates/bevy_reflect/src/lib.rs | 2 +- crates/bevy_scene/src/serde.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 89852745f6cd0..6e7a7bbcbc085 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -104,7 +104,7 @@ mod tests { use super::prelude::*; use super::*; use crate as bevy_reflect; - use crate::serde::{UntypedReflectDeserializer, ReflectSerializer}; + use crate::serde::{ReflectSerializer, UntypedReflectDeserializer}; #[test] fn reflect_struct() { diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index 6ca5f1e924cb9..8a3e5383af170 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -1,7 +1,7 @@ use crate::{DynamicEntity, DynamicScene}; use anyhow::Result; use bevy_reflect::{ - serde::{UntypedReflectDeserializer, ReflectSerializer}, + serde::{ReflectSerializer, UntypedReflectDeserializer}, Reflect, TypeRegistry, TypeRegistryArc, }; use serde::{ @@ -242,7 +242,9 @@ impl<'a, 'de> Visitor<'de> for ComponentSeqVisitor<'a> { A: SeqAccess<'de>, { let mut dynamic_properties = Vec::new(); - while let Some(entity) = seq.next_element_seed(UntypedReflectDeserializer::new(self.registry))? { + while let Some(entity) = + seq.next_element_seed(UntypedReflectDeserializer::new(self.registry))? + { dynamic_properties.push(entity); } From 811d3c9f4d6c082c6b64eba7364f0e9cf110c419 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 29 Jun 2022 08:25:49 -0700 Subject: [PATCH 18/24] Revert "Replace deserialize_any with deserialize_map" This reverts commit 4122568f1cabc1d76a81090a14a383f8dafe457a. --- crates/bevy_reflect/src/serde/de.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 6f9da313a726b..790b23e12e9a2 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -116,7 +116,7 @@ impl<'a, 'de> DeserializeSeed<'de> for UntypedReflectDeserializer<'a> { where D: serde::Deserializer<'de>, { - deserializer.deserialize_map(UntypedReflectDeserializerVisitor { + deserializer.deserialize_any(UntypedReflectDeserializerVisitor { registry: self.registry, }) } From 77bcefadd5053a57b98b62ad8b07a12b650e8700 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 7 Aug 2022 17:08:37 -0700 Subject: [PATCH 19/24] Remove "type" and "value" keys Replaced with "type" key with the actual type name --- crates/bevy_reflect/src/lib.rs | 6 +-- crates/bevy_reflect/src/serde/de.rs | 77 +++++++++------------------- crates/bevy_reflect/src/serde/mod.rs | 5 -- crates/bevy_reflect/src/serde/ser.rs | 24 ++++----- 4 files changed, 35 insertions(+), 77 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 6e7a7bbcbc085..66c486e5e8ed3 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -965,8 +965,7 @@ bevy_reflect::tests::should_reflect_debug::Test { let output = to_string_pretty(&ser, config).unwrap(); let expected = r#" { - "type": "glam::f32::vec3::Vec3", - "value": { + "glam::f32::vec3::Vec3": { "x": 12.0, "y": 3.0, "z": -6.9, @@ -980,8 +979,7 @@ bevy_reflect::tests::should_reflect_debug::Test { fn vec3_deserialization() { let data = r#" { - "type": "glam::f32::vec3::Vec3", - "value": { + "glam::f32::vec3::Vec3": { "x": 12.0, "y": 3.0, "z": -6.9, diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 790b23e12e9a2..d0592f58382b2 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,8 +1,8 @@ use crate::{ - serde::type_fields, ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, - DynamicStruct, DynamicTuple, DynamicTupleStruct, EnumInfo, ListInfo, Map, MapInfo, NamedField, - Reflect, ReflectDeserialize, StructInfo, StructVariantInfo, Tuple, TupleInfo, TupleStruct, - TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistry, UnnamedField, VariantInfo, + ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, + DynamicTupleStruct, EnumInfo, ListInfo, Map, MapInfo, NamedField, Reflect, ReflectDeserialize, + StructInfo, StructVariantInfo, Tuple, TupleInfo, TupleStruct, TupleStructInfo, + TupleVariantInfo, TypeInfo, TypeRegistry, UnnamedField, VariantInfo, }; use erased_serde::Deserializer; use serde::de::{self, DeserializeSeed, Error, MapAccess, SeqAccess, Visitor}; @@ -137,42 +137,19 @@ impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { where A: MapAccess<'de>, { - let type_name = match map.next_key::<&str>()? { - Some(type_fields::TYPE) => map.next_value::<&str>()?, - Some(type_fields::VALUE) => { - // `type` must come before `value`. - return Err(de::Error::missing_field(type_fields::TYPE)); - } - Some(field) => { - return Err(de::Error::unknown_field(field, &[type_fields::TYPE])); - } - None => { - return Err(de::Error::invalid_length( - 0, - &"two entries: `type` and `value`", - )); - } - }; + let type_name = map + .next_key::<&str>()? + .ok_or_else(|| Error::invalid_length(0, &"at least one entry"))?; - match map.next_key::<&str>()? { - Some(type_fields::VALUE) => { - let registration = self.registry.get_with_name(type_name).ok_or_else(|| { - de::Error::custom(format_args!("No registration found for {}", type_name)) - })?; - let type_info = registration.type_info(); - let value = map.next_value_seed(TypedReflectDeserializer { - type_info, - registry: self.registry, - })?; - Ok(value) - } - Some(type_fields::TYPE) => Err(de::Error::duplicate_field(type_fields::TYPE)), - Some(field) => Err(de::Error::unknown_field(field, &[type_fields::VALUE])), - None => Err(de::Error::invalid_length( - 0, - &"two entries: `type` and `value`", - )), - } + let registration = self.registry.get_with_name(type_name).ok_or_else(|| { + Error::custom(format_args!("No registration found for {}", type_name)) + })?; + let type_info = registration.type_info(); + let value = map.next_value_seed(TypedReflectDeserializer { + type_info, + registry: self.registry, + })?; + Ok(value) } } @@ -397,8 +374,8 @@ impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { } fn visit_seq(self, mut seq: V) -> Result - where - V: SeqAccess<'de>, + where + V: SeqAccess<'de>, { visit_tuple(&mut seq, self.tuple_info, self.registry) } @@ -819,8 +796,7 @@ mod tests { // === Unit Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "value": { + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { "Unit": (), }, }"#; @@ -833,8 +809,7 @@ mod tests { // === NewType Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "value": { + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { "NewType": (123), }, }"#; @@ -847,8 +822,7 @@ mod tests { // === Tuple Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "value": { + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { "Tuple": (1.23, 3.21), }, }"#; @@ -861,8 +835,7 @@ mod tests { // === Struct Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "value": { + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { "Struct": { "value": "I <3 Enums", }, @@ -899,8 +872,7 @@ mod tests { }; let input = r#"{ - "type": "bevy_reflect::serde::de::tests::MyStruct", - "value": { + "bevy_reflect::serde::de::tests::MyStruct": { "primitive_value": 123, "option_value": Some("Hello world!"), "tuple_value": ( @@ -951,8 +923,7 @@ mod tests { #[test] fn should_deserialize_value() { let input = r#"{ - "type": "f32", - "value": 1.23, + "f32": 1.23, }"#; let registry = get_registry(); diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index 882ddbe8f0995..21612b6c05553 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -3,8 +3,3 @@ mod ser; pub use de::*; pub use ser::*; - -pub(crate) mod type_fields { - pub const TYPE: &str = "type"; - pub const VALUE: &str = "value"; -} diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index a82c1606548b2..1a9a64e1d2f2e 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -1,6 +1,6 @@ use crate::{ - serde::type_fields, Array, Enum, List, Map, Reflect, ReflectRef, ReflectSerialize, Struct, - Tuple, TupleStruct, TypeRegistry, VariantType, + Array, Enum, List, Map, Reflect, ReflectRef, ReflectSerialize, Struct, Tuple, TupleStruct, + TypeRegistry, VariantType, }; use serde::ser::SerializeTuple; use serde::{ @@ -61,10 +61,9 @@ impl<'a> Serialize for ReflectSerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_map(Some(2))?; - state.serialize_entry(type_fields::TYPE, self.value.type_name())?; + let mut state = serializer.serialize_map(Some(1))?; state.serialize_entry( - type_fields::VALUE, + self.value.type_name(), &TypedReflectSerializer::new(self.value, self.registry), )?; state.end() @@ -442,8 +441,7 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ - "type": "bevy_reflect::serde::ser::tests::MyStruct", - "value": { + "bevy_reflect::serde::ser::tests::MyStruct": { "primitive_value": 123, "option_value": Some("Hello world!"), "tuple_value": (3.1415927, 1337), @@ -493,8 +491,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "value": { + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { "Unit": (), }, }"#; @@ -505,8 +502,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "value": { + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { "NewType": (123), }, }"#; @@ -517,8 +513,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "value": { + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { "Tuple": (1.23, 3.21), }, }"#; @@ -531,8 +526,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ - "type": "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum", - "value": { + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { "Struct": { "value": "I <3 Enums", }, From d62b699ebe43511be97e26b5ccad1ba8e6a79121 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 7 Aug 2022 17:26:22 -0700 Subject: [PATCH 20/24] Add nested enums to tests --- crates/bevy_reflect/src/serde/de.rs | 173 ++++++++++++++++----------- crates/bevy_reflect/src/serde/ser.rs | 32 +++++ 2 files changed, 135 insertions(+), 70 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index d0592f58382b2..48e40b299c847 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -737,6 +737,10 @@ mod tests { map_value: HashMap, struct_value: SomeStruct, tuple_struct_value: SomeTupleStruct, + unit_enum: SomeEnum, + newtype_enum: SomeEnum, + tuple_enum: SomeEnum, + struct_enum: SomeEnum, custom_deserialize: CustomDeserialize, } @@ -759,12 +763,21 @@ mod tests { inner_struct: SomeStruct, } + #[derive(Reflect, FromReflect, Debug, PartialEq)] + enum SomeEnum { + Unit, + NewType(usize), + Tuple(f32, f32), + Struct { foo: String }, + } + fn get_registry() -> TypeRegistry { let mut registry = TypeRegistry::default(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); + registry.register::(); registry.register::(); registry.register::(); registry.register::(); @@ -781,76 +794,6 @@ mod tests { registry } - #[test] - fn enum_should_deserialize() { - #[derive(Reflect)] - enum MyEnum { - Unit, - NewType(usize), - Tuple(f32, f32), - Struct { value: String }, - } - - let mut registry = get_registry(); - registry.register::(); - - // === Unit Variant === // - let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "Unit": (), - }, - }"#; - let reflect_deserializer = UntypedReflectDeserializer::new(®istry); - let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); - let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - - let expected = DynamicEnum::from(MyEnum::Unit); - assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); - - // === NewType Variant === // - let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "NewType": (123), - }, - }"#; - let reflect_deserializer = UntypedReflectDeserializer::new(®istry); - let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); - let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - - let expected = DynamicEnum::from(MyEnum::NewType(123)); - assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); - - // === Tuple Variant === // - let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "Tuple": (1.23, 3.21), - }, - }"#; - let reflect_deserializer = UntypedReflectDeserializer::new(®istry); - let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); - let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - - let expected = DynamicEnum::from(MyEnum::Tuple(1.23, 3.21)); - assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); - - // === Struct Variant === // - let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "Struct": { - "value": "I <3 Enums", - }, - }, - }"#; - let reflect_deserializer = UntypedReflectDeserializer::new(®istry); - let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); - let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - - let expected = DynamicEnum::from(MyEnum::Struct { - value: String::from("I <3 Enums"), - }); - assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); - } - #[test] fn should_deserialize() { let mut map = HashMap::new(); @@ -865,6 +808,12 @@ mod tests { map_value: map, struct_value: SomeStruct { foo: 999999999 }, tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")), + unit_enum: SomeEnum::Unit, + newtype_enum: SomeEnum::NewType(123), + tuple_enum: SomeEnum::Tuple(1.23, 3.21), + struct_enum: SomeEnum::Struct { + foo: String::from("Struct variant value"), + }, custom_deserialize: CustomDeserialize { value: 100, inner_struct: SomeStruct { foo: 101 }, @@ -900,6 +849,20 @@ mod tests { "foo": 999999999, }, "tuple_struct_value": ("Tuple Struct"), + "unit_enum": { + "Unit": (), + }, + "newtype_enum": { + "NewType": (123), + }, + "tuple_enum": { + "Tuple": (1.23, 3.21), + }, + "struct_enum": { + "Struct": { + "foo": "Struct variant value", + }, + }, "custom_deserialize": ( value: 100, renamed: ( @@ -962,4 +925,74 @@ mod tests { let output = ::from_reflect(dynamic_output.as_ref()).unwrap(); assert_eq!(expected, output); } + + #[test] + fn enum_should_deserialize() { + #[derive(Reflect)] + enum MyEnum { + Unit, + NewType(usize), + Tuple(f32, f32), + Struct { value: String }, + } + + let mut registry = get_registry(); + registry.register::(); + + // === Unit Variant === // + let input = r#"{ + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { + "Unit": (), + }, + }"#; + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); + let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); + + let expected = DynamicEnum::from(MyEnum::Unit); + assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); + + // === NewType Variant === // + let input = r#"{ + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { + "NewType": (123), + }, + }"#; + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); + let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); + + let expected = DynamicEnum::from(MyEnum::NewType(123)); + assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); + + // === Tuple Variant === // + let input = r#"{ + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { + "Tuple": (1.23, 3.21), + }, + }"#; + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); + let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); + + let expected = DynamicEnum::from(MyEnum::Tuple(1.23, 3.21)); + assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); + + // === Struct Variant === // + let input = r#"{ + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { + "Struct": { + "value": "I <3 Enums", + }, + }, + }"#; + let reflect_deserializer = UntypedReflectDeserializer::new(®istry); + let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); + + let expected = DynamicEnum::from(MyEnum::Struct { + value: String::from("I <3 Enums"), + }); + assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); + } } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 1a9a64e1d2f2e..1b7d1ae20b5c0 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -377,6 +377,10 @@ mod tests { map_value: HashMap, struct_value: SomeStruct, tuple_struct_value: SomeTupleStruct, + unit_enum: SomeEnum, + newtype_enum: SomeEnum, + tuple_enum: SomeEnum, + struct_enum: SomeEnum, custom_serialize: CustomSerialize, } @@ -388,6 +392,14 @@ mod tests { #[derive(Reflect, Debug, PartialEq)] struct SomeTupleStruct(String); + #[derive(Reflect, Debug, PartialEq)] + enum SomeEnum { + Unit, + NewType(usize), + Tuple(f32, f32), + Struct { foo: String }, + } + /// Implements a custom serialize using `#[reflect(Serialize)]`. /// /// For testing purposes, this just uses the generated one from deriving Serialize. @@ -425,6 +437,12 @@ mod tests { map_value: map, struct_value: SomeStruct { foo: 999999999 }, tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")), + unit_enum: SomeEnum::Unit, + newtype_enum: SomeEnum::NewType(123), + tuple_enum: SomeEnum::Tuple(1.23, 3.21), + struct_enum: SomeEnum::Struct { + foo: String::from("Struct variant value"), + }, custom_serialize: CustomSerialize { value: 100, inner_struct: SomeStruct { foo: 101 }, @@ -460,6 +478,20 @@ mod tests { "foo": 999999999, }, "tuple_struct_value": ("Tuple Struct"), + "unit_enum": { + "Unit": (), + }, + "newtype_enum": { + "NewType": (123), + }, + "tuple_enum": { + "Tuple": (1.23, 3.21), + }, + "struct_enum": { + "Struct": { + "foo": "Struct variant value", + }, + }, "custom_serialize": ( value: 100, renamed: ( From 4d4e9d0943866349e4b0a41ec9ade8d1581da317 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 10 Aug 2022 09:05:51 -0700 Subject: [PATCH 21/24] Fix scene example --- assets/scenes/load_scene_example.scn.ron | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/assets/scenes/load_scene_example.scn.ron b/assets/scenes/load_scene_example.scn.ron index c40f968f48874..8400e28f6e2aa 100644 --- a/assets/scenes/load_scene_example.scn.ron +++ b/assets/scenes/load_scene_example.scn.ron @@ -1,25 +1,29 @@ [ - ( entity: 0, components: [ { - "type": "bevy_transform::components::transform::Transform", - "value": { - "translation": (0.0, 0.0, 0.0), + "bevy_transform::components::transform::Transform": { + "translation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, "rotation": (0.0, 0.0, 0.0, 1.0), - "scale": (1.0, 1.0, 1.0), + "scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, }, }, { - "type": "scene::ComponentB", - "value": { + "scene::ComponentB": { "value": "hello", }, }, { - "type": "scene::ComponentA", - "value": { + "scene::ComponentA": { "x": 1.0, "y": 2.0, }, @@ -30,8 +34,7 @@ entity: 1, components: [ { - "type": "scene::ComponentA", - "value": { + "scene::ComponentA": { "x": 3.0, "y": 4.0, }, From 57d93e985ae9087fda943a5475a3ee4c44eecb20 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 22:24:26 -0700 Subject: [PATCH 22/24] Add more complex Option value to tests --- crates/bevy_reflect/src/serde/de.rs | 20 +++++++++++++++++--- crates/bevy_reflect/src/serde/ser.rs | 22 ++++++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 48e40b299c847..bb595347d740e 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -731,6 +731,7 @@ mod tests { struct MyStruct { primitive_value: i8, option_value: Option, + option_value_complex: Option, tuple_value: (f32, usize), list_value: Vec, array_value: [i32; 5], @@ -744,7 +745,7 @@ mod tests { custom_deserialize: CustomDeserialize, } - #[derive(Reflect, FromReflect, Debug, PartialEq, Deserialize)] + #[derive(Reflect, FromReflect, Debug, PartialEq)] struct SomeStruct { foo: i64, } @@ -752,6 +753,11 @@ mod tests { #[derive(Reflect, FromReflect, Debug, PartialEq)] struct SomeTupleStruct(String); + #[derive(Reflect, FromReflect, Debug, PartialEq, Deserialize)] + struct SomeDeserializableStruct { + foo: i64, + } + /// Implements a custom deserialize using #[reflect(Deserialize)]. /// /// For testing purposes, this is just the auto-generated one from deriving. @@ -760,7 +766,7 @@ mod tests { struct CustomDeserialize { value: usize, #[serde(rename = "renamed")] - inner_struct: SomeStruct, + inner_struct: SomeDeserializableStruct, } #[derive(Reflect, FromReflect, Debug, PartialEq)] @@ -777,6 +783,7 @@ mod tests { registry.register::(); registry.register::(); registry.register::(); + registry.register::(); registry.register::(); registry.register::(); registry.register::(); @@ -789,6 +796,7 @@ mod tests { registry.register::<[i32; 5]>(); registry.register::>(); registry.register::>(); + registry.register::>(); registry.register::>(); registry.register_type_data::, ReflectDeserialize>(); registry @@ -802,6 +810,7 @@ mod tests { let expected = MyStruct { primitive_value: 123, option_value: Some(String::from("Hello world!")), + option_value_complex: Some(SomeStruct { foo: 123 }), tuple_value: (PI, 1337), list_value: vec![-2, -1, 0, 1, 2], array_value: [-2, -1, 0, 1, 2], @@ -816,7 +825,7 @@ mod tests { }, custom_deserialize: CustomDeserialize { value: 100, - inner_struct: SomeStruct { foo: 101 }, + inner_struct: SomeDeserializableStruct { foo: 101 }, }, }; @@ -824,6 +833,11 @@ mod tests { "bevy_reflect::serde::de::tests::MyStruct": { "primitive_value": 123, "option_value": Some("Hello world!"), + "option_value_complex": { + "Some": ({ + "foo": 123, + }), + }, "tuple_value": ( 3.1415927, 1337, diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 1b7d1ae20b5c0..de78ca77b6206 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -361,7 +361,7 @@ impl<'a> Serialize for ArraySerializer<'a> { mod tests { use crate as bevy_reflect; use crate::serde::ReflectSerializer; - use crate::{Reflect, ReflectSerialize, TypeRegistry}; + use crate::{FromReflect, Reflect, ReflectSerialize, TypeRegistry}; use bevy_utils::HashMap; use ron::ser::PrettyConfig; use serde::Serialize; @@ -371,6 +371,7 @@ mod tests { struct MyStruct { primitive_value: i8, option_value: Option, + option_value_complex: Option, tuple_value: (f32, usize), list_value: Vec, array_value: [i32; 5], @@ -384,7 +385,7 @@ mod tests { custom_serialize: CustomSerialize, } - #[derive(Reflect, Debug, PartialEq, Serialize)] + #[derive(Reflect, FromReflect, Debug, PartialEq)] struct SomeStruct { foo: i64, } @@ -400,6 +401,11 @@ mod tests { Struct { foo: String }, } + #[derive(Reflect, Debug, PartialEq, Serialize)] + struct SomeSerializableStruct { + foo: i64, + } + /// Implements a custom serialize using `#[reflect(Serialize)]`. /// /// For testing purposes, this just uses the generated one from deriving Serialize. @@ -408,7 +414,7 @@ mod tests { struct CustomSerialize { value: usize, #[serde(rename = "renamed")] - inner_struct: SomeStruct, + inner_struct: SomeSerializableStruct, } fn get_registry() -> TypeRegistry { @@ -417,6 +423,8 @@ mod tests { registry.register::(); registry.register::(); registry.register::(); + registry.register::(); + registry.register_type_data::(); registry.register::(); registry.register::>(); registry.register_type_data::, ReflectSerialize>(); @@ -431,6 +439,7 @@ mod tests { let input = MyStruct { primitive_value: 123, option_value: Some(String::from("Hello world!")), + option_value_complex: Some(SomeStruct { foo: 123 }), tuple_value: (PI, 1337), list_value: vec![-2, -1, 0, 1, 2], array_value: [-2, -1, 0, 1, 2], @@ -445,7 +454,7 @@ mod tests { }, custom_serialize: CustomSerialize { value: 100, - inner_struct: SomeStruct { foo: 101 }, + inner_struct: SomeSerializableStruct { foo: 101 }, }, }; @@ -462,6 +471,11 @@ mod tests { "bevy_reflect::serde::ser::tests::MyStruct": { "primitive_value": 123, "option_value": Some("Hello world!"), + "option_value_complex": { + "Some": ({ + "foo": 123, + }), + }, "tuple_value": (3.1415927, 1337), "list_value": [ -2, From b35f7a3d2d549c1c0b56fc2d0d3a7ae80c21747d Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 22:37:36 -0700 Subject: [PATCH 23/24] Fix doc comment --- crates/bevy_reflect/src/serde/de.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index bb595347d740e..7b9760d8436f2 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -758,7 +758,7 @@ mod tests { foo: i64, } - /// Implements a custom deserialize using #[reflect(Deserialize)]. + /// Implements a custom deserialize using `#[reflect(Deserialize)]`. /// /// For testing purposes, this is just the auto-generated one from deriving. #[derive(Reflect, FromReflect, Debug, PartialEq, Deserialize)] From 90433d1f0d042014368e48263c31667e104779ac Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 29 Aug 2022 13:02:41 -0700 Subject: [PATCH 24/24] Apply review comment --- crates/bevy_reflect/src/serde/de.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 7b9760d8436f2..f95dc3e126e17 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -138,10 +138,10 @@ impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { A: MapAccess<'de>, { let type_name = map - .next_key::<&str>()? + .next_key::()? .ok_or_else(|| Error::invalid_length(0, &"at least one entry"))?; - let registration = self.registry.get_with_name(type_name).ok_or_else(|| { + let registration = self.registry.get_with_name(&type_name).ok_or_else(|| { Error::custom(format_args!("No registration found for {}", type_name)) })?; let type_info = registration.type_info(); @@ -512,12 +512,12 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { V: MapAccess<'de>, { let variant_name = map - .next_key::<&str>()? + .next_key::()? .ok_or_else(|| Error::missing_field("the variant name of the enum"))?; let variant_info = self .enum_info - .variant(variant_name) + .variant(&variant_name) .ok_or_else(|| Error::custom(format_args!("unknown variant {}", variant_name)))?; let mut dynamic_enum = DynamicEnum::default();