From 4230acd707728febafd04f1a4645e4c43e274d0a Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 19 Mar 2022 18:46:49 -0700 Subject: [PATCH 01/41] Simplified reflection ser/de --- .../bevy_reflect_derive/src/utility.rs | 5 +- crates/bevy_reflect/src/lib.rs | 15 +- crates/bevy_reflect/src/serde/de.rs | 1030 ++++++++++------- crates/bevy_reflect/src/serde/mod.rs | 8 - crates/bevy_reflect/src/serde/ser.rs | 441 ++++--- crates/bevy_reflect/src/serde/type_data.rs | 10 + 6 files changed, 844 insertions(+), 665 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 4f3668bd0cdb2..8b28e4924597d 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -124,10 +124,7 @@ where let mut bitset = BitSet::default(); member_iter.fold(0, |next_idx, member| match member { - ReflectIgnoreBehavior::IgnoreAlways => { - bitset.insert(next_idx); - next_idx - } + ReflectIgnoreBehavior::IgnoreAlways => next_idx, ReflectIgnoreBehavior::IgnoreSerialization => { bitset.insert(next_idx); next_idx + 1 diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 07c1cd0ec1ca0..a85a70d2181a5 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -476,12 +476,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(); @@ -960,13 +965,13 @@ bevy_reflect::tests::should_reflect_debug::Test { 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}}}"# + r#"{"type":"glam::f32::vec3::Vec3","value":(12.0,3.0,-6.9)}"# ); } #[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":(12.0,3.0,-6.9)}"#; let mut registry = TypeRegistry::default(); registry.add_registration(Vec3::get_type_registration()); diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index ad24185de15f3..f40c06e074995 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,9 +1,14 @@ +use crate::serde::SerializationData; 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 +17,389 @@ 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) + + let ignored_len = self + .registry + .get(self.tuple_struct_info.type_id()) + .and_then(|registration| registration.data::()) + .map(|data| data.len()) + .unwrap_or(0); + if tuple_struct.field_len() != self.tuple_struct_info.field_len() - ignored_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 +407,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 +415,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 +447,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 +455,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 +480,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 +797,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 +811,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 +825,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 +839,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 +855,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 1ff61a4e70b4e..1c89a7bbb4a3a 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -8,14 +8,6 @@ pub use type_data::*; 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 b086a6a942085..420f2604695a7 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, @@ -40,6 +40,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, @@ -56,6 +63,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, @@ -92,11 +133,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()), } } } @@ -111,13 +148,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) } } @@ -131,36 +164,15 @@ impl<'a> Serialize for StructSerializer<'a> { 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, - { - let mut state = serializer.serialize_map(Some(self.struct_value.field_len()))?; let serialization_data = self .registry - .get_with_name(self.struct_value.type_name()) + .get(self.struct_value.type_id()) .and_then(|registration| registration.data::()); + let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); + let mut state = + serializer.serialize_map(Some(self.struct_value.field_len() - ignored_len))?; + for (index, value) in self.struct_value.iter_fields().enumerate() { if serialization_data .map(|data| data.is_ignored_field(index)) @@ -169,7 +181,7 @@ impl<'a> Serialize for StructValueSerializer<'a> { continue; } 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() } @@ -185,36 +197,12 @@ 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 serialization_data = self .registry - .get_with_name(self.tuple_struct.type_name()) + .get(self.tuple_struct.type_id()) .and_then(|registration| registration.data::()); - + let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); + let mut state = serializer.serialize_tuple(self.tuple_struct.field_len() - ignored_len)?; for (index, value) in self.tuple_struct.iter_fields().enumerate() { if serialization_data .map(|data| data.is_ignored_field(index)) @@ -222,7 +210,7 @@ impl<'a> Serialize for TupleStructValueSerializer<'a> { { continue; } - state.serialize_element(&ReflectSerializer::new(value, self.registry))?; + state.serialize_element(&TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -238,11 +226,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, @@ -262,36 +248,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() } } @@ -305,10 +281,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() } @@ -324,16 +300,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() } @@ -349,34 +320,10 @@ 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() } @@ -388,30 +335,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, @@ -419,8 +342,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() @@ -433,36 +356,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() } @@ -478,32 +378,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() } @@ -511,21 +388,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)] @@ -547,8 +516,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); @@ -559,14 +528,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); @@ -577,18 +540,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); @@ -601,16 +554,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); } } diff --git a/crates/bevy_reflect/src/serde/type_data.rs b/crates/bevy_reflect/src/serde/type_data.rs index 2e3cd6bbf7951..ee69a390d09cb 100644 --- a/crates/bevy_reflect/src/serde/type_data.rs +++ b/crates/bevy_reflect/src/serde/type_data.rs @@ -31,4 +31,14 @@ impl SerializationData { pub fn is_ignored_field(&self, index: usize) -> bool { self.ignored_field_indices.contains(&index) } + + /// Returns the number of ignored fields. + pub fn len(&self) -> usize { + self.ignored_field_indices.len() + } + + /// Returns true if there are no ignored fields. + pub fn is_empty(&self) -> bool { + self.ignored_field_indices.is_empty() + } } From 32a83b9793034f49c32005336a3dd836b48ecedf Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Fri, 22 Apr 2022 12:45:42 -0700 Subject: [PATCH 02/41] 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 420f2604695a7..ab5d0b588d8c5 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -416,9 +416,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 e8bdefb7901dbb711d5383e8d66a27ba53e05f57 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Fri, 22 Apr 2022 13:38:18 -0700 Subject: [PATCH 03/41] 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 3dd5d0e4f2f50fc226b97cfb3da99c0a8ee51e4c Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 1 Jun 2022 00:11:49 -0700 Subject: [PATCH 04/41] 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 f40c06e074995..fc3e7ab04b85d 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -148,7 +148,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(); @@ -160,12 +160,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`", + )), } } } @@ -727,6 +725,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 { @@ -865,7 +864,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, @@ -883,7 +882,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 ab5d0b588d8c5..5091a61c51ea8 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -394,6 +394,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 { @@ -447,7 +448,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, @@ -468,7 +469,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 f794ad2e6924d67fa7ef8ce7e8af8a44163480c8 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 1 Jun 2022 00:30:04 -0700 Subject: [PATCH 05/41] 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 a85a70d2181a5..a9c749486260a 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -961,17 +961,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","value":(12.0,3.0,-6.9)}"# - ); + assert_eq!(expected, format!("\n{}\n", output)); } #[test] fn vec3_deserialization() { - let data = r#"{"type":"glam::f32::vec3::Vec3","value":(12.0,3.0,-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 f8433558c300ec5180c7078258557b8585337b89 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 1 Jun 2022 00:41:16 -0700 Subject: [PATCH 06/41] 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 a9c749486260a..6cce43f76549c 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -97,7 +97,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}, @@ -455,7 +455,8 @@ mod tests { h: [u32; 2], } - #[derive(Reflect)] + #[derive(Reflect, Serialize, Deserialize)] + #[reflect(Serialize, Deserialize)] struct Bar { x: u32, } From 762fe4fb4bb843c00af59a7de2d7c3ecde38eaa8 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 11 Jun 2022 16:54:07 -0700 Subject: [PATCH 07/41] 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 fc3e7ab04b85d..1245090deb9a3 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -860,7 +860,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 31135e65e65f24dc3d83cf21e6a7497abf2d09e0 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 11 Jun 2022 16:54:30 -0700 Subject: [PATCH 08/41] 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 5091a61c51ea8..9339883848edc 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -463,7 +463,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 5e3ba1ad3ea6e53232fe4aa8b5a6a04583dea10b Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 11 Jun 2022 17:20:44 -0700 Subject: [PATCH 09/41] 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 6cce43f76549c..320ef2fa4df95 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -962,7 +962,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 8d19407804574ea01d835f02bc1936ff27805b3d Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 26 Jun 2022 19:24:38 -0700 Subject: [PATCH 10/41] 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 1245090deb9a3..82b622ef01a0b 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -108,7 +108,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 83829ebdd63018a1399c89505906b92a5eae84d8 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 26 Jun 2022 19:25:54 -0700 Subject: [PATCH 11/41] 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 82b622ef01a0b..2f7d433119df9 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -294,7 +294,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") } @@ -314,7 +314,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") } @@ -372,7 +372,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") } @@ -404,7 +404,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") } @@ -444,7 +444,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") } @@ -486,7 +486,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 54aca19e970683eafb79bc30476852b822cb5cd1 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 26 Jun 2022 19:44:59 -0700 Subject: [PATCH 12/41] Fix PrettyConfig for tests --- crates/bevy_reflect/src/lib.rs | 16 ++++++++-------- crates/bevy_reflect/src/serde/ser.rs | 4 +++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 320ef2fa4df95..0f5c964b1c6eb 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -962,7 +962,9 @@ 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")) + .indentor(String::from(" ")); let output = to_string_pretty(&ser, config).unwrap(); let expected = r#" { @@ -972,10 +974,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] @@ -984,12 +985,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 9339883848edc..2693663cfc4e5 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -463,7 +463,9 @@ 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")) + .indentor(String::from(" ")); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ From 14105da7c6d604c6f9b23e0e8a0f804083d92a0e Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 22:43:31 -0700 Subject: [PATCH 13/41] 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 0f5c964b1c6eb..bf32bb25c7209 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -108,7 +108,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() { @@ -493,7 +493,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(); @@ -995,7 +995,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 2f7d433119df9..7bc52f2ea0272 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -78,47 +78,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 { @@ -170,13 +179,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, @@ -720,7 +738,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; @@ -801,7 +819,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(); @@ -815,7 +833,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(); @@ -829,7 +847,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(); @@ -845,7 +863,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(); @@ -915,7 +933,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 6966a58215fc4ecd811c51eeaff9c85caa8bd50e Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:01:08 -0700 Subject: [PATCH 14/41] 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 7bc52f2ea0272..6e29b54c99349 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -200,6 +200,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; @@ -737,13 +746,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 { @@ -942,4 +954,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 bafda23b72842e66117a7e599ec3ae2c84bc7b5c Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:02:14 -0700 Subject: [PATCH 15/41] 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 6e29b54c99349..6bf7f15b12d1b 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -955,6 +955,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 93b96794a55b4c8404f6261a2a12f9c9f2d88452 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:03:56 -0700 Subject: [PATCH 16/41] 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 6bf7f15b12d1b..2015959d55fc3 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -391,35 +391,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) } } @@ -463,6 +451,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, @@ -505,26 +525,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, @@ -968,7 +968,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 d13316765b2952f35acbdbe4f13a78711a2b8253 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 27 Jun 2022 23:05:11 -0700 Subject: [PATCH 17/41] 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 bf32bb25c7209..d1c2dc61f2265 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -108,7 +108,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 a44df7207ef92e9ca0efcd55329a94eca68e3a87 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 29 Jun 2022 08:25:49 -0700 Subject: [PATCH 18/41] 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 2015959d55fc3..47a6919ce055a 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -117,7 +117,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 88668ae8ebfd36e582ae7f9996e96ead8ba9ef21 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 7 Aug 2022 17:08:37 -0700 Subject: [PATCH 19/41] 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 | 11 ++-- crates/bevy_reflect/src/serde/ser.rs | 24 ++++----- 4 files changed, 38 insertions(+), 80 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index d1c2dc61f2265..784e2fa189b89 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -968,8 +968,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, @@ -983,8 +982,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 47a6919ce055a..ca897e1018014 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,9 +1,9 @@ use crate::serde::SerializationData; 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}; @@ -138,42 +138,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) } } @@ -404,8 +381,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) } @@ -826,8 +803,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": (), }, }"#; @@ -840,8 +816,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), }, }"#; @@ -854,8 +829,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), }, }"#; @@ -868,8 +842,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", }, @@ -906,8 +879,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": ( @@ -958,8 +930,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 1c89a7bbb4a3a..3355ed38d0b11 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -6,16 +6,11 @@ pub use de::*; pub use ser::*; pub use type_data::*; -pub(crate) mod type_fields { - pub const TYPE: &str = "type"; - pub const VALUE: &str = "value"; -} - #[cfg(test)] mod tests { use crate::{self as bevy_reflect, DynamicTupleStruct}; use crate::{ - serde::{ReflectDeserializer, ReflectSerializer}, + serde::{ReflectSerializer, UntypedReflectDeserializer}, type_registry::TypeRegistry, DynamicStruct, Reflect, }; @@ -53,7 +48,7 @@ mod tests { expected.insert("d", 6); let mut deserializer = ron::de::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 deserialized = value.take::().unwrap(); @@ -88,7 +83,7 @@ mod tests { expected.insert(6); let mut deserializer = ron::de::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 deserialized = value.take::().unwrap(); diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 2693663cfc4e5..4b95126152862 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::{ @@ -63,10 +63,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() @@ -469,8 +468,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), @@ -520,8 +518,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": (), }, }"#; @@ -532,8 +529,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), }, }"#; @@ -544,8 +540,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), }, }"#; @@ -558,8 +553,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 5b88e749530dce708252b68544b72f8aa4656763 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 7 Aug 2022 17:26:22 -0700 Subject: [PATCH 20/41] 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 ca897e1018014..bcec01d4b992d 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -744,6 +744,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, } @@ -766,12 +770,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::(); @@ -788,76 +801,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(); @@ -872,6 +815,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 }, @@ -907,6 +856,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: ( @@ -969,4 +932,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 4b95126152862..ef0c4836d3bb5 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -405,6 +405,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, } @@ -416,6 +420,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. @@ -453,6 +465,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 }, @@ -487,6 +505,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 bcb7a0ab8002df866d7a5255fcd2055ac4e04211 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 10 Aug 2022 09:05:51 -0700 Subject: [PATCH 21/41] 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 5d2c99e5fb33de55b7e750f7ae6dae81c509bb61 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 22:24:26 -0700 Subject: [PATCH 22/41] 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 bcec01d4b992d..21bb783bf8de3 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -738,6 +738,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], @@ -751,7 +752,7 @@ mod tests { custom_deserialize: CustomDeserialize, } - #[derive(Reflect, FromReflect, Debug, PartialEq, Deserialize)] + #[derive(Reflect, FromReflect, Debug, PartialEq)] struct SomeStruct { foo: i64, } @@ -759,6 +760,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. @@ -767,7 +773,7 @@ mod tests { struct CustomDeserialize { value: usize, #[serde(rename = "renamed")] - inner_struct: SomeStruct, + inner_struct: SomeDeserializableStruct, } #[derive(Reflect, FromReflect, Debug, PartialEq)] @@ -784,6 +790,7 @@ mod tests { registry.register::(); registry.register::(); registry.register::(); + registry.register::(); registry.register::(); registry.register::(); registry.register::(); @@ -796,6 +803,7 @@ mod tests { registry.register::<[i32; 5]>(); registry.register::>(); registry.register::>(); + registry.register::>(); registry.register::>(); registry.register_type_data::, ReflectDeserialize>(); registry @@ -809,6 +817,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], @@ -823,7 +832,7 @@ mod tests { }, custom_deserialize: CustomDeserialize { value: 100, - inner_struct: SomeStruct { foo: 101 }, + inner_struct: SomeDeserializableStruct { foo: 101 }, }, }; @@ -831,6 +840,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 ef0c4836d3bb5..38129423b760c 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -389,7 +389,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; @@ -399,6 +399,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], @@ -412,7 +413,7 @@ mod tests { custom_serialize: CustomSerialize, } - #[derive(Reflect, Debug, PartialEq, Serialize)] + #[derive(Reflect, FromReflect, Debug, PartialEq)] struct SomeStruct { foo: i64, } @@ -428,6 +429,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. @@ -436,7 +442,7 @@ mod tests { struct CustomSerialize { value: usize, #[serde(rename = "renamed")] - inner_struct: SomeStruct, + inner_struct: SomeSerializableStruct, } fn get_registry() -> TypeRegistry { @@ -445,6 +451,8 @@ mod tests { registry.register::(); registry.register::(); registry.register::(); + registry.register::(); + registry.register_type_data::(); registry.register::(); registry.register::>(); registry.register_type_data::, ReflectSerialize>(); @@ -459,6 +467,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], @@ -473,7 +482,7 @@ mod tests { }, custom_serialize: CustomSerialize { value: 100, - inner_struct: SomeStruct { foo: 101 }, + inner_struct: SomeSerializableStruct { foo: 101 }, }, }; @@ -489,6 +498,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 733b58049016e77903c6e961924235ed6808fd4d Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 22:37:36 -0700 Subject: [PATCH 23/41] 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 21bb783bf8de3..ab48125d54e49 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -765,7 +765,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 db1227e9217e3892acdc83fc7a6bdfc0ed391bfb Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 29 Aug 2022 13:02:41 -0700 Subject: [PATCH 24/41] 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 ab48125d54e49..70f51c3d962bd 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -139,10 +139,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(); @@ -519,12 +519,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(); From dd9b31952995e916bc9edd3c47d10d0a5ba29f25 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 13 Aug 2022 23:50:00 -0700 Subject: [PATCH 25/41] Improved reflect serialization v2 --- .../bevy_reflect_derive/src/impls/enums.rs | 3 +- .../bevy_reflect_derive/src/impls/structs.rs | 3 +- .../src/impls/tuple_structs.rs | 3 +- crates/bevy_reflect/src/enums/enum_trait.rs | 29 +- crates/bevy_reflect/src/enums/variants.rs | 82 ++--- crates/bevy_reflect/src/fields.rs | 7 +- crates/bevy_reflect/src/impls/std.rs | 13 +- crates/bevy_reflect/src/serde/de.rs | 311 +++++++++--------- crates/bevy_reflect/src/serde/ser.rs | 265 ++++++++------- crates/bevy_reflect/src/struct_trait.rs | 27 +- crates/bevy_reflect/src/tuple_struct.rs | 14 +- crates/bevy_reflect/src/type_info.rs | 2 +- crates/bevy_reflect/src/utility.rs | 4 +- 13 files changed, 405 insertions(+), 358 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index 83fceda4e7404..661ae3bee354a 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -53,12 +53,13 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } }); + let string_name = enum_name.to_string(); let typed_impl = impl_typed( enum_name, reflect_enum.meta().generics(), quote! { let variants = [#(#variant_info),*]; - let info = #bevy_reflect_path::EnumInfo::new::(&variants); + let info = #bevy_reflect_path::EnumInfo::new::(#string_name, &variants); #bevy_reflect_path::TypeInfo::Enum(info) }, bevy_reflect_path, diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs index f47dddf6536b0..aaffe40988ac7 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -51,6 +51,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }); + let string_name = struct_name.to_string(); let typed_impl = impl_typed( struct_name, reflect_struct.meta().generics(), @@ -58,7 +59,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { let fields = [ #(#bevy_reflect_path::NamedField::new::<#field_types, _>(#field_names),)* ]; - let info = #bevy_reflect_path::StructInfo::new::(&fields); + let info = #bevy_reflect_path::StructInfo::new::(#string_name, &fields); #bevy_reflect_path::TypeInfo::Struct(info) }, bevy_reflect_path, diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs index ecd829f94f034..bb44fc5f231aa 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs @@ -35,6 +35,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }); + let string_name = struct_name.to_string(); let typed_impl = impl_typed( struct_name, reflect_struct.meta().generics(), @@ -42,7 +43,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { let fields = [ #(#bevy_reflect_path::UnnamedField::new::<#field_types>(#field_idents),)* ]; - let info = #bevy_reflect_path::TupleStructInfo::new::(&fields); + let info = #bevy_reflect_path::TupleStructInfo::new::(#string_name, &fields); #bevy_reflect_path::TypeInfo::TupleStruct(info) }, bevy_reflect_path, diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index 9ee110d8f0a05..fb57b4fd8f2a8 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -1,7 +1,6 @@ use crate::{DynamicEnum, Reflect, VariantInfo, VariantType}; use bevy_utils::HashMap; use std::any::{Any, TypeId}; -use std::borrow::Cow; use std::slice::Iter; /// A trait representing a [reflected] enum. @@ -131,10 +130,12 @@ pub trait Enum: Reflect { /// A container for compile-time enum info, used by [`TypeInfo`](crate::TypeInfo). #[derive(Clone, Debug)] pub struct EnumInfo { + name: &'static str, type_name: &'static str, type_id: TypeId, variants: Box<[VariantInfo]>, - variant_indices: HashMap, usize>, + variant_names: Box<[&'static str]>, + variant_indices: HashMap<&'static str, usize>, } impl EnumInfo { @@ -142,9 +143,10 @@ impl EnumInfo { /// /// # Arguments /// + /// * `name`: The name of this enum (_without_ generics or lifetimes) /// * `variants`: The variants of this enum in the order they are defined /// - pub fn new(variants: &[VariantInfo]) -> Self { + pub fn new(name: &'static str, variants: &[VariantInfo]) -> Self { let variant_indices = variants .iter() .enumerate() @@ -154,10 +156,17 @@ impl EnumInfo { }) .collect::>(); + let variant_names = variants + .iter() + .map(|variant| variant.name()) + .collect::>(); + Self { + name, type_name: std::any::type_name::(), type_id: TypeId::of::(), variants: variants.to_vec().into_boxed_slice(), + variant_names: variant_names.into_boxed_slice(), variant_indices, } } @@ -169,6 +178,11 @@ impl EnumInfo { .map(|index| &self.variants[*index]) } + /// A slice containing the names of all variants in order. + pub fn variant_names(&self) -> &[&'static str] { + &self.variant_names + } + /// Get a variant at the given index. pub fn variant_at(&self, index: usize) -> Option<&VariantInfo> { self.variants.get(index) @@ -201,6 +215,15 @@ impl EnumInfo { self.variants.len() } + /// The name of the enum. + /// + /// This does _not_ include any generics or lifetimes. + /// + /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`. + pub fn name(&self) -> &'static str { + self.name + } + /// The [type name] of the enum. /// /// [type name]: std::any::type_name diff --git a/crates/bevy_reflect/src/enums/variants.rs b/crates/bevy_reflect/src/enums/variants.rs index b1a9740d21c75..5703a376fe2e9 100644 --- a/crates/bevy_reflect/src/enums/variants.rs +++ b/crates/bevy_reflect/src/enums/variants.rs @@ -1,6 +1,5 @@ use crate::{NamedField, UnnamedField}; use bevy_utils::HashMap; -use std::borrow::Cow; use std::slice::Iter; /// Describes the form of an enum variant. @@ -66,7 +65,7 @@ pub enum VariantInfo { } impl VariantInfo { - pub fn name(&self) -> &Cow<'static, str> { + pub fn name(&self) -> &'static str { match self { Self::Struct(info) => info.name(), Self::Tuple(info) => info.name(), @@ -78,39 +77,28 @@ impl VariantInfo { /// Type info for struct variants. #[derive(Clone, Debug)] pub struct StructVariantInfo { - name: Cow<'static, str>, + name: &'static str, fields: Box<[NamedField]>, - field_indices: HashMap, usize>, + field_names: Box<[&'static str]>, + field_indices: HashMap<&'static str, usize>, } impl StructVariantInfo { /// Create a new [`StructVariantInfo`]. - pub fn new(name: &str, fields: &[NamedField]) -> Self { - let field_indices = Self::collect_field_indices(fields); - - Self { - name: Cow::Owned(name.into()), - fields: fields.to_vec().into_boxed_slice(), - field_indices, - } - } - - /// Create a new [`StructVariantInfo`] using a static string. - /// - /// This helps save an allocation when the string has a static lifetime, such - /// as when using defined sa a literal. - pub fn new_static(name: &'static str, fields: &[NamedField]) -> Self { + pub fn new(name: &'static str, fields: &[NamedField]) -> Self { let field_indices = Self::collect_field_indices(fields); + let field_names = fields.iter().map(|field| field.name()).collect::>(); Self { - name: Cow::Borrowed(name), + name, fields: fields.to_vec().into_boxed_slice(), + field_names: field_names.into_boxed_slice(), field_indices, } } /// The name of this variant. - pub fn name(&self) -> &Cow<'static, str> { - &self.name + pub fn name(&self) -> &'static str { + self.name } /// Get the field with the given name. @@ -120,6 +108,11 @@ impl StructVariantInfo { .map(|index| &self.fields[*index]) } + /// A slice containing the names of all fields in order. + pub fn field_names(&self) -> &[&'static str] { + &self.field_names + } + /// Get the field at the given index. pub fn field_at(&self, index: usize) -> Option<&NamedField> { self.fields.get(index) @@ -140,7 +133,7 @@ impl StructVariantInfo { self.fields.len() } - fn collect_field_indices(fields: &[NamedField]) -> HashMap, usize> { + fn collect_field_indices(fields: &[NamedField]) -> HashMap<&'static str, usize> { fields .iter() .enumerate() @@ -155,33 +148,22 @@ impl StructVariantInfo { /// Type info for tuple variants. #[derive(Clone, Debug)] pub struct TupleVariantInfo { - name: Cow<'static, str>, + name: &'static str, fields: Box<[UnnamedField]>, } impl TupleVariantInfo { /// Create a new [`TupleVariantInfo`]. - pub fn new(name: &str, fields: &[UnnamedField]) -> Self { - Self { - name: Cow::Owned(name.into()), - fields: fields.to_vec().into_boxed_slice(), - } - } - - /// Create a new [`TupleVariantInfo`] using a static string. - /// - /// This helps save an allocation when the string has a static lifetime, such - /// as when using defined sa a literal. - pub fn new_static(name: &'static str, fields: &[UnnamedField]) -> Self { + pub fn new(name: &'static str, fields: &[UnnamedField]) -> Self { Self { - name: Cow::Borrowed(name), + name, fields: fields.to_vec().into_boxed_slice(), } } /// The name of this variant. - pub fn name(&self) -> &Cow<'static, str> { - &self.name + pub fn name(&self) -> &'static str { + self.name } /// Get the field at the given index. @@ -203,29 +185,17 @@ impl TupleVariantInfo { /// Type info for unit variants. #[derive(Clone, Debug)] pub struct UnitVariantInfo { - name: Cow<'static, str>, + name: &'static str, } impl UnitVariantInfo { /// Create a new [`UnitVariantInfo`]. - pub fn new(name: &str) -> Self { - Self { - name: Cow::Owned(name.into()), - } - } - - /// Create a new [`UnitVariantInfo`] using a static string. - /// - /// This helps save an allocation when the string has a static lifetime, such - /// as when using defined sa a literal. - pub fn new_static(name: &'static str) -> Self { - Self { - name: Cow::Borrowed(name), - } + pub fn new(name: &'static str) -> Self { + Self { name } } /// The name of this variant. - pub fn name(&self) -> &Cow<'static, str> { - &self.name + pub fn name(&self) -> &'static str { + self.name } } diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index 21dc9ec5f75e2..3e6505b1e22dd 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,18 +1,17 @@ use crate::Reflect; use std::any::{Any, TypeId}; -use std::borrow::Cow; /// The named field of a reflected struct. #[derive(Clone, Debug)] pub struct NamedField { - name: Cow<'static, str>, + name: &'static str, type_name: &'static str, type_id: TypeId, } impl NamedField { /// Create a new [`NamedField`]. - pub fn new>>(name: TName) -> Self { + pub fn new>(name: TName) -> Self { Self { name: name.into(), type_name: std::any::type_name::(), @@ -21,7 +20,7 @@ impl NamedField { } /// The name of the field. - pub fn name(&self) -> &Cow<'static, str> { + pub fn name(&self) -> &'static str { &self.name } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 462791d32bc95..a5f6816cd1e3f 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -844,12 +844,13 @@ impl Typed for Option { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| { - let none_variant = VariantInfo::Unit(UnitVariantInfo::new_static("None")); - let some_variant = VariantInfo::Tuple(TupleVariantInfo::new_static( - "Some", - &[UnnamedField::new::(0)], - )); - TypeInfo::Enum(EnumInfo::new::(&[none_variant, some_variant])) + let none_variant = VariantInfo::Unit(UnitVariantInfo::new("None")); + let some_variant = + VariantInfo::Tuple(TupleVariantInfo::new("Some", &[UnnamedField::new::(0)])); + TypeInfo::Enum(EnumInfo::new::( + "Option", + &[none_variant, some_variant], + )) }) } } diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 70f51c3d962bd..42d0a3b3fb6a8 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,13 +1,17 @@ use crate::serde::SerializationData; use crate::{ 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, + DynamicTupleStruct, DynamicVariant, 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 serde::de::{ + self, DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor, +}; +use serde::Deserialize; use std::any::TypeId; +use std::fmt; use std::fmt::Formatter; pub trait DeserializeValue { @@ -76,6 +80,43 @@ impl TupleLikeInfo for TupleVariantInfo { } } +/// Represents a simple reflected identifier. +#[derive(Debug, Clone, Eq, PartialEq)] +struct Ident(String); + +impl<'de> Deserialize<'de> for Ident { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct IdentVisitor; + + impl<'de> Visitor<'de> for IdentVisitor { + type Value = Ident; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("identifier") + } + + fn visit_str(self, value: &str) -> Result + where + E: Error, + { + Ok(Ident(value.to_string())) + } + + fn visit_string(self, value: String) -> Result + where + E: Error, + { + Ok(Ident(value)) + } + } + + deserializer.deserialize_identifier(IdentVisitor) + } +} + /// A general purpose deserializer for reflected types. /// /// This will return a [`Box`] containing the deserialized data. @@ -173,12 +214,12 @@ impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { /// [`DynamicList`]: crate::DynamicList /// [`FromReflect`]: crate::FromReflect pub struct TypedReflectDeserializer<'a> { - type_info: &'a TypeInfo, + type_info: &'static TypeInfo, registry: &'a TypeRegistry, } impl<'a> TypedReflectDeserializer<'a> { - pub fn new(type_info: &'a TypeInfo, registry: &'a TypeRegistry) -> Self { + pub fn new(type_info: &'static TypeInfo, registry: &'a TypeRegistry) -> Self { Self { type_info, registry, @@ -207,15 +248,20 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { match self.type_info { TypeInfo::Struct(struct_info) => { - let mut dynamic_struct = deserializer.deserialize_map(StructVisitor { - struct_info, - registry: self.registry, - })?; + let mut dynamic_struct = deserializer.deserialize_struct( + struct_info.name(), + struct_info.field_names(), + 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( + let mut dynamic_tuple_struct = deserializer.deserialize_tuple_struct( + tuple_struct_info.name(), tuple_struct_info.field_len(), TupleStructVisitor { tuple_struct_info, @@ -264,10 +310,14 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { Ok(Box::new(dynamic_tuple)) } TypeInfo::Enum(enum_info) => { - let mut dynamic_enum = deserializer.deserialize_map(EnumVisitor { - enum_info, - registry: self.registry, - })?; + let mut dynamic_enum = deserializer.deserialize_enum( + enum_info.name(), + enum_info.variant_names(), + EnumVisitor { + enum_info, + registry: self.registry, + }, + )?; dynamic_enum.set_name(enum_info.type_name().to_string()); Ok(Box::new(dynamic_enum)) } @@ -329,7 +379,7 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { let mut index = 0usize; let mut tuple_struct = DynamicTupleStruct::default(); - let get_field_info = |index: usize| -> Result<&'a TypeInfo, V::Error> { + let get_field_info = |index: usize| -> Result<&'static 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 {}", @@ -503,7 +553,7 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { } struct EnumVisitor<'a> { - enum_info: &'a EnumInfo, + enum_info: &'static EnumInfo, registry: &'a TypeRegistry, } @@ -514,39 +564,58 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { formatter.write_str("reflected enum value") } - fn visit_map(self, mut map: V) -> Result + fn visit_enum(self, data: A) -> Result where - V: MapAccess<'de>, + A: EnumAccess<'de>, { - let variant_name = map - .next_key::()? - .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, + match data.variant().unwrap() { + (Ident(variant_name), variant) => { + let variant_info = self.enum_info.variant(&variant_name).ok_or_else(|| { + Error::unknown_variant(&variant_name, self.enum_info.variant_names()) })?; - dynamic_enum.set_variant(variant_name, dynamic_tuple); - } - VariantInfo::Unit(..) => { - map.next_value::<()>()?; - dynamic_enum.set_variant(variant_name, ()); + let value: DynamicVariant = match variant_info { + VariantInfo::Unit(..) => variant.unit_variant()?.into(), + VariantInfo::Struct(struct_info) => variant + .struct_variant( + struct_info.field_names(), + StructVariantVisitor { + struct_info, + registry: self.registry, + }, + )? + .into(), + VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { + let field = tuple_info.field_at(0).unwrap(); + let type_info = + self.registry + .get_type_info(field.type_id()) + .ok_or_else(|| { + Error::custom(format_args!( + "no registration found for type {}", + field.type_name() + )) + })?; + let value = variant.newtype_variant_seed(TypedReflectDeserializer { + type_info, + registry: self.registry, + })?; + let mut dynamic_tuple = DynamicTuple::default(); + dynamic_tuple.insert_boxed(value); + dynamic_tuple.into() + } + VariantInfo::Tuple(tuple_info) => variant + .tuple_variant( + tuple_info.field_len(), + TupleVariantVisitor { + tuple_info, + registry: self.registry, + }, + )? + .into(), + }; + + dynamic_enum.set_variant(variant_name, value); } } @@ -554,25 +623,6 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { } } -struct StructVariantDeserializer<'a> { - struct_info: &'a StructVariantInfo, - registry: &'a TypeRegistry, -} - -impl<'a, 'de> DeserializeSeed<'de> for StructVariantDeserializer<'a> { - type Value = DynamicStruct; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_map(StructVariantVisitor { - struct_info: self.struct_info, - registry: self.registry, - }) - } -} - struct StructVariantVisitor<'a> { struct_info: &'a StructVariantInfo, registry: &'a TypeRegistry, @@ -593,28 +643,6 @@ impl<'a, 'de> Visitor<'de> for StructVariantVisitor<'a> { } } -struct TupleVariantDeserializer<'a> { - tuple_info: &'a TupleVariantInfo, - registry: &'a TypeRegistry, -} - -impl<'a, 'de> DeserializeSeed<'de> for TupleVariantDeserializer<'a> { - type Value = DynamicTuple; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_tuple( - self.tuple_info.field_len(), - TupleVariantVisitor { - tuple_info: self.tuple_info, - registry: self.registry, - }, - ) - } -} - struct TupleVariantVisitor<'a> { tuple_info: &'a TupleVariantInfo, registry: &'a TypeRegistry, @@ -645,7 +673,7 @@ where V: MapAccess<'de>, { let mut dynamic_struct = DynamicStruct::default(); - while let Some(key) = map.next_key::()? { + while let Some(Ident(key)) = map.next_key::()? { let field = info.get_field(&key).ok_or_else(|| { Error::custom(format_args!( "no field named {} on struct {}", @@ -710,11 +738,11 @@ where Ok(tuple) } -fn get_type_info<'a, E: de::Error>( +fn get_type_info( type_id: TypeId, - type_name: &'a str, - registry: &'a TypeRegistry, -) -> Result<&'a TypeInfo, E> { + type_name: &str, + registry: &TypeRegistry, +) -> Result<&'static TypeInfo, E> { let registration = registry.get(type_id).ok_or_else(|| { de::Error::custom(format_args!("no registration found for type {}", type_name)) })?; @@ -837,60 +865,41 @@ mod tests { }; let input = r#"{ - "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, - ), - "list_value": [ + "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), + list_value: [ -2, -1, 0, 1, 2, ], - "array_value": ( - -2, - -1, - 0, - 1, - 2, - ), - "map_value": { + array_value: (-2, -1, 0, 1, 2), + map_value: { 64: 32, }, - "struct_value": { - "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": ( + struct_value: ( + 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: ( foo: 101, ), - ) - }, + ), + ), }"#; let registry = get_registry(); @@ -931,9 +940,9 @@ mod tests { let expected = Foo { bar: 123 }; - let input = r#"{ - "bar": 123 - }"#; + let input = r#"( + bar: 123 + )"#; let mut registry = get_registry(); registry.register::(); @@ -962,10 +971,8 @@ mod tests { // === Unit Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "Unit": (), - }, - }"#; + "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(); @@ -975,10 +982,8 @@ mod tests { // === NewType Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "NewType": (123), - }, - }"#; + "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(); @@ -988,10 +993,8 @@ mod tests { // === Tuple Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "Tuple": (1.23, 3.21), - }, - }"#; + "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(); @@ -1001,12 +1004,10 @@ mod tests { // === Struct Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": { - "Struct": { - "value": "I <3 Enums", - }, - }, - }"#; + "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(); diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 38129423b760c..a7d32f579360a 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -1,11 +1,14 @@ use crate::{ Array, Enum, List, Map, Reflect, ReflectRef, ReflectSerialize, Struct, Tuple, TupleStruct, - TypeRegistry, VariantType, + TypeInfo, TypeRegistry, VariantInfo, VariantType, +}; +use serde::ser::{ + Error, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, + SerializeTupleVariant, }; -use serde::ser::SerializeTuple; use serde::{ ser::{SerializeMap, SerializeSeq}, - Serialize, Serializer, + Serialize, }; use super::SerializationData; @@ -163,14 +166,25 @@ impl<'a> Serialize for StructSerializer<'a> { where S: serde::Serializer, { + let struct_info = match self.struct_value.get_type_info() { + TypeInfo::Struct(struct_info) => struct_info, + info => { + return Err(Error::custom(format_args!( + "expected struct type but received {:?}", + info + ))); + } + }; let serialization_data = self .registry .get(self.struct_value.type_id()) .and_then(|registration| registration.data::()); let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); - let mut state = - serializer.serialize_map(Some(self.struct_value.field_len() - ignored_len))?; + let mut state = serializer.serialize_struct( + struct_info.name(), + self.struct_value.field_len() - ignored_len, + )?; for (index, value) in self.struct_value.iter_fields().enumerate() { if serialization_data @@ -179,8 +193,8 @@ impl<'a> Serialize for StructSerializer<'a> { { continue; } - let key = self.struct_value.name_at(index).unwrap(); - state.serialize_entry(key, &TypedReflectSerializer::new(value, self.registry))?; + let key = struct_info.field_at(index).unwrap().name(); + state.serialize_field(&key, &TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -196,12 +210,26 @@ impl<'a> Serialize for TupleStructSerializer<'a> { where S: serde::Serializer, { + let tuple_struct_info = match self.tuple_struct.get_type_info() { + TypeInfo::TupleStruct(tuple_struct_info) => tuple_struct_info, + info => { + return Err(Error::custom(format_args!( + "expected tuple struct type but received {:?}", + info + ))); + } + }; + let serialization_data = self .registry .get(self.tuple_struct.type_id()) .and_then(|registration| registration.data::()); let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); - let mut state = serializer.serialize_tuple(self.tuple_struct.field_len() - ignored_len)?; + let mut state = serializer.serialize_tuple_struct( + tuple_struct_info.name(), + self.tuple_struct.field_len() - ignored_len, + )?; + for (index, value) in self.tuple_struct.iter_fields().enumerate() { if serialization_data .map(|data| data.is_ignored_field(index)) @@ -209,7 +237,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> { { continue; } - state.serialize_element(&TypedReflectSerializer::new(value, self.registry))?; + state.serialize_field(&TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -225,90 +253,95 @@ impl<'a> Serialize for EnumSerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_map(Some(1))?; - state.serialize_entry( - self.enum_value.variant_name(), - &EnumValueSerializer { - enum_value: self.enum_value, - registry: self.registry, - }, - )?; - state.end() - } -} - -pub struct EnumValueSerializer<'a> { - pub enum_value: &'a dyn Enum, - pub registry: &'a TypeRegistry, -} + let enum_info = match self.enum_value.get_type_info() { + TypeInfo::Enum(enum_info) => enum_info, + info => { + return Err(Error::custom(format_args!( + "expected enum type but received {:?}", + info + ))); + } + }; -impl<'a> Serialize for EnumValueSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self.enum_value.variant_type() { + let enum_name = enum_info.name(); + let variant_info = enum_info + .variant(self.enum_value.variant_name()) + .ok_or_else(|| { + Error::custom(format_args!( + "variant `{}` does not exist", + self.enum_value.variant_name() + )) + })?; + let variant_index = enum_info + .index_of(self.enum_value.variant_name()) + .ok_or_else(|| { + Error::custom(format_args!( + "variant `{}` does not exist", + self.enum_value.variant_name() + )) + })? as u32; + let variant_name = variant_info.name(); + let variant_type = self.enum_value.variant_type(); + let field_len = self.enum_value.field_len(); + + match variant_type { + VariantType::Unit => { + serializer.serialize_unit_variant(enum_name, variant_index, variant_name) + } VariantType::Struct => { - 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)?; + let struct_info = match variant_info { + VariantInfo::Struct(struct_info) => struct_info, + info => { + return Err(Error::custom(format_args!( + "expected struct variant type but received {:?}", + info + ))); + } + }; + + let mut state = serializer.serialize_struct_variant( + enum_name, + variant_index, + variant_name, + field_len, + )?; + for (index, field) in self.enum_value.iter_fields().enumerate() { + let field_info = struct_info.field_at(index).unwrap(); + state.serialize_field( + field_info.name(), + &TypedReflectSerializer::new(field.value(), self.registry), + )?; } state.end() } + VariantType::Tuple if field_len == 1 => { + let field = self.enum_value.field_at(0).unwrap(); + serializer.serialize_newtype_variant( + enum_name, + variant_index, + variant_name, + &TypedReflectSerializer::new(field, self.registry), + ) + } VariantType::Tuple => { - let mut state = serializer.serialize_tuple(self.enum_value.field_len())?; + let mut state = serializer.serialize_tuple_variant( + enum_name, + variant_index, + variant_name, + field_len, + )?; for field in self.enum_value.iter_fields() { - let value = TypedReflectSerializer::new(field.value(), self.registry); - state.serialize_element(&value)?; + state.serialize_field(&TypedReflectSerializer::new( + field.value(), + self.registry, + ))?; } state.end() } - VariantType::Unit => serializer.serialize_unit(), } } } -pub struct TupleVariantSerializer<'a> { - pub enum_value: &'a dyn Enum, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for TupleVariantSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - 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() - } -} - -pub struct StructVariantSerializer<'a> { - pub enum_value: &'a dyn Enum, - pub registry: &'a TypeRegistry, -} - -impl<'a> Serialize for StructVariantSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - 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() - } -} - pub struct TupleSerializer<'a> { pub tuple: &'a dyn Tuple, pub registry: &'a TypeRegistry, @@ -495,51 +528,41 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ - "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": [ + "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, -1, 0, 1, 2, ], - "array_value": (-2, -1, 0, 1, 2), - "map_value": { + array_value: (-2, -1, 0, 1, 2), + map_value: { 64: 32, }, - "struct_value": { - "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": ( + struct_value: ( + 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: ( foo: 101, ), ), - }, + ), }"#; assert_eq!(expected, output); } @@ -564,9 +587,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { - "Unit": (), - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Unit, }"#; assert_eq!(expected, output); @@ -575,9 +596,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { - "NewType": (123), - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": NewType(123), }"#; assert_eq!(expected, output); @@ -586,9 +605,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { - "Tuple": (1.23, 3.21), - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Tuple(1.23, 3.21), }"#; assert_eq!(expected, output); @@ -599,11 +616,9 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": { - "Struct": { - "value": "I <3 Enums", - }, - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Struct( + value: "I <3 Enums", + ), }"#; assert_eq!(expected, output); } diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index a1dc934b9efaf..a92a276c677c8 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -69,10 +69,12 @@ pub trait Struct: Reflect { /// A container for compile-time struct info. #[derive(Clone, Debug)] pub struct StructInfo { + name: &'static str, type_name: &'static str, type_id: TypeId, fields: Box<[NamedField]>, - field_indices: HashMap, usize>, + field_names: Box<[&'static str]>, + field_indices: HashMap<&'static str, usize>, } impl StructInfo { @@ -80,9 +82,10 @@ impl StructInfo { /// /// # Arguments /// + /// * `name`: The name of this struct (_without_ generics or lifetimes) /// * `fields`: The fields of this struct in the order they are defined /// - pub fn new(fields: &[NamedField]) -> Self { + pub fn new(name: &'static str, fields: &[NamedField]) -> Self { let field_indices = fields .iter() .enumerate() @@ -91,10 +94,16 @@ impl StructInfo { (name, index) }) .collect::>(); + let field_names = fields + .iter() + .map(|field| field.name()) + .collect::>(); Self { + name, type_name: std::any::type_name::(), type_id: TypeId::of::(), + field_names: field_names.into_boxed_slice(), fields: fields.to_vec().into_boxed_slice(), field_indices, } @@ -107,6 +116,11 @@ impl StructInfo { .map(|index| &self.fields[*index]) } + /// A slice containing the names of all fields in order. + pub fn field_names(&self) -> &[&'static str] { + &self.field_names + } + /// Get the field at the given index. pub fn field_at(&self, index: usize) -> Option<&NamedField> { self.fields.get(index) @@ -127,6 +141,15 @@ impl StructInfo { self.fields.len() } + /// The name of the struct. + /// + /// This does _not_ include any generics or lifetimes. + /// + /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`. + pub fn name(&self) -> &'static str { + self.name + } + /// The [type name] of the struct. /// /// [type name]: std::any::type_name diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 507b6b4bfd117..e7bb89cebb5a8 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -49,6 +49,7 @@ pub trait TupleStruct: Reflect { /// A container for compile-time tuple struct info. #[derive(Clone, Debug)] pub struct TupleStructInfo { + name: &'static str, type_name: &'static str, type_id: TypeId, fields: Box<[UnnamedField]>, @@ -59,10 +60,12 @@ impl TupleStructInfo { /// /// # Arguments /// + /// * `name`: The name of this struct (_without_ generics or lifetimes) /// * `fields`: The fields of this struct in the order they are defined /// - pub fn new(fields: &[UnnamedField]) -> Self { + pub fn new(name: &'static str, fields: &[UnnamedField]) -> Self { Self { + name, type_name: std::any::type_name::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), @@ -84,6 +87,15 @@ impl TupleStructInfo { self.fields.len() } + /// The name of the struct. + /// + /// This does _not_ include any generics or lifetimes. + /// + /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`. + pub fn name(&self) -> &'static str { + self.name + } + /// The [type name] of the tuple struct. /// /// [type name]: std::any::type_name diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index afbe037b7243d..a954082f9b9c6 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -40,7 +40,7 @@ use std::any::{Any, TypeId}; /// NamedField::new::("foo"), /// NamedField::new::<(f32, f32), _>("bar"), /// ]; -/// let info = StructInfo::new::(&fields); +/// let info = StructInfo::new::("MyStruct", &fields); /// TypeInfo::Struct(info) /// }) /// } diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 3e38c6dc35932..c11d2a08cf7b5 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -28,7 +28,7 @@ use std::any::{Any, TypeId}; /// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); /// CELL.get_or_set(|| { /// let fields = [NamedField::new::("bar")]; -/// let info = StructInfo::new::(&fields); +/// let info = StructInfo::new::("Foo", &fields); /// TypeInfo::Struct(info) /// }) /// } @@ -89,7 +89,7 @@ impl NonGenericTypeInfoCell { /// static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); /// CELL.get_or_insert::(|| { /// let fields = [UnnamedField::new::(0)]; -/// let info = TupleStructInfo::new::(&fields); +/// let info = TupleStructInfo::new::("Foo", &fields); /// TypeInfo::TupleStruct(info) /// }) /// } From 94baee853cb83fc69234091fb64988dd278dd455 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 22:57:40 -0700 Subject: [PATCH 26/41] Improve error message for unknown fields on struct-likes --- crates/bevy_reflect/src/serde/de.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 42d0a3b3fb6a8..f3ca7979eb612 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -24,6 +24,7 @@ pub trait DeserializeValue { trait StructLikeInfo { fn get_name(&self) -> &str; fn get_field(&self, name: &str) -> Option<&NamedField>; + fn get_field_names(&self) -> &[&'static str]; } trait TupleLikeInfo { @@ -40,6 +41,10 @@ impl StructLikeInfo for StructInfo { fn get_field(&self, name: &str) -> Option<&NamedField> { self.field(name) } + + fn get_field_names(&self) -> &[&'static str] { + self.field_names() + } } impl StructLikeInfo for StructVariantInfo { @@ -50,6 +55,10 @@ impl StructLikeInfo for StructVariantInfo { fn get_field(&self, name: &str) -> Option<&NamedField> { self.field(name) } + + fn get_field_names(&self) -> &[&'static str] { + self.field_names() + } } impl TupleLikeInfo for TupleInfo { @@ -341,7 +350,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { } struct StructVisitor<'a> { - struct_info: &'a StructInfo, + struct_info: &'static StructInfo, registry: &'a TypeRegistry, } @@ -624,7 +633,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { } struct StructVariantVisitor<'a> { - struct_info: &'a StructVariantInfo, + struct_info: &'static StructVariantInfo, registry: &'a TypeRegistry, } @@ -665,7 +674,7 @@ impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'a> { fn visit_struct<'de, T, V>( map: &mut V, - info: &T, + info: &'static T, registry: &TypeRegistry, ) -> Result where @@ -674,13 +683,9 @@ where { let mut dynamic_struct = DynamicStruct::default(); while let Some(Ident(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 field = info + .get_field(&key) + .ok_or_else(|| Error::unknown_field(&key, info.get_field_names()))?; let type_info = get_type_info(field.type_id(), field.type_name(), registry)?; let value = map.next_value_seed(TypedReflectDeserializer { type_info, From cb37f2eb57dd99beea786323c4ab7ee2e5c5e80d Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 22:59:51 -0700 Subject: [PATCH 27/41] Require 'static on all type info This is meant for future-proofing certain operations --- 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 f3ca7979eb612..46f51646bb5a3 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -370,7 +370,7 @@ impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { } struct TupleStructVisitor<'a> { - tuple_struct_info: &'a TupleStructInfo, + tuple_struct_info: &'static TupleStructInfo, registry: &'a TypeRegistry, } @@ -428,7 +428,7 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { } struct TupleVisitor<'a> { - tuple_info: &'a TupleInfo, + tuple_info: &'static TupleInfo, registry: &'a TypeRegistry, } @@ -448,7 +448,7 @@ impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { } struct ArrayVisitor<'a> { - array_info: &'a ArrayInfo, + array_info: &'static ArrayInfo, registry: &'a TypeRegistry, } @@ -488,7 +488,7 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { } struct ListVisitor<'a> { - list_info: &'a ListInfo, + list_info: &'static ListInfo, registry: &'a TypeRegistry, } @@ -520,7 +520,7 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { } struct MapVisitor<'a> { - map_info: &'a MapInfo, + map_info: &'static MapInfo, registry: &'a TypeRegistry, } @@ -653,7 +653,7 @@ impl<'a, 'de> Visitor<'de> for StructVariantVisitor<'a> { } struct TupleVariantVisitor<'a> { - tuple_info: &'a TupleVariantInfo, + tuple_info: &'static TupleVariantInfo, registry: &'a TypeRegistry, } From 98458ba86ec8da52ec69c06b57ef449533752693 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 23:04:33 -0700 Subject: [PATCH 28/41] Improve error message --- crates/bevy_reflect/src/serde/de.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 46f51646bb5a3..4f3bf8538feef 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -711,11 +711,7 @@ where 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(), - )) + Error::invalid_length(index, &info.get_field_len().to_string().as_str()) })?; get_type_info(field.type_id(), field.type_name(), registry) }; From ca68a37641606f5ea9969e0665de47281f11736f Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 16 Aug 2022 23:14:05 -0700 Subject: [PATCH 29/41] Update scene file --- assets/scenes/load_scene_example.scn.ron | 48 ++++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/assets/scenes/load_scene_example.scn.ron b/assets/scenes/load_scene_example.scn.ron index 8400e28f6e2aa..015b41774f3c0 100644 --- a/assets/scenes/load_scene_example.scn.ron +++ b/assets/scenes/load_scene_example.scn.ron @@ -3,30 +3,30 @@ entity: 0, components: [ { - "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": { - "x": 1.0, - "y": 1.0, - "z": 1.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: ( + x: 1.0, + y: 1.0, + z: 1.0 + ), + ), }, { - "scene::ComponentB": { - "value": "hello", - }, + "scene::ComponentB": ( + value: "hello", + ), }, { - "scene::ComponentA": { - "x": 1.0, - "y": 2.0, - }, + "scene::ComponentA": ( + x: 1.0, + y: 2.0, + ), }, ], ), @@ -34,10 +34,10 @@ entity: 1, components: [ { - "scene::ComponentA": { - "x": 3.0, - "y": 4.0, - }, + "scene::ComponentA": ( + x: 3.0, + y: 4.0, + ), }, ], ), From a2b6e2ec46cafa074b578390067d54dc46a3f638 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 17 Aug 2022 00:08:09 -0700 Subject: [PATCH 30/41] Allow Dynamic types to be serialized again --- crates/bevy_reflect/src/serde/ser.rs | 49 +++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index a7d32f579360a..5832b1e215fe5 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -43,6 +43,29 @@ fn get_serializable<'a, E: serde::ser::Error>( Ok(reflect_serialize.get_serializable(reflect_value)) } +/// Get the underlying [`TypeInfo`] of a given type. +/// +/// If the given type is a [`TypeInfo::Dynamic`] then we need to try and look +/// up the actual type in the registry. +fn get_type_info( + type_info: &'static TypeInfo, + type_name: &str, + registry: &TypeRegistry, +) -> Result<&'static TypeInfo, E> { + match type_info { + TypeInfo::Dynamic(..) => match registry.get_with_name(type_name) { + Some(registration) => Ok(registration.type_info()), + None => { + return Err(Error::custom(format_args!( + "no registration found for dynamic type with name {}", + type_name + ))) + } + }, + info => Ok(info), + } +} + /// A general purpose serializer for reflected types. /// /// The serialized data will take the form of a map containing the following entries: @@ -166,7 +189,13 @@ impl<'a> Serialize for StructSerializer<'a> { where S: serde::Serializer, { - let struct_info = match self.struct_value.get_type_info() { + let type_info = get_type_info( + self.struct_value.get_type_info(), + self.struct_value.type_name(), + self.registry, + )?; + + let struct_info = match type_info { TypeInfo::Struct(struct_info) => struct_info, info => { return Err(Error::custom(format_args!( @@ -175,11 +204,11 @@ impl<'a> Serialize for StructSerializer<'a> { ))); } }; + let serialization_data = self .registry .get(self.struct_value.type_id()) .and_then(|registration| registration.data::()); - let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); let mut state = serializer.serialize_struct( struct_info.name(), @@ -210,7 +239,13 @@ impl<'a> Serialize for TupleStructSerializer<'a> { where S: serde::Serializer, { - let tuple_struct_info = match self.tuple_struct.get_type_info() { + let type_info = get_type_info( + self.tuple_struct.get_type_info(), + self.tuple_struct.type_name(), + self.registry, + )?; + + let tuple_struct_info = match type_info { TypeInfo::TupleStruct(tuple_struct_info) => tuple_struct_info, info => { return Err(Error::custom(format_args!( @@ -253,7 +288,13 @@ impl<'a> Serialize for EnumSerializer<'a> { where S: serde::Serializer, { - let enum_info = match self.enum_value.get_type_info() { + let type_info = get_type_info( + self.enum_value.get_type_info(), + self.enum_value.type_name(), + self.registry, + )?; + + let enum_info = match type_info { TypeInfo::Enum(enum_info) => enum_info, info => { return Err(Error::custom(format_args!( From 43fb3abaa4e9ece3a6a03ede15a9dfa5e83906fb Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 17 Aug 2022 00:13:47 -0700 Subject: [PATCH 31/41] Formatting --- crates/bevy_reflect/src/struct_trait.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index a92a276c677c8..251fb12cb268c 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -94,10 +94,7 @@ impl StructInfo { (name, index) }) .collect::>(); - let field_names = fields - .iter() - .map(|field| field.name()) - .collect::>(); + let field_names = fields.iter().map(|field| field.name()).collect::>(); Self { name, From df99b9625ffe13dd098dba436e85937a5e34e07f Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 17 Aug 2022 17:04:56 -0700 Subject: [PATCH 32/41] Support Option types --- crates/bevy_reflect/src/serde/de.rs | 159 ++++++++++++++++++++++++--- crates/bevy_reflect/src/serde/ser.rs | 88 +++++++++++++-- 2 files changed, 223 insertions(+), 24 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 4f3bf8538feef..cc28903328e67 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -319,15 +319,23 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { Ok(Box::new(dynamic_tuple)) } TypeInfo::Enum(enum_info) => { - let mut dynamic_enum = deserializer.deserialize_enum( - enum_info.name(), - enum_info.variant_names(), - EnumVisitor { + let type_name = enum_info.type_name(); + let mut dynamic_enum = if type_name.starts_with("core::option::Option") { + deserializer.deserialize_option(OptionVisitor { enum_info, registry: self.registry, - }, - )?; - dynamic_enum.set_name(enum_info.type_name().to_string()); + })? + } else { + deserializer.deserialize_enum( + enum_info.name(), + enum_info.variant_names(), + EnumVisitor { + enum_info, + registry: self.registry, + }, + )? + }; + dynamic_enum.set_name(type_name.to_string()); Ok(Box::new(dynamic_enum)) } TypeInfo::Value(_) => { @@ -595,16 +603,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { )? .into(), VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { - let field = tuple_info.field_at(0).unwrap(); - let type_info = - self.registry - .get_type_info(field.type_id()) - .ok_or_else(|| { - Error::custom(format_args!( - "no registration found for type {}", - field.type_name() - )) - })?; + let type_info = get_newtype_info(tuple_info, self.registry)?; let value = variant.newtype_variant_seed(TypedReflectDeserializer { type_info, registry: self.registry, @@ -672,6 +671,54 @@ impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'a> { } } +struct OptionVisitor<'a> { + enum_info: &'static EnumInfo, + registry: &'a TypeRegistry, +} + +impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> { + type Value = DynamicEnum; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + formatter.write_str("reflected option value of type ")?; + formatter.write_str(self.enum_info.type_name()) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let variant_info = self.enum_info.variant("Some").unwrap(); + match variant_info { + VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { + let type_info = get_newtype_info(tuple_info, self.registry)?; + let de = TypedReflectDeserializer { + type_info, + registry: self.registry, + }; + let mut value = DynamicTuple::default(); + value.insert_boxed(de.deserialize(deserializer)?); + let mut option = DynamicEnum::default(); + option.set_variant("Some", value); + Ok(option) + } + info => Err(Error::custom(format_args!( + "invalid variant, expected `Some` but got `{}`", + info.name() + ))), + } + } + + fn visit_none(self) -> Result + where + E: Error, + { + let mut option = DynamicEnum::default(); + option.set_variant("None", ()); + Ok(option) + } +} + fn visit_struct<'de, T, V>( map: &mut V, info: &'static T, @@ -739,6 +786,19 @@ where Ok(tuple) } +fn get_newtype_info( + tuple_info: &'static TupleVariantInfo, + registry: &TypeRegistry, +) -> Result<&'static TypeInfo, E> { + let field = tuple_info.field_at(0).unwrap(); + registry.get_type_info(field.type_id()).ok_or_else(|| { + Error::custom(format_args!( + "no registration found for type {}", + field.type_name() + )) + }) +} + fn get_type_info( type_id: TypeId, type_name: &str, @@ -957,6 +1017,71 @@ mod tests { assert_eq!(expected, output); } + #[test] + fn should_deserialize_option() { + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct OptionTest { + none: Option<()>, + simple: Option, + complex: Option, + } + + let expected = OptionTest { + none: None, + simple: Some(String::from("Hello world!")), + complex: Some(SomeStruct { foo: 123 }), + }; + + let mut registry = get_registry(); + registry.register::(); + registry.register::>(); + + // === Normal === // + let input = r#"{ + "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": ( + none: None, + simple: Some("Hello world!"), + complex: Some(( + foo: 123, + )), + ), + }"#; + + 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 = ::from_reflect(dynamic_output.as_ref()).unwrap(); + assert_eq!(expected, output, "failed to deserialize Options"); + + // === Implicit Some === // + let input = r#" + #![enable(implicit_some)] + { + "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": ( + none: None, + simple: "Hello world!", + complex: ( + foo: 123, + ), + ), + }"#; + + 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 = ::from_reflect(dynamic_output.as_ref()).unwrap(); + assert_eq!( + expected, output, + "failed to deserialize Options with implicit Some" + ); + } + #[test] fn enum_should_deserialize() { #[derive(Reflect)] diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 5832b1e215fe5..8cee449c89744 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -327,7 +327,15 @@ impl<'a> Serialize for EnumSerializer<'a> { match variant_type { VariantType::Unit => { - serializer.serialize_unit_variant(enum_name, variant_index, variant_name) + if self + .enum_value + .type_name() + .starts_with("core::option::Option") + { + serializer.serialize_none() + } else { + serializer.serialize_unit_variant(enum_name, variant_index, variant_name) + } } VariantType::Struct => { let struct_info = match variant_info { @@ -357,12 +365,20 @@ impl<'a> Serialize for EnumSerializer<'a> { } VariantType::Tuple if field_len == 1 => { let field = self.enum_value.field_at(0).unwrap(); - serializer.serialize_newtype_variant( - enum_name, - variant_index, - variant_name, - &TypedReflectSerializer::new(field, self.registry), - ) + if self + .enum_value + .type_name() + .starts_with("core::option::Option") + { + serializer.serialize_some(&TypedReflectSerializer::new(field, self.registry)) + } else { + serializer.serialize_newtype_variant( + enum_name, + variant_index, + variant_name, + &TypedReflectSerializer::new(field, self.registry), + ) + } } VariantType::Tuple => { let mut state = serializer.serialize_tuple_variant( @@ -465,6 +481,7 @@ mod tests { use crate::serde::ReflectSerializer; use crate::{FromReflect, Reflect, ReflectSerialize, TypeRegistry}; use bevy_utils::HashMap; + use ron::extensions::Extensions; use ron::ser::PrettyConfig; use serde::Serialize; use std::f32::consts::PI; @@ -608,6 +625,63 @@ mod tests { assert_eq!(expected, output); } + #[test] + fn should_serialize_option() { + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct OptionTest { + none: Option<()>, + simple: Option, + complex: Option, + } + + let value = OptionTest { + none: None, + simple: Some(String::from("Hello world!")), + complex: Some(SomeStruct { foo: 123 }), + }; + + let registry = get_registry(); + let serializer = ReflectSerializer::new(&value, ®istry); + + // === Normal === // + let config = PrettyConfig::default() + .new_line(String::from("\n")) + .indentor(String::from(" ")); + + let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); + let expected = r#"{ + "bevy_reflect::serde::ser::tests::should_serialize_option::OptionTest": ( + none: None, + simple: Some("Hello world!"), + complex: Some(( + foo: 123, + )), + ), +}"#; + + assert_eq!(expected, output); + + // === Implicit Some === // + let config = PrettyConfig::default() + .new_line(String::from("\n")) + .extensions(Extensions::IMPLICIT_SOME) + .indentor(String::from(" ")); + + let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); + let expected = r#"#![enable(implicit_some)] +{ + "bevy_reflect::serde::ser::tests::should_serialize_option::OptionTest": ( + none: None, + simple: "Hello world!", + complex: ( + foo: 123, + ), + ), +}"#; + + assert_eq!(expected, output); + } + #[test] fn enum_should_serialize() { #[derive(Reflect)] From 509cb9f2b08defd0102c570e638450e135b0c1d1 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 17 Aug 2022 20:10:26 -0700 Subject: [PATCH 33/41] Fix clippy errors --- crates/bevy_reflect/src/enums/enum_trait.rs | 5 +- crates/bevy_reflect/src/enums/variants.rs | 5 +- crates/bevy_reflect/src/fields.rs | 2 +- crates/bevy_reflect/src/serde/de.rs | 73 ++++++++++----------- crates/bevy_reflect/src/serde/ser.rs | 12 ++-- crates/bevy_reflect/src/struct_trait.rs | 5 +- 6 files changed, 44 insertions(+), 58 deletions(-) diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index fb57b4fd8f2a8..12e017dc53877 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -150,10 +150,7 @@ impl EnumInfo { let variant_indices = variants .iter() .enumerate() - .map(|(index, variant)| { - let name = variant.name().clone(); - (name, index) - }) + .map(|(index, variant)| (variant.name(), index)) .collect::>(); let variant_names = variants diff --git a/crates/bevy_reflect/src/enums/variants.rs b/crates/bevy_reflect/src/enums/variants.rs index 5703a376fe2e9..d748eac3c50d5 100644 --- a/crates/bevy_reflect/src/enums/variants.rs +++ b/crates/bevy_reflect/src/enums/variants.rs @@ -137,10 +137,7 @@ impl StructVariantInfo { fields .iter() .enumerate() - .map(|(index, field)| { - let name = field.name().clone(); - (name, index) - }) + .map(|(index, field)| (field.name(), index)) .collect() } } diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index 3e6505b1e22dd..a752fb1fab731 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -21,7 +21,7 @@ impl NamedField { /// The name of the field. pub fn name(&self) -> &'static str { - &self.name + self.name } /// The [type name] of the field. diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index cc28903328e67..52e95c1601f0d 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -586,47 +586,44 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { A: EnumAccess<'de>, { let mut dynamic_enum = DynamicEnum::default(); - match data.variant().unwrap() { - (Ident(variant_name), variant) => { - let variant_info = self.enum_info.variant(&variant_name).ok_or_else(|| { - Error::unknown_variant(&variant_name, self.enum_info.variant_names()) + let (Ident(variant_name), variant) = data.variant().unwrap(); + let variant_info = self + .enum_info + .variant(&variant_name) + .ok_or_else(|| Error::unknown_variant(&variant_name, self.enum_info.variant_names()))?; + let value: DynamicVariant = match variant_info { + VariantInfo::Unit(..) => variant.unit_variant()?.into(), + VariantInfo::Struct(struct_info) => variant + .struct_variant( + struct_info.field_names(), + StructVariantVisitor { + struct_info, + registry: self.registry, + }, + )? + .into(), + VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { + let type_info = get_newtype_info(tuple_info, self.registry)?; + let value = variant.newtype_variant_seed(TypedReflectDeserializer { + type_info, + registry: self.registry, })?; - let value: DynamicVariant = match variant_info { - VariantInfo::Unit(..) => variant.unit_variant()?.into(), - VariantInfo::Struct(struct_info) => variant - .struct_variant( - struct_info.field_names(), - StructVariantVisitor { - struct_info, - registry: self.registry, - }, - )? - .into(), - VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { - let type_info = get_newtype_info(tuple_info, self.registry)?; - let value = variant.newtype_variant_seed(TypedReflectDeserializer { - type_info, - registry: self.registry, - })?; - let mut dynamic_tuple = DynamicTuple::default(); - dynamic_tuple.insert_boxed(value); - dynamic_tuple.into() - } - VariantInfo::Tuple(tuple_info) => variant - .tuple_variant( - tuple_info.field_len(), - TupleVariantVisitor { - tuple_info, - registry: self.registry, - }, - )? - .into(), - }; - - dynamic_enum.set_variant(variant_name, value); + let mut dynamic_tuple = DynamicTuple::default(); + dynamic_tuple.insert_boxed(value); + dynamic_tuple.into() } - } + VariantInfo::Tuple(tuple_info) => variant + .tuple_variant( + tuple_info.field_len(), + TupleVariantVisitor { + tuple_info, + registry: self.registry, + }, + )? + .into(), + }; + dynamic_enum.set_variant(variant_name, value); Ok(dynamic_enum) } } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 8cee449c89744..10291bb8bef2d 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -55,12 +55,10 @@ fn get_type_info( match type_info { TypeInfo::Dynamic(..) => match registry.get_with_name(type_name) { Some(registration) => Ok(registration.type_info()), - None => { - return Err(Error::custom(format_args!( - "no registration found for dynamic type with name {}", - type_name - ))) - } + None => Err(Error::custom(format_args!( + "no registration found for dynamic type with name {}", + type_name + ))), }, info => Ok(info), } @@ -223,7 +221,7 @@ impl<'a> Serialize for StructSerializer<'a> { continue; } let key = struct_info.field_at(index).unwrap().name(); - state.serialize_field(&key, &TypedReflectSerializer::new(value, self.registry))?; + state.serialize_field(key, &TypedReflectSerializer::new(value, self.registry))?; } state.end() } diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 251fb12cb268c..502825f45a0aa 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -89,10 +89,7 @@ impl StructInfo { let field_indices = fields .iter() .enumerate() - .map(|(index, field)| { - let name = field.name().clone(); - (name, index) - }) + .map(|(index, field)| (field.name(), index)) .collect::>(); let field_names = fields.iter().map(|field| field.name()).collect::>(); From 61a742bc4b1d93b2e7342e42047463d4c795f198 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 17 Aug 2022 20:11:42 -0700 Subject: [PATCH 34/41] Fix glam tests --- crates/bevy_reflect/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 784e2fa189b89..a9e57d3fbfac0 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -968,11 +968,11 @@ bevy_reflect::tests::should_reflect_debug::Test { let output = to_string_pretty(&ser, config).unwrap(); let expected = r#" { - "glam::f32::vec3::Vec3": { - "x": 12.0, - "y": 3.0, - "z": -6.9, - }, + "glam::f32::vec3::Vec3": ( + x: 12.0, + y: 3.0, + z: -6.9, + ), }"#; assert_eq!(expected, format!("\n{}", output)); @@ -982,11 +982,11 @@ bevy_reflect::tests::should_reflect_debug::Test { fn vec3_deserialization() { let data = r#" { - "glam::f32::vec3::Vec3": { - "x": 12.0, - "y": 3.0, - "z": -6.9, - }, + "glam::f32::vec3::Vec3": ( + x: 12.0, + y: 3.0, + z: -6.9, + ), }"#; let mut registry = TypeRegistry::default(); From 070e50947b0cc8868668ede632ecfbbb3dc01af7 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 31 Aug 2022 22:33:15 -0700 Subject: [PATCH 35/41] Remove unnecessary Into --- crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs | 2 +- crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs | 2 +- crates/bevy_reflect/src/fields.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index 661ae3bee354a..7dd2fcd3857cd 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -343,7 +343,7 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden }); let field_ty = &field.data.ty; - quote! { #bevy_reflect_path::NamedField::new::<#field_ty, _>(#field_name) } + quote! { #bevy_reflect_path::NamedField::new::<#field_ty>(#field_name) } }); let arguments = quote!(#name, &[ #(#argument),* ]); add_fields_branch("Struct", "StructVariantInfo", arguments, field_len); diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs index aaffe40988ac7..c68aab2e2d4c3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -57,7 +57,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { reflect_struct.meta().generics(), quote! { let fields = [ - #(#bevy_reflect_path::NamedField::new::<#field_types, _>(#field_names),)* + #(#bevy_reflect_path::NamedField::new::<#field_types>(#field_names),)* ]; let info = #bevy_reflect_path::StructInfo::new::(#string_name, &fields); #bevy_reflect_path::TypeInfo::Struct(info) diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index a752fb1fab731..f70e5c4c686d4 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -11,9 +11,9 @@ pub struct NamedField { impl NamedField { /// Create a new [`NamedField`]. - pub fn new>(name: TName) -> Self { + pub fn new(name: &'static str) -> Self { Self { - name: name.into(), + name, type_name: std::any::type_name::(), type_id: TypeId::of::(), } From 320d9e4fd7f17d0ea0ac9feca4881a44a050df99 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 31 Aug 2022 22:56:58 -0700 Subject: [PATCH 36/41] Fix getting registration for type twice --- crates/bevy_reflect/src/serde/de.rs | 102 +++++++++++++--------------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 52e95c1601f0d..a119987d017d1 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -3,7 +3,8 @@ use crate::{ ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField, Reflect, ReflectDeserialize, StructInfo, StructVariantInfo, Tuple, TupleInfo, TupleStruct, - TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistry, UnnamedField, VariantInfo, + TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, UnnamedField, + VariantInfo, }; use erased_serde::Deserializer; use serde::de::{ @@ -193,11 +194,10 @@ impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { .ok_or_else(|| Error::invalid_length(0, &"at least one entry"))?; let registration = self.registry.get_with_name(&type_name).ok_or_else(|| { - Error::custom(format_args!("No registration found for {}", type_name)) + 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, + registration, registry: self.registry, })?; Ok(value) @@ -223,14 +223,14 @@ impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { /// [`DynamicList`]: crate::DynamicList /// [`FromReflect`]: crate::FromReflect pub struct TypedReflectDeserializer<'a> { - type_info: &'static TypeInfo, + registration: &'a TypeRegistration, registry: &'a TypeRegistry, } impl<'a> TypedReflectDeserializer<'a> { - pub fn new(type_info: &'static TypeInfo, registry: &'a TypeRegistry) -> Self { + pub fn new(registration: &'a TypeRegistration, registry: &'a TypeRegistry) -> Self { Self { - type_info, + registration, registry, } } @@ -243,19 +243,15 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { where D: serde::Deserializer<'de>, { - // 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)) - })?; + let type_name = self.registration.type_name(); - if let Some(deserialize_reflect) = registration.data::() { + // Handle both Value case and types that have a custom `ReflectDeserialize` + if let Some(deserialize_reflect) = self.registration.data::() { let value = deserialize_reflect.deserialize(deserializer)?; return Ok(value); } - match self.type_info { + match self.registration.type_info() { TypeInfo::Struct(struct_info) => { let mut dynamic_struct = deserializer.deserialize_struct( struct_info.name(), @@ -396,7 +392,7 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { let mut index = 0usize; let mut tuple_struct = DynamicTupleStruct::default(); - let get_field_info = |index: usize| -> Result<&'static TypeInfo, V::Error> { + let get_field_registration = |index: usize| -> Result<&'a TypeRegistration, 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 {}", @@ -404,11 +400,11 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { self.tuple_struct_info.type_name(), )) })?; - get_type_info(field.type_id(), field.type_name(), self.registry) + get_registration(field.type_id(), field.type_name(), self.registry) }; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { - type_info: get_field_info(index)?, + registration: get_field_registration(index)?, registry: self.registry, })? { tuple_struct.insert_boxed(value); @@ -472,13 +468,13 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { V: SeqAccess<'de>, { let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default()); - let type_info = get_type_info( + let registration = get_registration( 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, + registration, registry: self.registry, })? { vec.push(value); @@ -512,13 +508,13 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { V: SeqAccess<'de>, { let mut list = DynamicList::default(); - let type_info = get_type_info( + let registration = get_registration( 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, + registration, registry: self.registry, })? { list.push_box(value); @@ -544,22 +540,22 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { V: MapAccess<'de>, { let mut dynamic_map = DynamicMap::default(); - let key_type_info = get_type_info( + let key_registration = get_registration( self.map_info.key_type_id(), self.map_info.key_type_name(), self.registry, )?; - let value_type_info = get_type_info( + let value_registration = get_registration( 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, + registration: key_registration, registry: self.registry, })? { let value = map.next_value_seed(TypedReflectDeserializer { - type_info: value_type_info, + registration: value_registration, registry: self.registry, })?; dynamic_map.insert_boxed(key, value); @@ -603,9 +599,11 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { )? .into(), VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { - let type_info = get_newtype_info(tuple_info, self.registry)?; + let field = tuple_info.field_at(0).unwrap(); + let registration = + get_registration(field.type_id(), field.type_name(), self.registry)?; let value = variant.newtype_variant_seed(TypedReflectDeserializer { - type_info, + registration, registry: self.registry, })?; let mut dynamic_tuple = DynamicTuple::default(); @@ -688,9 +686,11 @@ impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> { let variant_info = self.enum_info.variant("Some").unwrap(); match variant_info { VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { - let type_info = get_newtype_info(tuple_info, self.registry)?; + let field = tuple_info.field_at(0).unwrap(); + let registration = + get_registration(field.type_id(), field.type_name(), self.registry)?; let de = TypedReflectDeserializer { - type_info, + registration, registry: self.registry, }; let mut value = DynamicTuple::default(); @@ -730,9 +730,9 @@ where let field = info .get_field(&key) .ok_or_else(|| Error::unknown_field(&key, info.get_field_names()))?; - let type_info = get_type_info(field.type_id(), field.type_name(), registry)?; + let registration = get_registration(field.type_id(), field.type_name(), registry)?; let value = map.next_value_seed(TypedReflectDeserializer { - type_info, + registration, registry, })?; dynamic_struct.insert_boxed(&key, value); @@ -753,15 +753,15 @@ where let mut tuple = DynamicTuple::default(); let mut index = 0usize; - let get_field_info = |index: usize| -> Result<&TypeInfo, V::Error> { + let get_field_registration = |index: usize| -> Result<&TypeRegistration, V::Error> { let field = info.get_field(index).ok_or_else(|| { Error::invalid_length(index, &info.get_field_len().to_string().as_str()) })?; - get_type_info(field.type_id(), field.type_name(), registry) + get_registration(field.type_id(), field.type_name(), registry) }; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { - type_info: get_field_info(index)?, + registration: get_field_registration(index)?, registry, })? { tuple.insert_boxed(value); @@ -783,32 +783,23 @@ where Ok(tuple) } -fn get_newtype_info( - tuple_info: &'static TupleVariantInfo, - registry: &TypeRegistry, -) -> Result<&'static TypeInfo, E> { - let field = tuple_info.field_at(0).unwrap(); - registry.get_type_info(field.type_id()).ok_or_else(|| { - Error::custom(format_args!( - "no registration found for type {}", - field.type_name() - )) - }) -} - -fn get_type_info( +fn get_registration<'a, E: Error>( type_id: TypeId, type_name: &str, - registry: &TypeRegistry, -) -> Result<&'static TypeInfo, E> { + registry: &'a TypeRegistry, +) -> Result<&'a TypeRegistration, E> { let registration = registry.get(type_id).ok_or_else(|| { - de::Error::custom(format_args!("no registration found for type {}", type_name)) + Error::custom(format_args!( + "no registration found for type `{}`", + type_name + )) })?; - Ok(registration.type_info()) + Ok(registration) } #[cfg(test)] mod tests { + use std::any::TypeId; use std::f32::consts::PI; use serde::de::DeserializeSeed; @@ -818,7 +809,7 @@ mod tests { use crate as bevy_reflect; use crate::serde::{TypedReflectDeserializer, UntypedReflectDeserializer}; - use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry, Typed}; + use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry}; #[derive(Reflect, FromReflect, Debug, PartialEq)] struct MyStruct { @@ -1004,7 +995,8 @@ mod tests { let mut registry = get_registry(); registry.register::(); - let reflect_deserializer = TypedReflectDeserializer::new(Foo::type_info(), ®istry); + let registration = registry.get(TypeId::of::()).unwrap(); + let reflect_deserializer = TypedReflectDeserializer::new(registration, ®istry); let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap(); let dynamic_output = reflect_deserializer .deserialize(&mut ron_deserializer) From 1d34ea5c2aeaad72298feab39215c26a66ddbfb6 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Wed, 31 Aug 2022 23:14:50 -0700 Subject: [PATCH 37/41] Added Enum::variant_index --- .../bevy_reflect_derive/src/impls/enums.rs | 24 +++++++-- crates/bevy_reflect/src/enums/dynamic_enum.rs | 51 +++++++++++++++++-- crates/bevy_reflect/src/enums/enum_trait.rs | 2 + crates/bevy_reflect/src/impls/std.rs | 7 +++ crates/bevy_reflect/src/serde/ser.rs | 15 ++---- 5 files changed, 81 insertions(+), 18 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index 7dd2fcd3857cd..8a7afb792eef0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -21,6 +21,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { enum_name_at, enum_field_len, enum_variant_name, + enum_variant_index, enum_variant_type, } = generate_impls(reflect_enum, &ref_index, &ref_name); @@ -137,6 +138,14 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } } + #[inline] + fn variant_index(&self) -> usize { + match self { + #(#enum_variant_index,)* + _ => unreachable!(), + } + } + #[inline] fn variant_type(&self) -> #bevy_reflect_path::VariantType { match self { @@ -255,6 +264,7 @@ struct EnumImpls { enum_name_at: Vec, enum_field_len: Vec, enum_variant_name: Vec, + enum_variant_index: Vec, enum_variant_type: Vec, } @@ -268,13 +278,21 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden let mut enum_name_at = Vec::new(); let mut enum_field_len = Vec::new(); let mut enum_variant_name = Vec::new(); + let mut enum_variant_index = Vec::new(); let mut enum_variant_type = Vec::new(); - for variant in reflect_enum.variants() { + for (variant_index, variant) in reflect_enum.variants().iter().enumerate() { let ident = &variant.data.ident; let name = ident.to_string(); let unit = reflect_enum.get_unit(ident); + enum_variant_name.push(quote! { + #unit{..} => #name + }); + enum_variant_index.push(quote! { + #unit{..} => #variant_index + }); + fn for_fields( fields: &[StructField], mut generate_for_field: impl FnMut(usize, usize, &StructField) -> proc_macro2::TokenStream, @@ -302,9 +320,6 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden enum_field_len.push(quote! { #unit{..} => #field_len }); - enum_variant_name.push(quote! { - #unit{..} => #name - }); enum_variant_type.push(quote! { #unit{..} => #bevy_reflect_path::VariantType::#variant }); @@ -359,6 +374,7 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden enum_name_at, enum_field_len, enum_variant_name, + enum_variant_index, enum_variant_type, } } diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index cc07b5c5282d9..e0ad08a689406 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -77,6 +77,7 @@ impl From<()> for DynamicVariant { pub struct DynamicEnum { name: String, variant_name: String, + variant_index: usize, variant: DynamicVariant, } @@ -96,6 +97,30 @@ impl DynamicEnum { ) -> Self { Self { name: name.into(), + variant_index: 0, + variant_name: variant_name.into(), + variant: variant.into(), + } + } + + /// Create a new [`DynamicEnum`] with a variant index to represent an enum at runtime. + /// + /// # Arguments + /// + /// * `name`: The type name of the enum + /// * `variant_index`: The index of the variant to set + /// * `variant_name`: The name of the variant to set + /// * `variant`: The variant data + /// + pub fn new_with_index, V: Into>( + name: I, + variant_index: usize, + variant_name: I, + variant: V, + ) -> Self { + Self { + name: name.into(), + variant_index, variant_name: variant_name.into(), variant: variant.into(), } @@ -117,6 +142,18 @@ impl DynamicEnum { self.variant = variant.into(); } + /// Set the current enum variant represented by this struct along with its variant index. + pub fn set_variant_with_index, V: Into>( + &mut self, + variant_index: usize, + name: I, + variant: V, + ) { + self.variant_index = variant_index; + self.variant_name = name.into(); + self.variant = variant.into(); + } + /// Create a [`DynamicEnum`] from an existing one. /// /// This is functionally the same as [`DynamicEnum::from_ref`] except it takes an owned value. @@ -129,8 +166,9 @@ impl DynamicEnum { /// This is functionally the same as [`DynamicEnum::from`] except it takes a reference. pub fn from_ref(value: &TEnum) -> Self { match value.variant_type() { - VariantType::Unit => DynamicEnum::new( + VariantType::Unit => DynamicEnum::new_with_index( value.type_name(), + value.variant_index(), value.variant_name(), DynamicVariant::Unit, ), @@ -139,8 +177,9 @@ impl DynamicEnum { for field in value.iter_fields() { data.insert_boxed(field.value().clone_value()); } - DynamicEnum::new( + DynamicEnum::new_with_index( value.type_name(), + value.variant_index(), value.variant_name(), DynamicVariant::Tuple(data), ) @@ -151,8 +190,9 @@ impl DynamicEnum { let name = field.name().unwrap(); data.insert_boxed(name, field.value().clone_value()); } - DynamicEnum::new( + DynamicEnum::new_with_index( value.type_name(), + value.variant_index(), value.variant_name(), DynamicVariant::Struct(data), ) @@ -226,6 +266,10 @@ impl Enum for DynamicEnum { &self.variant_name } + fn variant_index(&self) -> usize { + self.variant_index + } + fn variant_type(&self) -> VariantType { match &self.variant { DynamicVariant::Unit => VariantType::Unit, @@ -237,6 +281,7 @@ impl Enum for DynamicEnum { fn clone_dynamic(&self) -> DynamicEnum { Self { name: self.name.clone(), + variant_index: self.variant_index, variant_name: self.variant_name.clone(), variant: self.variant.clone(), } diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index 12e017dc53877..d4650e958785c 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -113,6 +113,8 @@ pub trait Enum: Reflect { fn field_len(&self) -> usize; /// The name of the current variant. fn variant_name(&self) -> &str; + /// The index of the current variant. + fn variant_index(&self) -> usize; /// The type of the current variant. fn variant_type(&self) -> VariantType; // Clones the enum into a [`DynamicEnum`]. diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index a5f6816cd1e3f..6b6be3e4b245f 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -682,6 +682,13 @@ impl Enum for Option { } } + fn variant_index(&self) -> usize { + match self { + None => 0, + Some(..) => 1, + } + } + #[inline] fn variant_type(&self) -> VariantType { match self { diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 10291bb8bef2d..8425f1e0a015b 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -303,22 +303,15 @@ impl<'a> Serialize for EnumSerializer<'a> { }; let enum_name = enum_info.name(); + let variant_index = self.enum_value.variant_index() as u32; let variant_info = enum_info - .variant(self.enum_value.variant_name()) + .variant_at(variant_index as usize) .ok_or_else(|| { Error::custom(format_args!( - "variant `{}` does not exist", - self.enum_value.variant_name() + "variant at index `{}` does not exist", + variant_index )) })?; - let variant_index = enum_info - .index_of(self.enum_value.variant_name()) - .ok_or_else(|| { - Error::custom(format_args!( - "variant `{}` does not exist", - self.enum_value.variant_name() - )) - })? as u32; let variant_name = variant_info.name(); let variant_type = self.enum_value.variant_type(); let field_len = self.enum_value.field_len(); From 265cc30584fdaa2bc90bc98fa55c9eae72acdfb0 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Thu, 1 Sep 2022 00:41:16 -0700 Subject: [PATCH 38/41] Remove duplicate field_names/variant_names fields --- crates/bevy_reflect/src/enums/enum_trait.rs | 12 ---- crates/bevy_reflect/src/enums/variants.rs | 8 --- crates/bevy_reflect/src/serde/de.rs | 78 ++++++++++++++++----- crates/bevy_reflect/src/struct_trait.rs | 8 --- 4 files changed, 62 insertions(+), 44 deletions(-) diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index d4650e958785c..ab3fd03dd05e1 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -136,7 +136,6 @@ pub struct EnumInfo { type_name: &'static str, type_id: TypeId, variants: Box<[VariantInfo]>, - variant_names: Box<[&'static str]>, variant_indices: HashMap<&'static str, usize>, } @@ -155,17 +154,11 @@ impl EnumInfo { .map(|(index, variant)| (variant.name(), index)) .collect::>(); - let variant_names = variants - .iter() - .map(|variant| variant.name()) - .collect::>(); - Self { name, type_name: std::any::type_name::(), type_id: TypeId::of::(), variants: variants.to_vec().into_boxed_slice(), - variant_names: variant_names.into_boxed_slice(), variant_indices, } } @@ -177,11 +170,6 @@ impl EnumInfo { .map(|index| &self.variants[*index]) } - /// A slice containing the names of all variants in order. - pub fn variant_names(&self) -> &[&'static str] { - &self.variant_names - } - /// Get a variant at the given index. pub fn variant_at(&self, index: usize) -> Option<&VariantInfo> { self.variants.get(index) diff --git a/crates/bevy_reflect/src/enums/variants.rs b/crates/bevy_reflect/src/enums/variants.rs index d748eac3c50d5..d00c0a9c49c78 100644 --- a/crates/bevy_reflect/src/enums/variants.rs +++ b/crates/bevy_reflect/src/enums/variants.rs @@ -79,7 +79,6 @@ impl VariantInfo { pub struct StructVariantInfo { name: &'static str, fields: Box<[NamedField]>, - field_names: Box<[&'static str]>, field_indices: HashMap<&'static str, usize>, } @@ -87,11 +86,9 @@ impl StructVariantInfo { /// Create a new [`StructVariantInfo`]. pub fn new(name: &'static str, fields: &[NamedField]) -> Self { let field_indices = Self::collect_field_indices(fields); - let field_names = fields.iter().map(|field| field.name()).collect::>(); Self { name, fields: fields.to_vec().into_boxed_slice(), - field_names: field_names.into_boxed_slice(), field_indices, } } @@ -108,11 +105,6 @@ impl StructVariantInfo { .map(|index| &self.fields[*index]) } - /// A slice containing the names of all fields in order. - pub fn field_names(&self) -> &[&'static str] { - &self.field_names - } - /// Get the field at the given index. pub fn field_at(&self, index: usize) -> Option<&NamedField> { self.fields.get(index) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index a119987d017d1..8b84590e29064 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -13,7 +13,8 @@ use serde::de::{ use serde::Deserialize; use std::any::TypeId; use std::fmt; -use std::fmt::Formatter; +use std::fmt::{Debug, Display, Formatter}; +use std::slice::Iter; pub trait DeserializeValue { fn deserialize( @@ -25,7 +26,7 @@ pub trait DeserializeValue { trait StructLikeInfo { fn get_name(&self) -> &str; fn get_field(&self, name: &str) -> Option<&NamedField>; - fn get_field_names(&self) -> &[&'static str]; + fn iter_fields(&self) -> Iter<'_, NamedField>; } trait TupleLikeInfo { @@ -43,8 +44,8 @@ impl StructLikeInfo for StructInfo { self.field(name) } - fn get_field_names(&self) -> &[&'static str] { - self.field_names() + fn iter_fields(&self) -> Iter<'_, NamedField> { + self.iter() } } @@ -57,8 +58,8 @@ impl StructLikeInfo for StructVariantInfo { self.field(name) } - fn get_field_names(&self) -> &[&'static str] { - self.field_names() + fn iter_fields(&self) -> Iter<'_, NamedField> { + self.iter() } } @@ -90,6 +91,39 @@ impl TupleLikeInfo for TupleVariantInfo { } } +/// A debug struct used for error messages that displays a list of expected values. +/// +/// # Example +/// +/// ```ignore +/// let expected = vec!["foo", "bar", "baz"]; +/// assert_eq!("`foo`, `bar`, `baz`", format!("{}", ExpectedValues(expected))); +/// ``` +struct ExpectedValues(TIntoIter) +where + TIntoIter: IntoIterator + Clone, + TIter: Iterator + ExactSizeIterator, + TItem: Display; + +impl Debug for ExpectedValues +where + TIntoIter: IntoIterator + Clone, + TIter: Iterator + ExactSizeIterator, + TItem: Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let iter = self.0.clone().into_iter(); + let len = iter.len(); + for (index, item) in iter.enumerate() { + write!(f, "`{}`", item)?; + if index < len - 1 { + write!(f, ", ")?; + } + } + Ok(()) + } +} + /// Represents a simple reflected identifier. #[derive(Debug, Clone, Eq, PartialEq)] struct Ident(String); @@ -255,7 +289,8 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { TypeInfo::Struct(struct_info) => { let mut dynamic_struct = deserializer.deserialize_struct( struct_info.name(), - struct_info.field_names(), + // Field names are mainly just a hint, we don't necessarily need to store and pass that data + &[], StructVisitor { struct_info, registry: self.registry, @@ -324,7 +359,8 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { } else { deserializer.deserialize_enum( enum_info.name(), - enum_info.variant_names(), + // Variant names are mainly just a hint, we don't necessarily need to store and pass that data + &[], EnumVisitor { enum_info, registry: self.registry, @@ -583,15 +619,20 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { { let mut dynamic_enum = DynamicEnum::default(); let (Ident(variant_name), variant) = data.variant().unwrap(); - let variant_info = self - .enum_info - .variant(&variant_name) - .ok_or_else(|| Error::unknown_variant(&variant_name, self.enum_info.variant_names()))?; + let variant_info = self.enum_info.variant(&variant_name).ok_or_else(|| { + let names = self.enum_info.iter().map(|variant| variant.name()); + Error::custom(format_args!( + "unknown variant `{}`, expected one of {:?}", + variant_name, + ExpectedValues(names) + )) + })?; let value: DynamicVariant = match variant_info { VariantInfo::Unit(..) => variant.unit_variant()?.into(), VariantInfo::Struct(struct_info) => variant .struct_variant( - struct_info.field_names(), + // Field names are mainly just a hint, we don't necessarily need to store and pass that data + &[], StructVariantVisitor { struct_info, registry: self.registry, @@ -727,9 +768,14 @@ where { let mut dynamic_struct = DynamicStruct::default(); while let Some(Ident(key)) = map.next_key::()? { - let field = info - .get_field(&key) - .ok_or_else(|| Error::unknown_field(&key, info.get_field_names()))?; + let field = info.get_field(&key).ok_or_else(|| { + let fields = info.iter_fields().map(|field| field.name()); + Error::custom(format_args!( + "unknown field `{}`, expected one of {:?}", + key, + ExpectedValues(fields) + )) + })?; let registration = get_registration(field.type_id(), field.type_name(), registry)?; let value = map.next_value_seed(TypedReflectDeserializer { registration, diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 502825f45a0aa..f246b7128cc35 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -73,7 +73,6 @@ pub struct StructInfo { type_name: &'static str, type_id: TypeId, fields: Box<[NamedField]>, - field_names: Box<[&'static str]>, field_indices: HashMap<&'static str, usize>, } @@ -91,13 +90,11 @@ impl StructInfo { .enumerate() .map(|(index, field)| (field.name(), index)) .collect::>(); - let field_names = fields.iter().map(|field| field.name()).collect::>(); Self { name, type_name: std::any::type_name::(), type_id: TypeId::of::(), - field_names: field_names.into_boxed_slice(), fields: fields.to_vec().into_boxed_slice(), field_indices, } @@ -110,11 +107,6 @@ impl StructInfo { .map(|index| &self.fields[*index]) } - /// A slice containing the names of all fields in order. - pub fn field_names(&self) -> &[&'static str] { - &self.field_names - } - /// Get the field at the given index. pub fn field_at(&self, index: usize) -> Option<&NamedField> { self.fields.get(index) From 6430af4d854726fcd81ee6f16bd689b833787e3f Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Thu, 1 Sep 2022 00:44:59 -0700 Subject: [PATCH 39/41] Simplify ExpectedValues struct --- crates/bevy_reflect/src/serde/de.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 8b84590e29064..dcc891b1c4829 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -99,22 +99,12 @@ impl TupleLikeInfo for TupleVariantInfo { /// let expected = vec!["foo", "bar", "baz"]; /// assert_eq!("`foo`, `bar`, `baz`", format!("{}", ExpectedValues(expected))); /// ``` -struct ExpectedValues(TIntoIter) -where - TIntoIter: IntoIterator + Clone, - TIter: Iterator + ExactSizeIterator, - TItem: Display; +struct ExpectedValues(Vec); -impl Debug for ExpectedValues -where - TIntoIter: IntoIterator + Clone, - TIter: Iterator + ExactSizeIterator, - TItem: Display, -{ +impl Debug for ExpectedValues { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let iter = self.0.clone().into_iter(); - let len = iter.len(); - for (index, item) in iter.enumerate() { + let len = self.0.len(); + for (index, item) in self.0.iter().enumerate() { write!(f, "`{}`", item)?; if index < len - 1 { write!(f, ", ")?; @@ -624,7 +614,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { Error::custom(format_args!( "unknown variant `{}`, expected one of {:?}", variant_name, - ExpectedValues(names) + ExpectedValues(names.collect()) )) })?; let value: DynamicVariant = match variant_info { @@ -773,7 +763,7 @@ where Error::custom(format_args!( "unknown field `{}`, expected one of {:?}", key, - ExpectedValues(fields) + ExpectedValues(fields.collect()) )) })?; let registration = get_registration(field.type_id(), field.type_name(), registry)?; From fe2ee1c7e3bbb50baf63402e85c48e3800e724a0 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 4 Sep 2022 19:29:45 -0700 Subject: [PATCH 40/41] Fix doc error --- crates/bevy_reflect/src/type_info.rs | 4 ++-- crates/bevy_reflect/src/utility.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index a954082f9b9c6..9e5519d500ad6 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -37,8 +37,8 @@ use std::any::{Any, TypeId}; /// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); /// CELL.get_or_set(|| { /// let fields = [ -/// NamedField::new::("foo"), -/// NamedField::new::<(f32, f32), _>("bar"), +/// NamedField::new::("foo"), +/// NamedField::new::<(f32, f32) >("bar"), /// ]; /// let info = StructInfo::new::("MyStruct", &fields); /// TypeInfo::Struct(info) diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index c11d2a08cf7b5..1c331978f3f78 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -27,7 +27,7 @@ use std::any::{Any, TypeId}; /// fn type_info() -> &'static TypeInfo { /// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); /// CELL.get_or_set(|| { -/// let fields = [NamedField::new::("bar")]; +/// let fields = [NamedField::new::("bar")]; /// let info = StructInfo::new::("Foo", &fields); /// TypeInfo::Struct(info) /// }) From 8f6ed3218dc8b6305d4f8dfd271cc10e9536b1df Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Tue, 20 Sep 2022 12:27:49 -0700 Subject: [PATCH 41/41] Pass in TypeRegistration to cut out redundant lookup --- crates/bevy_reflect/src/serde/de.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index dcc891b1c4829..d0f03d0f8631b 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -296,6 +296,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { TupleStructVisitor { tuple_struct_info, registry: self.registry, + registration: self.registration, }, )?; dynamic_tuple_struct.set_name(tuple_struct_info.type_name().to_string()); @@ -402,6 +403,7 @@ impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { struct TupleStructVisitor<'a> { tuple_struct_info: &'static TupleStructInfo, registry: &'a TypeRegistry, + registration: &'a TypeRegistration, } impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { @@ -441,9 +443,8 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { } let ignored_len = self - .registry - .get(self.tuple_struct_info.type_id()) - .and_then(|registration| registration.data::()) + .registration + .data::() .map(|data| data.len()) .unwrap_or(0); if tuple_struct.field_len() != self.tuple_struct_info.field_len() - ignored_len {