diff --git a/assets/scenes/load_scene_example.scn.ron b/assets/scenes/load_scene_example.scn.ron index 338084e9671b6..015b41774f3c0 100644 --- a/assets/scenes/load_scene_example.scn.ron +++ b/assets/scenes/load_scene_example.scn.ron @@ -3,43 +3,30 @@ 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), - }, - }, + "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 + ), + ), }, { - "type": "scene::ComponentB", - "struct": { - "value": { - "type": "alloc::string::String", - "value": "hello", - }, - }, + "scene::ComponentB": ( + value: "hello", + ), }, { - "type": "scene::ComponentA", - "struct": { - "x": { - "type": "f32", - "value": 1.0, - }, - "y": { - "type": "f32", - "value": 2.0, - }, - }, + "scene::ComponentA": ( + x: 1.0, + y: 2.0, + ), }, ], ), @@ -47,17 +34,10 @@ entity: 1, components: [ { - "type": "scene::ComponentA", - "struct": { - "x": { - "type": "f32", - "value": 3.0, - }, - "y": { - "type": "f32", - "value": 4.0, - }, - }, + "scene::ComponentA": ( + x: 3.0, + y: 4.0, + ), }, ], ), 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..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); @@ -53,12 +54,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, @@ -136,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 { @@ -254,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, } @@ -267,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, @@ -301,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 }); @@ -342,7 +358,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); @@ -358,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/bevy_reflect_derive/src/impls/structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs index f47dddf6536b0..c68aab2e2d4c3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -51,14 +51,15 @@ 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(), 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::(&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/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/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 9ee110d8f0a05..ab3fd03dd05e1 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. @@ -114,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`]. @@ -131,10 +132,11 @@ 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_indices: HashMap<&'static str, usize>, } impl EnumInfo { @@ -142,19 +144,18 @@ 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() - .map(|(index, variant)| { - let name = variant.name().clone(); - (name, index) - }) + .map(|(index, variant)| (variant.name(), index)) .collect::>(); Self { + name, type_name: std::any::type_name::(), type_id: TypeId::of::(), variants: variants.to_vec().into_boxed_slice(), @@ -201,6 +202,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..d00c0a9c49c78 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,25 @@ 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_indices: HashMap<&'static str, usize>, } impl StructVariantInfo { /// Create a new [`StructVariantInfo`]. - pub fn new(name: &str, fields: &[NamedField]) -> Self { + pub fn new(name: &'static 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 { - let field_indices = Self::collect_field_indices(fields); - Self { - name: Cow::Borrowed(name), + name, fields: fields.to_vec().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. @@ -140,14 +125,11 @@ 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() - .map(|(index, field)| { - let name = field.name().clone(); - (name, index) - }) + .map(|(index, field)| (field.name(), index)) .collect() } } @@ -155,33 +137,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 +174,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..f70e5c4c686d4 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,28 +1,27 @@ 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: &'static str) -> Self { Self { - name: name.into(), + name, type_name: std::any::type_name::(), type_id: TypeId::of::(), } } /// The name of the field. - pub fn name(&self) -> &Cow<'static, str> { - &self.name + pub fn name(&self) -> &'static str { + self.name } /// The [type name] of the field. 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/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 0c021ba8c4c35..1d7acbabf096a 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -683,6 +683,13 @@ impl Enum for Option { } } + fn variant_index(&self) -> usize { + match self { + None => 0, + Some(..) => 1, + } + } + #[inline] fn variant_type(&self) -> VariantType { match self { @@ -845,12 +852,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/lib.rs b/crates/bevy_reflect/src/lib.rs index 07c1cd0ec1ca0..a9e57d3fbfac0 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}, @@ -108,7 +108,7 @@ mod tests { use super::prelude::*; use super::*; use crate as bevy_reflect; - use crate::serde::{ReflectDeserializer, ReflectSerializer}; + use crate::serde::{ReflectSerializer, UntypedReflectDeserializer}; #[test] fn reflect_struct() { @@ -455,7 +455,8 @@ mod tests { h: [u32; 2], } - #[derive(Reflect)] + #[derive(Reflect, Serialize, Deserialize)] + #[reflect(Serialize, Deserialize)] struct Bar { x: u32, } @@ -476,18 +477,23 @@ 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(); 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(); @@ -956,23 +962,38 @@ 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 config = PrettyConfig::default() + .new_line(String::from("\n")) + .indentor(String::from(" ")); + let output = to_string_pretty(&ser, config).unwrap(); + let expected = r#" +{ + "glam::f32::vec3::Vec3": ( + x: 12.0, + y: 3.0, + z: -6.9, + ), +}"#; - assert_eq!( - result, - r#"{"type":"glam::f32::vec3::Vec3","struct":{"x":{"type":"f32","value":12.0},"y":{"type":"f32","value":3.0},"z":{"type":"f32","value":-6.9}}}"# - ); + assert_eq!(expected, format!("\n{}", output)); } #[test] fn vec3_deserialization() { - let data = r#"{"type":"glam::vec3::Vec3","struct":{"x":{"type":"f32","value":12},"y":{"type":"f32","value":3},"z":{"type":"f32","value":-6.9}}}"#; + let data = r#" +{ + "glam::f32::vec3::Vec3": ( + x: 12.0, + y: 3.0, + z: -6.9, + ), +}"#; let mut registry = TypeRegistry::default(); 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 ad24185de15f3..d0f03d0f8631b 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,9 +1,20 @@ +use crate::serde::SerializationData; use crate::{ - serde::type_fields, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, - DynamicTuple, DynamicTupleStruct, Map, Reflect, ReflectDeserialize, TypeRegistry, + ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, + DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField, Reflect, + ReflectDeserialize, StructInfo, StructVariantInfo, Tuple, TupleInfo, TupleStruct, + TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, 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::{Debug, Display, Formatter}; +use std::slice::Iter; pub trait DeserializeValue { fn deserialize( @@ -12,321 +23,471 @@ 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>; + fn iter_fields(&self) -> Iter<'_, 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; +impl StructLikeInfo for StructInfo { + fn get_name(&self) -> &str { + self.type_name() + } - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(ReflectVisitor { - registry: self.registry, - }) + fn get_field(&self, name: &str) -> Option<&NamedField> { + self.field(name) } -} -struct ReflectVisitor<'a> { - registry: &'a TypeRegistry, + fn iter_fields(&self) -> Iter<'_, NamedField> { + self.iter() + } } -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)) + fn iter_fields(&self) -> Iter<'_, NamedField> { + self.iter() } +} - fn visit_u16(self, v: u16) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) +impl TupleLikeInfo for TupleInfo { + fn get_name(&self) -> &str { + self.type_name() } - fn visit_u32(self, v: u32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field(&self, index: usize) -> Option<&UnnamedField> { + self.field_at(index) } - fn visit_u64(self, v: u64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field_len(&self) -> usize { + self.field_len() } +} - fn visit_i8(self, v: i8) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) +impl TupleLikeInfo for TupleVariantInfo { + fn get_name(&self) -> &str { + self.name() } - fn visit_i16(self, v: i16) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field(&self, index: usize) -> Option<&UnnamedField> { + self.field_at(index) } - fn visit_i32(self, v: i32) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) + fn get_field_len(&self) -> usize { + self.field_len() } +} - fn visit_i64(self, v: i64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) +/// 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(Vec); + +impl Debug for ExpectedValues { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let len = self.0.len(); + for (index, item) in self.0.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); - fn visit_f32(self, v: f32) -> Result +impl<'de> Deserialize<'de> for Ident { + fn deserialize(deserializer: D) -> Result where - E: de::Error, + D: serde::Deserializer<'de>, { - Ok(Box::new(v)) + 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) } +} - fn visit_f64(self, v: f64) -> Result - where - E: de::Error, - { - Ok(Box::new(v)) +/// A general purpose deserializer for reflected types. +/// +/// 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`]. 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. +/// +/// 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 +/// +/// 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 UntypedReflectDeserializer<'a> { + registry: &'a TypeRegistry, +} + +impl<'a> UntypedReflectDeserializer<'a> { + pub fn new(registry: &'a TypeRegistry) -> Self { + Self { registry } } +} + +impl<'a, 'de> DeserializeSeed<'de> for UntypedReflectDeserializer<'a> { + type Value = Box; - fn visit_string(self, v: String) -> Result + fn deserialize(self, deserializer: D) -> Result where - E: de::Error, + D: serde::Deserializer<'de>, { - Ok(Box::new(v)) + deserializer.deserialize_any(UntypedReflectDeserializerVisitor { + registry: self.registry, + }) } +} - fn visit_str(self, v: &str) -> Result - where - E: de::Error, - { - Ok(Box::new(v.to_string())) +struct UntypedReflectDeserializerVisitor<'a> { + registry: &'a TypeRegistry, +} + +impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'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(), &[])), - } - } - - Err(de::Error::custom("Maps in this location must have the \'type\' field and one of the following fields: \'map\', \'seq\', \'value\'")) + let type_name = map + .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(|| { + Error::custom(format_args!("No registration found for `{}`", type_name)) + })?; + let value = map.next_value_seed(TypedReflectDeserializer { + registration, + registry: self.registry, + })?; + Ok(value) } } -struct DeserializeReflectDeserializer<'a> { - reflect_deserialize: &'a ReflectDeserialize, +/// A deserializer for reflected types whose [`TypeInfo`] is known. +/// +/// 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`]. 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> { + registration: &'a TypeRegistration, + registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for DeserializeReflectDeserializer<'a> { +impl<'a> TypedReflectDeserializer<'a> { + pub fn new(registration: &'a TypeRegistration, registry: &'a TypeRegistry) -> Self { + Self { + registration, + registry, + } + } +} + +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) + let type_name = self.registration.type_name(); + + // 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.registration.type_info() { + TypeInfo::Struct(struct_info) => { + let mut dynamic_struct = deserializer.deserialize_struct( + struct_info.name(), + // Field names are mainly just a hint, we don't necessarily need to store and pass that data + &[], + 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_struct( + tuple_struct_info.name(), + tuple_struct_info.field_len(), + TupleStructVisitor { + tuple_struct_info, + registry: self.registry, + registration: self.registration, + }, + )?; + 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 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, + })? + } else { + deserializer.deserialize_enum( + enum_info.name(), + // Variant names are mainly just a hint, we don't necessarily need to store and pass that data + &[], + EnumVisitor { + enum_info, + registry: self.registry, + }, + )? + }; + dynamic_enum.set_name(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: &'static 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 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: &'static TupleStructInfo, registry: &'a TypeRegistry, + registration: &'a TypeRegistration, } -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") + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + 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_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 {}", + index, + self.tuple_struct_info.type_name(), + )) + })?; + get_registration(field.type_id(), field.type_name(), self.registry) + }; + + while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { + registration: get_field_registration(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 + .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 TupleVisitor<'a> { + tuple_info: &'static TupleInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for ArrayDeserializer<'a> { - type Value = DynamicArray; +impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { + type Value = DynamicTuple; - fn deserialize(self, deserializer: D) -> Result + fn expecting(&self, formatter: &mut 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_seq(ArrayVisitor { - registry: self.registry, - }) + visit_tuple(&mut seq, self.tuple_info, self.registry) } } struct ArrayVisitor<'a> { + array_info: &'static ArrayInfo, registry: &'a TypeRegistry, } 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") + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + formatter.write_str("reflected array value") } fn visit_seq(self, mut seq: V) -> Result @@ -334,42 +495,71 @@ 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 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 { + registration, registry: self.registry, })? { vec.push(value); } - Ok(DynamicArray::new(Box::from(vec))) + if vec.len() != self.array_info.capacity() { + return Err(Error::invalid_length( + vec.len(), + &self.array_info.capacity().to_string().as_str(), + )); + } + + Ok(DynamicArray::new(vec.into_boxed_slice())) } } -struct MapDeserializer<'a> { +struct ListVisitor<'a> { + list_info: &'static ListInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for MapDeserializer<'a> { - type Value = DynamicMap; +impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { + type Value = DynamicList; - fn deserialize(self, deserializer: D) -> Result + fn expecting(&self, formatter: &mut 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_map(MapVisitor { + let mut list = DynamicList::default(); + 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 { + registration, registry: self.registry, - }) + })? { + list.push_box(value); + } + Ok(list) } } struct MapVisitor<'a> { + map_info: &'static MapInfo, registry: &'a TypeRegistry, } 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") + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + formatter.write_str("reflected map value") } fn visit_map(self, mut map: V) -> Result @@ -377,10 +567,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_registration = get_registration( + self.map_info.key_type_id(), + self.map_info.key_type_name(), + self.registry, + )?; + 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 { + registration: key_registration, registry: self.registry, })? { - let value = map.next_value_seed(ReflectDeserializer { + let value = map.next_value_seed(TypedReflectDeserializer { + registration: value_registration, registry: self.registry, })?; dynamic_map.insert_boxed(key, value); @@ -390,221 +592,520 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { } } -struct StructDeserializer<'a> { +struct EnumVisitor<'a> { + enum_info: &'static EnumInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for StructDeserializer<'a> { - type Value = DynamicStruct; +impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { + type Value = DynamicEnum; - fn deserialize(self, deserializer: D) -> Result + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("reflected enum value") + } + + fn visit_enum(self, data: A) -> Result where - D: serde::Deserializer<'de>, + A: EnumAccess<'de>, { - deserializer.deserialize_map(StructVisitor { - registry: self.registry, - }) + 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(|| { + let names = self.enum_info.iter().map(|variant| variant.name()); + Error::custom(format_args!( + "unknown variant `{}`, expected one of {:?}", + variant_name, + ExpectedValues(names.collect()) + )) + })?; + let value: DynamicVariant = match variant_info { + VariantInfo::Unit(..) => variant.unit_variant()?.into(), + VariantInfo::Struct(struct_info) => variant + .struct_variant( + // Field names are mainly just a hint, we don't necessarily need to store and pass that data + &[], + 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 registration = + get_registration(field.type_id(), field.type_name(), self.registry)?; + let value = variant.newtype_variant_seed(TypedReflectDeserializer { + registration, + 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); + Ok(dynamic_enum) } } -struct StructVisitor<'a> { +struct StructVariantVisitor<'a> { + struct_info: &'static StructVariantInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { +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("struct value") + formatter.write_str("reflected struct variant 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); - } - - Ok(dynamic_struct) + visit_struct(&mut map, self.struct_info, self.registry) } } -struct TupleStructDeserializer<'a> { +struct TupleVariantVisitor<'a> { + tuple_info: &'static TupleVariantInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> DeserializeSeed<'de> for TupleStructDeserializer<'a> { - type Value = DynamicTupleStruct; +impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'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 variant value") + } + + fn visit_seq(self, mut seq: V) -> Result where - D: serde::Deserializer<'de>, + V: SeqAccess<'de>, { - deserializer.deserialize_seq(TupleStructVisitor { - registry: self.registry, - }) + visit_tuple(&mut seq, self.tuple_info, self.registry) } } -struct TupleStructVisitor<'a> { +struct OptionVisitor<'a> { + enum_info: &'static EnumInfo, registry: &'a TypeRegistry, } -impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { - type Value = DynamicTupleStruct; +impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> { + type Value = DynamicEnum; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("tuple struct value") + 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_seq(self, mut seq: V) -> Result + fn visit_some(self, deserializer: D) -> Result where - V: SeqAccess<'de>, + D: serde::Deserializer<'de>, { - let mut tuple_struct = DynamicTupleStruct::default(); - while let Some(value) = seq.next_element_seed(ReflectDeserializer { - registry: self.registry, - })? { - tuple_struct.insert_boxed(value); + let variant_info = self.enum_info.variant("Some").unwrap(); + match variant_info { + VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { + let field = tuple_info.field_at(0).unwrap(); + let registration = + get_registration(field.type_id(), field.type_name(), self.registry)?; + let de = TypedReflectDeserializer { + registration, + 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() + ))), } - Ok(tuple_struct) + } + + fn visit_none(self) -> Result + where + E: Error, + { + let mut option = DynamicEnum::default(); + option.set_variant("None", ()); + Ok(option) } } -struct TupleDeserializer<'a> { - registry: &'a TypeRegistry, +fn visit_struct<'de, T, V>( + map: &mut V, + info: &'static T, + registry: &TypeRegistry, +) -> Result +where + T: StructLikeInfo, + V: MapAccess<'de>, +{ + let mut dynamic_struct = DynamicStruct::default(); + while let Some(Ident(key)) = map.next_key::()? { + 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.collect()) + )) + })?; + let registration = get_registration(field.type_id(), field.type_name(), registry)?; + let value = map.next_value_seed(TypedReflectDeserializer { + registration, + registry, + })?; + dynamic_struct.insert_boxed(&key, value); + } + + Ok(dynamic_struct) } -impl<'a, 'de> DeserializeSeed<'de> for TupleDeserializer<'a> { - type Value = DynamicTuple; +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_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_registration(field.type_id(), field.type_name(), registry) + }; + + while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { + registration: get_field_registration(index)?, + registry, + })? { + tuple.insert_boxed(value); + index += 1; + if index >= info.get_field_len() { + break; + } + } - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_seq(TupleVisitor { - registry: self.registry, - }) + let len = info.get_field_len(); + + if tuple.field_len() != len { + return Err(Error::invalid_length( + tuple.field_len(), + &len.to_string().as_str(), + )); } + + Ok(tuple) } -struct TupleVisitor<'a> { +fn get_registration<'a, E: Error>( + type_id: TypeId, + type_name: &str, registry: &'a TypeRegistry, +) -> Result<&'a TypeRegistration, E> { + let registration = registry.get(type_id).ok_or_else(|| { + Error::custom(format_args!( + "no registration found for type `{}`", + type_name + )) + })?; + Ok(registration) } -impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { - type Value = DynamicTuple; +#[cfg(test)] +mod tests { + use std::any::TypeId; + use std::f32::consts::PI; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("tuple value") + use serde::de::DeserializeSeed; + use serde::Deserialize; + + use bevy_utils::HashMap; + + use crate as bevy_reflect; + use crate::serde::{TypedReflectDeserializer, UntypedReflectDeserializer}; + use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry}; + + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct MyStruct { + primitive_value: i8, + option_value: Option, + option_value_complex: Option, + tuple_value: (f32, usize), + list_value: Vec, + array_value: [i32; 5], + 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, } - 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); - } - Ok(tuple) + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct SomeStruct { + foo: i64, } -} -struct EnumDeserializer<'a> { - registry: &'a TypeRegistry, -} + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct SomeTupleStruct(String); -impl<'a, 'de> DeserializeSeed<'de> for EnumDeserializer<'a> { - type Value = DynamicEnum; + #[derive(Reflect, FromReflect, Debug, PartialEq, Deserialize)] + struct SomeDeserializableStruct { + foo: i64, + } - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_map(EnumVisitor { - registry: self.registry, - }) + /// 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: SomeDeserializableStruct, } -} -struct EnumVisitor<'a> { - registry: &'a TypeRegistry, -} + #[derive(Reflect, FromReflect, Debug, PartialEq)] + enum SomeEnum { + Unit, + NewType(usize), + Tuple(f32, f32), + Struct { foo: String }, + } -impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { - type Value = DynamicEnum; + 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::(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::(); + registry.register::<(f32, usize)>(); + registry.register::<[i32; 5]>(); + registry.register::>(); + registry.register::>(); + registry.register::>(); + registry.register::>(); + registry.register_type_data::, ReflectDeserialize>(); + registry + } - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("enum value") + #[test] + fn should_deserialize() { + let mut map = HashMap::new(); + map.insert(64, 32); + + 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], + 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: SomeDeserializableStruct { foo: 101 }, + }, + }; + + 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: [ + -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"), + 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(); + 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); } - 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)); - } + #[test] + fn should_deserialize_value() { + let input = r#"{ + "f32": 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)] + struct Foo { + bar: i32, } - let variant_name = map.next_value::()?; + let expected = Foo { bar: 123 }; - let mut dynamic_enum = DynamicEnum::default(); + let input = r#"( + bar: 123 + )"#; - 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, ()), + let mut registry = get_registry(); + registry.register::(); + 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) + .unwrap(); + + let output = ::from_reflect(dynamic_output.as_ref()).unwrap(); + assert_eq!(expected, output); + } + + #[test] + fn should_deserialize_option() { + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct OptionTest { + none: Option<()>, + simple: Option, + complex: Option, } - Ok(dynamic_enum) - } -} + let expected = OptionTest { + none: None, + simple: Some(String::from("Hello world!")), + complex: Some(SomeStruct { foo: 123 }), + }; -#[cfg(test)] -mod tests { - use super::ReflectDeserializer; - use crate as bevy_reflect; - use crate::prelude::*; - use crate::{DynamicEnum, TypeRegistry}; - use ::serde::de::DeserializeSeed; + let mut registry = get_registry(); + registry.register::(); + registry.register::>(); - fn get_registry() -> TypeRegistry { - let mut registry = TypeRegistry::default(); - registry.register::(); - registry.register::(); - registry.register::(); - registry.register::<(f32, f32)>(); - registry + // === 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] @@ -622,12 +1123,9 @@ mod tests { // === Unit Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "enum": { - "variant": "Unit", - }, + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": 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(); @@ -636,18 +1134,9 @@ 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, - }, - ], - }, + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": 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(); @@ -656,22 +1145,9 @@ 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, - }, - ], - }, + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": 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(); @@ -680,18 +1156,11 @@ mod tests { // === Struct Variant === // let input = r#"{ - "type": "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum", - "enum": { - "variant": "Struct", - "struct": { - "value": { - "type": "alloc::string::String", - "value": "I <3 Enums", - }, - }, - }, + "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": Struct( + value: "I <3 Enums", + ), }"#; - 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(); diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index 1ff61a4e70b4e..3355ed38d0b11 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -6,24 +6,11 @@ pub use de::*; pub use ser::*; 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"; -} - #[cfg(test)] mod tests { use crate::{self as bevy_reflect, DynamicTupleStruct}; use crate::{ - serde::{ReflectDeserializer, ReflectSerializer}, + serde::{ReflectSerializer, UntypedReflectDeserializer}, type_registry::TypeRegistry, DynamicStruct, Reflect, }; @@ -61,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(); @@ -96,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 b086a6a942085..8425f1e0a015b 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -1,11 +1,14 @@ 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, + TypeInfo, TypeRegistry, VariantInfo, VariantType, +}; +use serde::ser::{ + Error, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, + SerializeTupleVariant, }; -use serde::ser::Error; use serde::{ ser::{SerializeMap, SerializeSeq}, - Serialize, Serializer, + Serialize, }; use super::SerializationData; @@ -40,6 +43,34 @@ 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 => 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: +/// 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 +87,39 @@ impl<'a> Serialize for ReflectSerializer<'a> { where S: serde::Serializer, { + let mut state = serializer.serialize_map(Some(1))?; + state.serialize_entry( + self.value.type_name(), + &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 +156,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 +171,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,35 +187,31 @@ 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, - }, + let type_info = get_type_info( + self.struct_value.get_type_info(), + self.struct_value.type_name(), + self.registry, )?; - state.end() - } -} -pub struct StructValueSerializer<'a> { - pub struct_value: &'a dyn Struct, - pub registry: &'a TypeRegistry, -} + let struct_info = match type_info { + TypeInfo::Struct(struct_info) => struct_info, + info => { + return Err(Error::custom(format_args!( + "expected struct type but received {:?}", + info + ))); + } + }; -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_struct( + struct_info.name(), + self.struct_value.field_len() - ignored_len, + )?; for (index, value) in self.struct_value.iter_fields().enumerate() { if serialization_data @@ -168,8 +220,8 @@ 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))?; + let key = struct_info.field_at(index).unwrap().name(); + state.serialize_field(key, &TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -185,35 +237,31 @@ 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, - }, + let type_info = get_type_info( + self.tuple_struct.get_type_info(), + self.tuple_struct.type_name(), + self.registry, )?; - state.end() - } -} -pub struct TupleStructValueSerializer<'a> { - pub tuple_struct: &'a dyn TupleStruct, - pub registry: &'a TypeRegistry, -} + let tuple_struct_info = match type_info { + TypeInfo::TupleStruct(tuple_struct_info) => tuple_struct_info, + info => { + return Err(Error::custom(format_args!( + "expected tuple struct type but received {:?}", + info + ))); + } + }; -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_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 @@ -222,7 +270,7 @@ impl<'a> Serialize for TupleStructValueSerializer<'a> { { continue; } - state.serialize_element(&ReflectSerializer::new(value, self.registry))?; + state.serialize_field(&TypedReflectSerializer::new(value, self.registry))?; } state.end() } @@ -238,104 +286,107 @@ 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())?; - state.serialize_entry( - type_fields::ENUM, - &EnumValueSerializer { - enum_value: self.enum_value, - registry: self.registry, - }, + let type_info = get_type_info( + self.enum_value.get_type_info(), + self.enum_value.type_name(), + self.registry, )?; - state.end() - } -} - -pub struct EnumValueSerializer<'a> { - pub enum_value: &'a dyn Enum, - pub registry: &'a TypeRegistry, -} -impl<'a> Serialize for EnumValueSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - 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))? + let enum_info = match type_info { + TypeInfo::Enum(enum_info) => enum_info, + info => { + return Err(Error::custom(format_args!( + "expected enum type but received {:?}", + info + ))); + } }; - state.serialize_entry(type_fields::VARIANT, variant_name)?; + let enum_name = enum_info.name(); + let variant_index = self.enum_value.variant_index() as u32; + let variant_info = enum_info + .variant_at(variant_index as usize) + .ok_or_else(|| { + Error::custom(format_args!( + "variant at index `{}` does not exist", + variant_index + )) + })?; + let variant_name = variant_info.name(); + let variant_type = self.enum_value.variant_type(); + let field_len = self.enum_value.field_len(); - match self.enum_value.variant_type() { + match variant_type { + VariantType::Unit => { + 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 => { - state.serialize_key(type_fields::STRUCT)?; - state.serialize_value(&StructVariantSerializer { - enum_value: self.enum_value, - registry: self.registry, - })?; + 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(); + 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 => { - state.serialize_key(type_fields::TUPLE)?; - state.serialize_value(&TupleVariantSerializer { - enum_value: self.enum_value, - registry: self.registry, - })?; + let mut state = serializer.serialize_tuple_variant( + enum_name, + variant_index, + variant_name, + field_len, + )?; + for field in self.enum_value.iter_fields() { + state.serialize_field(&TypedReflectSerializer::new( + field.value(), + self.registry, + ))?; + } + state.end() } - _ => {} - } - - state.end() - } -} - -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 field_len = self.enum_value.field_len(); - let mut state = serializer.serialize_seq(Some(field_len))?; - for field in self.enum_value.iter_fields() { - state.serialize_element(&ReflectSerializer::new(field.value(), self.registry))?; - } - 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 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))?; } - state.end() } } @@ -349,34 +400,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 +415,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 +422,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 +436,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 +458,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 +468,211 @@ 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::{FromReflect, Reflect, ReflectSerialize, TypeRegistry}; + use bevy_utils::HashMap; + use ron::extensions::Extensions; use ron::ser::PrettyConfig; + use serde::Serialize; + use std::f32::consts::PI; + + #[derive(Reflect, Debug, PartialEq)] + struct MyStruct { + primitive_value: i8, + option_value: Option, + option_value_complex: Option, + tuple_value: (f32, usize), + list_value: Vec, + array_value: [i32; 5], + 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, + } + + #[derive(Reflect, FromReflect, Debug, PartialEq)] + struct SomeStruct { + foo: i64, + } + + #[derive(Reflect, Debug, PartialEq)] + struct SomeTupleStruct(String); + + #[derive(Reflect, Debug, PartialEq)] + enum SomeEnum { + Unit, + NewType(usize), + Tuple(f32, f32), + 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. + #[derive(Reflect, Debug, PartialEq, Serialize)] + #[reflect(Serialize)] + struct CustomSerialize { + value: usize, + #[serde(rename = "renamed")] + inner_struct: SomeSerializableStruct, + } 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_type_data::(); 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!")), + 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], + 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: SomeSerializableStruct { foo: 101 }, + }, + }; + + let registry = get_registry(); + let serializer = ReflectSerializer::new(&input, ®istry); + + 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::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: { + 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: ( + value: 100, + renamed: ( + foo: 101, + ), + ), + ), +}"#; + 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)] @@ -546,10 +693,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", - "enum": { - "variant": "Unit", - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Unit, }"#; assert_eq!(expected, output); @@ -558,16 +702,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", - "enum": { - "variant": "NewType", - "tuple": [ - { - "type": "usize", - "value": 123, - }, - ], - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": NewType(123), }"#; assert_eq!(expected, output); @@ -576,20 +711,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", - "enum": { - "variant": "Tuple", - "tuple": [ - { - "type": "f32", - "value": 1.23, - }, - { - "type": "f32", - "value": 3.21, - }, - ], - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Tuple(1.23, 3.21), }"#; assert_eq!(expected, output); @@ -600,17 +722,10 @@ 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", - "enum": { - "variant": "Struct", - "struct": { - "value": { - "type": "alloc::string::String", - "value": "I <3 Enums", - }, - }, - }, + "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": 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() + } } diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index a1dc934b9efaf..f246b7128cc35 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -69,10 +69,11 @@ 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_indices: HashMap<&'static str, usize>, } impl StructInfo { @@ -80,19 +81,18 @@ 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() - .map(|(index, field)| { - let name = field.name().clone(); - (name, index) - }) + .map(|(index, field)| (field.name(), index)) .collect::>(); Self { + name, type_name: std::any::type_name::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), @@ -127,6 +127,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..9e5519d500ad6 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -37,10 +37,10 @@ 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::(&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..1c331978f3f78 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -27,8 +27,8 @@ 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 info = StructInfo::new::(&fields); +/// let fields = [NamedField::new::("bar")]; +/// 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) /// }) /// } diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index e55a5fd4b592b..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::{ReflectDeserializer, 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(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();