From 6b630915b46b7ddb1cb5443a715c91b5c657c424 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 13 Dec 2022 16:12:03 -0700 Subject: [PATCH 01/11] Add Proxy trait and update Dynamics --- .../bevy_reflect_derive/src/impls/structs.rs | 2 +- .../src/impls/tuple_structs.rs | 2 +- crates/bevy_reflect/src/array.rs | 35 ++-- crates/bevy_reflect/src/enums/dynamic_enum.rs | 58 +++--- crates/bevy_reflect/src/enums/mod.rs | 12 +- crates/bevy_reflect/src/from_reflect.rs | 4 +- crates/bevy_reflect/src/impls/std.rs | 2 +- crates/bevy_reflect/src/lib.rs | 1 + crates/bevy_reflect/src/list.rs | 35 ++-- crates/bevy_reflect/src/map.rs | 33 +-- crates/bevy_reflect/src/proxy.rs | 191 ++++++++++++++++++ crates/bevy_reflect/src/serde/de.rs | 14 +- crates/bevy_reflect/src/struct_trait.rs | 29 ++- crates/bevy_reflect/src/tuple.rs | 50 +++-- crates/bevy_reflect/src/tuple_struct.rs | 29 ++- crates/bevy_reflect/src/type_info.rs | 64 +++++- 16 files changed, 424 insertions(+), 137 deletions(-) create mode 100644 crates/bevy_reflect/src/proxy.rs 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 e22634e5de762..726a7d9bd1d18 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -151,7 +151,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicStruct { let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default(); - dynamic.set_name(::std::string::ToString::to_string(#bevy_reflect_path::Reflect::type_name(self))); + dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::get_type_info(self))); #(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } 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 c41c53b86ef55..2f5995e6820d8 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 @@ -122,7 +122,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct { let mut dynamic: #bevy_reflect_path::DynamicTupleStruct = #FQDefault::default(); - dynamic.set_name(::std::string::ToString::to_string(#bevy_reflect_path::Reflect::type_name(self))); + dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::get_type_info(self))); #(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 947601a1548e5..7735ecf895482 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,3 +1,4 @@ +use crate::proxy::Proxy; use crate::{ utility::{reflect_hasher, NonGenericTypeInfoCell}, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, @@ -67,7 +68,7 @@ pub trait Array: Reflect { /// Clones the list, producing a [`DynamicArray`]. fn clone_dynamic(&self) -> DynamicArray { DynamicArray { - name: self.type_name().to_string(), + represented_type: Some(self.get_type_info()), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -167,7 +168,7 @@ impl ArrayInfo { /// [`DynamicList`]: crate::DynamicList #[derive(Debug)] pub struct DynamicArray { - pub(crate) name: String, + pub(crate) represented_type: Option<&'static TypeInfo>, pub(crate) values: Box<[Box]>, } @@ -175,14 +176,14 @@ impl DynamicArray { #[inline] pub fn new(values: Box<[Box]>) -> Self { Self { - name: String::default(), + represented_type: None, values, } } pub fn from_vec(values: Vec) -> Self { Self { - name: String::default(), + represented_type: None, values: values .into_iter() .map(|field| Box::new(field) as Box) @@ -191,21 +192,21 @@ impl DynamicArray { } } - #[inline] - pub fn name(&self) -> &str { - &self.name - } - - #[inline] - pub fn set_name(&mut self, name: String) { - self.name = name; + /// Sets the [type] to be [represented] by this `DynamicArray`. + /// + /// [type]: TypeInfo + /// [represented]: Proxy::represents + pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + self.represented_type = represented_type; } } impl Reflect for DynamicArray { #[inline] fn type_name(&self) -> &str { - self.name.as_str() + self.represented_type + .map(|info| info.type_name()) + .unwrap_or_default() } #[inline] @@ -312,7 +313,7 @@ impl Array for DynamicArray { #[inline] fn clone_dynamic(&self) -> DynamicArray { DynamicArray { - name: self.name.clone(), + represented_type: self.represented_type, values: self .values .iter() @@ -322,6 +323,12 @@ impl Array for DynamicArray { } } +impl Proxy for DynamicArray { + fn represents(&self) -> Option<&'static TypeInfo> { + self.represented_type + } +} + impl Typed for DynamicArray { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index db9e050fbe2ab..d10c51d8e0d08 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -1,3 +1,4 @@ +use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, @@ -58,7 +59,6 @@ impl From<()> for DynamicVariant { /// /// // Create a DynamicEnum to represent the new value /// let mut dyn_enum = DynamicEnum::new( -/// Reflect::type_name(&value), /// "None", /// DynamicVariant::Unit /// ); @@ -71,7 +71,7 @@ impl From<()> for DynamicVariant { /// ``` #[derive(Default, Debug)] pub struct DynamicEnum { - name: String, + represented_type: Option<&'static TypeInfo>, variant_name: String, variant_index: usize, variant: DynamicVariant, @@ -82,17 +82,12 @@ impl DynamicEnum { /// /// # Arguments /// - /// * `name`: The type name of the enum /// * `variant_name`: The name of the variant to set /// * `variant`: The variant data /// - pub fn new, V: Into>( - name: I, - variant_name: I, - variant: V, - ) -> Self { + pub fn new, V: Into>(variant_name: I, variant: V) -> Self { Self { - name: name.into(), + represented_type: None, variant_index: 0, variant_name: variant_name.into(), variant: variant.into(), @@ -103,33 +98,29 @@ impl DynamicEnum { /// /// # 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(), + represented_type: None, variant_index, variant_name: variant_name.into(), variant: variant.into(), } } - /// Returns the type name of the enum. - pub fn name(&self) -> &str { - &self.name - } - - /// Sets the type name of the enum. - pub fn set_name(&mut self, name: String) { - self.name = name; + /// Sets the [type] to be [represented] by this `DynamicEnum`. + /// + /// [type]: TypeInfo + /// [represented]: Proxy::represents + pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + self.represented_type = represented_type; } /// Set the current enum variant represented by this struct. @@ -142,11 +133,11 @@ impl DynamicEnum { pub fn set_variant_with_index, V: Into>( &mut self, variant_index: usize, - name: I, + variant_name: I, variant: V, ) { self.variant_index = variant_index; - self.variant_name = name.into(); + self.variant_name = variant_name.into(); self.variant = variant.into(); } @@ -161,9 +152,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() { + let type_info = value.get_type_info(); + let mut dyn_enum = match value.variant_type() { VariantType::Unit => DynamicEnum::new_with_index( - value.type_name(), value.variant_index(), value.variant_name(), DynamicVariant::Unit, @@ -174,7 +165,6 @@ impl DynamicEnum { data.insert_boxed(field.value().clone_value()); } DynamicEnum::new_with_index( - value.type_name(), value.variant_index(), value.variant_name(), DynamicVariant::Tuple(data), @@ -187,13 +177,15 @@ impl DynamicEnum { data.insert_boxed(name, field.value().clone_value()); } DynamicEnum::new_with_index( - value.type_name(), value.variant_index(), value.variant_name(), DynamicVariant::Struct(data), ) } - } + }; + + dyn_enum.set_represented_type(Some(type_info)); + dyn_enum } } @@ -276,7 +268,7 @@ impl Enum for DynamicEnum { fn clone_dynamic(&self) -> DynamicEnum { Self { - name: self.name.clone(), + represented_type: self.represented_type, variant_index: self.variant_index, variant_name: self.variant_name.clone(), variant: self.variant.clone(), @@ -287,7 +279,9 @@ impl Enum for DynamicEnum { impl Reflect for DynamicEnum { #[inline] fn type_name(&self) -> &str { - &self.name + self.represented_type + .map(|info| info.type_name()) + .unwrap_or_default() } #[inline] @@ -419,6 +413,12 @@ impl Reflect for DynamicEnum { } } +impl Proxy for DynamicEnum { + fn represents(&self) -> Option<&'static TypeInfo> { + self.represented_type + } +} + impl Typed for DynamicEnum { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index e8c32e73ef9c5..7693bf9794acc 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -342,14 +342,14 @@ mod tests { // === Tuple === // let mut data = DynamicTuple::default(); data.insert(1.23_f32); - let dyn_enum = DynamicEnum::new(std::any::type_name::>(), "B", data); + let dyn_enum = DynamicEnum::new("B", data); value.apply(&dyn_enum); assert_eq!(TestEnum::B(1.23), value); // === Struct === // let mut data = DynamicStruct::default(); data.insert("value", 1.23_f32); - let dyn_enum = DynamicEnum::new(std::any::type_name::>(), "C", data); + let dyn_enum = DynamicEnum::new("C", data); value.apply(&dyn_enum); assert_eq!(TestEnum::C { value: 1.23 }, value); } @@ -371,14 +371,14 @@ mod tests { // === Tuple === // let mut data = DynamicTuple::default(); data.insert(TestStruct(123)); - let dyn_enum = DynamicEnum::new(std::any::type_name::(), "B", data); + let dyn_enum = DynamicEnum::new("B", data); value.apply(&dyn_enum); assert_eq!(TestEnum::B(TestStruct(123)), value); // === Struct === // let mut data = DynamicStruct::default(); data.insert("value", TestStruct(123)); - let dyn_enum = DynamicEnum::new(std::any::type_name::(), "C", data); + let dyn_enum = DynamicEnum::new("C", data); value.apply(&dyn_enum); assert_eq!( TestEnum::C { @@ -409,14 +409,14 @@ mod tests { // === Tuple === // let mut data = DynamicTuple::default(); data.insert(OtherEnum::B(123)); - let dyn_enum = DynamicEnum::new(std::any::type_name::(), "B", data); + let dyn_enum = DynamicEnum::new("B", data); value.apply(&dyn_enum); assert_eq!(TestEnum::B(OtherEnum::B(123)), value); // === Struct === // let mut data = DynamicStruct::default(); data.insert("value", OtherEnum::C { value: 1.23 }); - let dyn_enum = DynamicEnum::new(std::any::type_name::(), "C", data); + let dyn_enum = DynamicEnum::new("C", data); value.apply(&dyn_enum); assert_eq!( TestEnum::C { diff --git a/crates/bevy_reflect/src/from_reflect.rs b/crates/bevy_reflect/src/from_reflect.rs index 4d98698398bf0..f4abb65d7e0f6 100644 --- a/crates/bevy_reflect/src/from_reflect.rs +++ b/crates/bevy_reflect/src/from_reflect.rs @@ -75,7 +75,7 @@ pub trait FromReflect: Reflect + Sized { /// # Example /// /// ``` -/// # use bevy_reflect::{DynamicTupleStruct, FromReflect, Reflect, ReflectFromReflect, TypeRegistry}; +/// # use bevy_reflect::{DynamicTupleStruct, FromReflect, Reflect, ReflectFromReflect, Typed, TypeRegistry}; /// # #[derive(Reflect, FromReflect, PartialEq, Eq, Debug)] /// # #[reflect(FromReflect)] /// # struct Foo(#[reflect(default = "default_value")] usize); @@ -84,7 +84,7 @@ pub trait FromReflect: Reflect + Sized { /// # registry.register::(); /// /// let mut reflected = DynamicTupleStruct::default(); -/// reflected.set_name(std::any::type_name::().to_string()); +/// reflected.set_represented_type(Some(::type_info())); /// /// let registration = registry.get_with_name(reflected.type_name()).unwrap(); /// let rfr = registration.data::().unwrap(); diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 0b42a707930b8..f88bd5eb96103 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -397,7 +397,7 @@ macro_rules! impl_reflect_for_hashmap { fn clone_dynamic(&self) -> DynamicMap { let mut dynamic_map = DynamicMap::default(); - dynamic_map.set_name(self.type_name().to_string()); + dynamic_map.set_represented_type(Some(self.get_type_info())); for (k, v) in self { let key = K::from_reflect(k).unwrap_or_else(|| { panic!("Attempted to clone invalid key of type {}.", k.type_name()) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 8b75615963d69..28de45cbd7781 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -470,6 +470,7 @@ mod impls { } mod enums; +pub mod proxy; pub mod serde; pub mod std_traits; pub mod utility; diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index d13e7776f0693..0f4b7ccf67e4c 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -2,6 +2,7 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher}; +use crate::proxy::Proxy; use crate::utility::{reflect_hasher, NonGenericTypeInfoCell}; use crate::{ DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, @@ -97,7 +98,7 @@ pub trait List: Reflect { /// Clones the list, producing a [`DynamicList`]. fn clone_dynamic(&self) -> DynamicList { DynamicList { - name: self.type_name().to_string(), + represented_type: Some(self.get_type_info()), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -177,25 +178,17 @@ impl ListInfo { /// A list of reflected values. #[derive(Default)] pub struct DynamicList { - name: String, + represented_type: Option<&'static TypeInfo>, values: Vec>, } impl DynamicList { - /// Returns the type name of the list. + /// Sets the [type] to be [represented] by this `DynamicList`. /// - /// The value returned by this method is the same value returned by - /// [`Reflect::type_name`]. - pub fn name(&self) -> &str { - &self.name - } - - /// Sets the type name of the list. - /// - /// The value set by this method is the value returned by - /// [`Reflect::type_name`]. - pub fn set_name(&mut self, name: String) { - self.name = name; + /// [type]: TypeInfo + /// [represented]: Proxy::represents + pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + self.represented_type = represented_type; } /// Appends a typed value to the list. @@ -248,7 +241,7 @@ impl List for DynamicList { fn clone_dynamic(&self) -> DynamicList { DynamicList { - name: self.name.clone(), + represented_type: self.represented_type, values: self .values .iter() @@ -261,7 +254,9 @@ impl List for DynamicList { impl Reflect for DynamicList { #[inline] fn type_name(&self) -> &str { - self.name.as_str() + self.represented_type + .map(|info| info.type_name()) + .unwrap_or_default() } #[inline] @@ -345,6 +340,12 @@ impl Reflect for DynamicList { } } +impl Proxy for DynamicList { + fn represents(&self) -> Option<&'static TypeInfo> { + self.represented_type + } +} + impl Debug for DynamicList { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.debug(f) diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 8dcd28386a2e5..1a8a4ed032c41 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -4,6 +4,7 @@ use std::hash::Hash; use bevy_utils::{Entry, HashMap}; +use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed}; @@ -184,26 +185,18 @@ const HASH_ERROR: &str = "the given key does not support hashing"; /// An ordered mapping between reflected values. #[derive(Default)] pub struct DynamicMap { - name: String, + represented_type: Option<&'static TypeInfo>, values: Vec<(Box, Box)>, indices: HashMap, } impl DynamicMap { - /// Returns the type name of the map. + /// Sets the [type] to be [represented] by this `DynamicMap`. /// - /// The value returned by this method is the same value returned by - /// [`Reflect::type_name`]. - pub fn name(&self) -> &str { - &self.name - } - - /// Sets the type name of the map. - /// - /// The value set by this method is the same value returned by - /// [`Reflect::type_name`]. - pub fn set_name(&mut self, name: String) { - self.name = name; + /// [type]: TypeInfo + /// [represented]: Proxy::represents + pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + self.represented_type = represented_type; } /// Inserts a typed key-value pair into the map. @@ -232,7 +225,7 @@ impl Map for DynamicMap { fn clone_dynamic(&self) -> DynamicMap { DynamicMap { - name: self.name.clone(), + represented_type: self.represented_type, values: self .values .iter() @@ -289,7 +282,9 @@ impl Map for DynamicMap { impl Reflect for DynamicMap { fn type_name(&self) -> &str { - &self.name + self.represented_type + .map(|info| info.type_name()) + .unwrap_or_default() } #[inline] @@ -360,6 +355,12 @@ impl Reflect for DynamicMap { } } +impl Proxy for DynamicMap { + fn represents(&self) -> Option<&'static TypeInfo> { + self.represented_type + } +} + impl Debug for DynamicMap { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.debug(f) diff --git a/crates/bevy_reflect/src/proxy.rs b/crates/bevy_reflect/src/proxy.rs new file mode 100644 index 0000000000000..278a8f9a622a7 --- /dev/null +++ b/crates/bevy_reflect/src/proxy.rs @@ -0,0 +1,191 @@ +use crate::{Reflect, TypeInfo}; + +/// This trait allows for types to behave as proxies to another type. +/// +/// This is mainly used by [dynamic] types such as [`DynamicStruct`], +/// [`DynamicList`], etc. +/// +/// [dynamic]: crate::TypeInfo::Dynamic +/// [`DynamicStruct`]: crate::DynamicStruct +/// [`DynamicList`]: crate::DynamicList +pub trait Proxy: Reflect { + /// Returns the [`TypeInfo`] of the type this proxy represents, if any. + /// + /// This will return `None` if the proxy currently does not represent any concrete type. + fn represents(&self) -> Option<&'static TypeInfo>; +} + +#[cfg(test)] +mod tests { + use super::Proxy; + use crate as bevy_reflect; + use crate::{ + Array, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, + DynamicTupleStruct, Enum, List, Map, Reflect, Struct, Tuple, TupleStruct, TypeInfo, Typed, + }; + use bevy_utils::HashMap; + + macro_rules! assert_proxy { + ($expected_type_info: ident, $proxy: ident) => { + assert_eq!( + $expected_type_info.type_name(), + $proxy.represents().unwrap().type_name() + ); + + let TypeInfo::Dynamic(info) = $proxy.get_type_info() else { panic!("expected `TypeInfo::Dynamic`") }; + assert_eq!( + $expected_type_info.type_name(), + info.represents(&$proxy).unwrap().type_name() + ) + }; + } + + #[test] + fn dynamic_tuple_should_represent_type() { + let expected = <(f32, f32) as Typed>::type_info(); + let mut dyn_tuple = DynamicTuple::default(); + dyn_tuple.insert(1.23_f32); + dyn_tuple.insert(3.21_f32); + + // Inserting to a DynamicTuple clears the represented type + assert!(dyn_tuple.represents().is_none()); + + dyn_tuple.set_represented_type(Some(expected)); + assert_proxy!(expected, dyn_tuple); + + let dyn_tuple = (1.23_f32, 3.21_f32).clone_dynamic(); + assert_proxy!(expected, dyn_tuple); + } + + #[test] + fn dynamic_array_should_represent_type() { + let expected = <[f32; 2] as Typed>::type_info(); + let mut dyn_array = DynamicArray::from_vec(vec![1.23_f32, 3.21_f32]); + + // DynamicArrays initialize without a represented type + assert!(dyn_array.represents().is_none()); + + dyn_array.set_represented_type(Some(expected)); + assert_proxy!(expected, dyn_array); + + let dyn_array = [1.23_f32, 3.21_f32].clone_dynamic(); + assert_proxy!(expected, dyn_array); + } + + #[test] + fn dynamic_list_should_represent_type() { + let expected = as Typed>::type_info(); + let mut dyn_list = DynamicList::default(); + dyn_list.push(1.23_f32); + dyn_list.push(3.21_f32); + + // DynamicLists initialize without a represented type + assert!(dyn_list.represents().is_none()); + + dyn_list.set_represented_type(Some(expected)); + assert_proxy!(expected, dyn_list); + + let dyn_list = List::clone_dynamic(&vec![1.23_f32, 3.21_f32]); + assert_proxy!(expected, dyn_list); + } + + #[test] + fn dynamic_map_should_represent_type() { + let expected = as Typed>::type_info(); + let mut dyn_map = DynamicMap::default(); + dyn_map.insert(0_usize, 1.23_f32); + dyn_map.insert(1_usize, 3.21_f32); + + // DynamicMaps initialize without a represented type + assert!(dyn_map.represents().is_none()); + + dyn_map.set_represented_type(Some(expected)); + assert_proxy!(expected, dyn_map); + + let mut map = HashMap::::new(); + map.insert(0_usize, 1.23_f32); + map.insert(1_usize, 3.21_f32); + let dyn_map = map.clone_dynamic(); + assert_proxy!(expected, dyn_map); + } + + #[test] + fn dynamic_tuple_struct_should_represent_type() { + #[derive(Reflect)] + struct MyTupleStruct(f32, f32); + + let expected = ::type_info(); + let mut dyn_tuple_struct = DynamicTupleStruct::default(); + dyn_tuple_struct.insert(1.23_f32); + dyn_tuple_struct.insert(3.21_f32); + + // DynamicTupleStructs initialize without a represented type + assert!(dyn_tuple_struct.represents().is_none()); + + dyn_tuple_struct.set_represented_type(Some(expected)); + assert_proxy!(expected, dyn_tuple_struct); + + let dyn_tuple_struct = MyTupleStruct(1.23_f32, 3.21_f32).clone_dynamic(); + assert_proxy!(expected, dyn_tuple_struct); + } + + #[test] + fn dynamic_struct_should_represent_type() { + #[derive(Reflect)] + struct MyStruct { + foo: f32, + bar: f32, + } + + let expected = ::type_info(); + let mut dyn_struct = DynamicStruct::default(); + dyn_struct.insert("foo", 1.23_f32); + dyn_struct.insert("bar", 3.21_f32); + + // DynamicStructs initialize without a represented type + assert!(dyn_struct.represents().is_none()); + + dyn_struct.set_represented_type(Some(expected)); + assert_proxy!(expected, dyn_struct); + + let dyn_struct = MyStruct { + foo: 1.23_f32, + bar: 3.21_f32, + } + .clone_dynamic(); + assert_proxy!(expected, dyn_struct); + } + + #[test] + fn dynamic_enum_should_represent_type() { + #[derive(Reflect)] + enum MyEnum { + Unit, + Tuple(f32, f32), + Struct { foo: f32, bar: f32 }, + } + + let expected = ::type_info(); + let mut dyn_enum = DynamicEnum::default(); + dyn_enum.set_variant("Unit", ()); + + // DynamicEnums initialize without a represented type + assert!(dyn_enum.represents().is_none()); + + dyn_enum.set_represented_type(Some(expected)); + assert_proxy!(expected, dyn_enum); + + let dyn_unit_enum = MyEnum::Unit.clone_dynamic(); + assert_proxy!(expected, dyn_unit_enum); + + let dyn_tuple_enum = MyEnum::Tuple(1.23, 3.21).clone_dynamic(); + assert_proxy!(expected, dyn_tuple_enum); + + let dyn_struct_enum = MyEnum::Struct { + foo: 1.23_f32, + bar: 3.21_f32, + } + .clone_dynamic(); + assert_proxy!(expected, dyn_struct_enum); + } +} diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 60d3b0aa2047c..ebf0b40a85b00 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -389,7 +389,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { registry: self.registry, }, )?; - dynamic_struct.set_name(struct_info.type_name().to_string()); + dynamic_struct.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_struct)) } TypeInfo::TupleStruct(tuple_struct_info) => { @@ -402,7 +402,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { registration: self.registration, }, )?; - dynamic_tuple_struct.set_name(tuple_struct_info.type_name().to_string()); + dynamic_tuple_struct.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_tuple_struct)) } TypeInfo::List(list_info) => { @@ -410,7 +410,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { list_info, registry: self.registry, })?; - dynamic_list.set_name(list_info.type_name().to_string()); + dynamic_list.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_list)) } TypeInfo::Array(array_info) => { @@ -421,7 +421,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { registry: self.registry, }, )?; - dynamic_array.set_name(array_info.type_name().to_string()); + dynamic_array.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_array)) } TypeInfo::Map(map_info) => { @@ -429,7 +429,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { map_info, registry: self.registry, })?; - dynamic_map.set_name(map_info.type_name().to_string()); + dynamic_map.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_map)) } TypeInfo::Tuple(tuple_info) => { @@ -440,7 +440,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { registry: self.registry, }, )?; - dynamic_tuple.set_name(tuple_info.type_name().to_string()); + dynamic_tuple.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_tuple)) } TypeInfo::Enum(enum_info) => { @@ -461,7 +461,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { }, )? }; - dynamic_enum.set_name(type_name.to_string()); + dynamic_enum.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_enum)) } TypeInfo::Value(_) => { diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index ab146d1b36a43..0555ea3d202f7 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,3 +1,4 @@ +use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, @@ -272,21 +273,19 @@ impl GetField for dyn Struct { /// A struct type which allows fields to be added at runtime. #[derive(Default)] pub struct DynamicStruct { - name: String, + represented_type: Option<&'static TypeInfo>, fields: Vec>, field_names: Vec>, field_indices: HashMap, usize>, } impl DynamicStruct { - /// Returns the type name of the struct. - pub fn name(&self) -> &str { - &self.name - } - - /// Sets the type name of the struct. - pub fn set_name(&mut self, name: String) { - self.name = name; + /// Sets the [type] to be [represented] by this `DynamicStruct`. + /// + /// [type]: TypeInfo + /// [represented]: Proxy::represents + pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + self.represented_type = represented_type; } /// Inserts a field named `name` with value `value` into the struct. @@ -370,7 +369,7 @@ impl Struct for DynamicStruct { fn clone_dynamic(&self) -> DynamicStruct { DynamicStruct { - name: self.name.clone(), + represented_type: Some(self.get_type_info()), field_names: self.field_names.clone(), field_indices: self.field_indices.clone(), fields: self @@ -385,7 +384,9 @@ impl Struct for DynamicStruct { impl Reflect for DynamicStruct { #[inline] fn type_name(&self) -> &str { - &self.name + self.represented_type + .map(|info| info.type_name()) + .unwrap_or_default() } #[inline] @@ -472,6 +473,12 @@ impl Reflect for DynamicStruct { } } +impl Proxy for DynamicStruct { + fn represents(&self) -> Option<&'static TypeInfo> { + self.represented_type + } +} + impl Debug for DynamicStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.debug(f) diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index f0e20aff6ba25..4933b1065ff18 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,9 +1,11 @@ +use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, UnnamedField, }; use std::any::{Any, TypeId}; +use std::borrow::Cow; use std::fmt::{Debug, Formatter}; use std::slice::Iter; @@ -207,39 +209,39 @@ impl TupleInfo { /// A tuple which allows fields to be added at runtime. #[derive(Default, Debug)] pub struct DynamicTuple { - name: String, + name: Cow<'static, str>, + represented_type: Option<&'static TypeInfo>, fields: Vec>, } impl DynamicTuple { - /// Returns the type name of the tuple. + /// Sets the [type] to be [represented] by this `DynamicTuple`. /// - /// The tuple's name is automatically generated from its element types. - pub fn name(&self) -> &str { - &self.name - } - - /// Manually sets the type name of the tuple. - /// - /// Note that the tuple name will be overwritten when elements are added. - pub fn set_name(&mut self, name: String) { - self.name = name; + /// [type]: TypeInfo + /// [represented]: Proxy::represents + pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + if let Some(info) = represented_type { + self.name = Cow::Borrowed(info.type_name()); + } + self.represented_type = represented_type; } /// Appends an element with value `value` to the tuple. pub fn insert_boxed(&mut self, value: Box) { + self.represented_type = None; self.fields.push(value); self.generate_name(); } /// Appends a typed element with value `value` to the tuple. pub fn insert(&mut self, value: T) { + self.represented_type = None; self.insert_boxed(Box::new(value)); self.generate_name(); } fn generate_name(&mut self) { - let name = &mut self.name; + let mut name = self.name.to_string(); name.clear(); name.push('('); for (i, field) in self.fields.iter().enumerate() { @@ -249,6 +251,7 @@ impl DynamicTuple { name.push_str(field.type_name()); } name.push(')'); + self.name = Cow::Owned(name); } } @@ -285,6 +288,7 @@ impl Tuple for DynamicTuple { fn clone_dynamic(&self) -> DynamicTuple { DynamicTuple { name: self.name.clone(), + represented_type: self.represented_type, fields: self .fields .iter() @@ -297,7 +301,9 @@ impl Tuple for DynamicTuple { impl Reflect for DynamicTuple { #[inline] fn type_name(&self) -> &str { - self.name() + self.represented_type + .map(|info| info.type_name()) + .unwrap_or_else(|| &self.name) } #[inline] @@ -375,6 +381,12 @@ impl Reflect for DynamicTuple { } } +impl Proxy for DynamicTuple { + fn represents(&self) -> Option<&'static TypeInfo> { + self.represented_type + } +} + impl Typed for DynamicTuple { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -496,15 +508,15 @@ macro_rules! impl_reflect_tuple { #[inline] fn clone_dynamic(&self) -> DynamicTuple { - let mut dyn_tuple = DynamicTuple { - name: String::default(), + let info = self.get_type_info(); + DynamicTuple { + name: Cow::Borrowed(info.type_name()), + represented_type: Some(info), fields: self .iter_fields() .map(|value| value.clone_value()) .collect(), - }; - dyn_tuple.generate_name(); - dyn_tuple + } } } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 33edd7bb172e3..8e8ee4b953bdf 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -1,3 +1,4 @@ +use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, @@ -222,19 +223,17 @@ impl GetTupleStructField for dyn TupleStruct { /// A tuple struct which allows fields to be added at runtime. #[derive(Default)] pub struct DynamicTupleStruct { - name: String, + represented_type: Option<&'static TypeInfo>, fields: Vec>, } impl DynamicTupleStruct { - /// Returns the type name of the tuple struct. - pub fn name(&self) -> &str { - &self.name - } - - /// Sets the type name of the tuple struct. - pub fn set_name(&mut self, name: String) { - self.name = name; + /// Sets the [type] to be [represented] by this `DynamicTupleStruct`. + /// + /// [type]: TypeInfo + /// [represented]: Proxy::represents + pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + self.represented_type = represented_type; } /// Appends an element with value `value` to the tuple struct. @@ -274,7 +273,7 @@ impl TupleStruct for DynamicTupleStruct { fn clone_dynamic(&self) -> DynamicTupleStruct { DynamicTupleStruct { - name: self.name.clone(), + represented_type: self.represented_type, fields: self .fields .iter() @@ -287,7 +286,9 @@ impl TupleStruct for DynamicTupleStruct { impl Reflect for DynamicTupleStruct { #[inline] fn type_name(&self) -> &str { - self.name.as_str() + self.represented_type + .map(|info| info.type_name()) + .unwrap_or_default() } #[inline] @@ -373,6 +374,12 @@ impl Reflect for DynamicTupleStruct { } } +impl Proxy for DynamicTupleStruct { + fn represents(&self) -> Option<&'static TypeInfo> { + self.represented_type + } +} + impl Debug for DynamicTupleStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.debug(f) diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 27df34ea767e3..50c3d68bd5992 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,7 +1,9 @@ +use crate::proxy::Proxy; use crate::{ ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, }; use std::any::{Any, TypeId}; +use std::fmt::{Debug, Formatter}; /// A static accessor to compile-time type information. /// @@ -227,27 +229,69 @@ impl ValueInfo { /// This is functionally the same as [`ValueInfo`], however, semantically it refers to dynamic /// types such as [`DynamicStruct`], [`DynamicTuple`], [`DynamicList`], etc. /// +/// This struct may also be used to extract the proxied [`TypeInfo`] from a dynamic type. +/// /// [`DynamicStruct`]: crate::DynamicStruct /// [`DynamicTuple`]: crate::DynamicTuple /// [`DynamicList`]: crate::DynamicList -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct DynamicInfo { type_name: &'static str, type_id: TypeId, + represents: fn(&dyn Reflect) -> Option<&'static TypeInfo>, #[cfg(feature = "documentation")] docs: Option<&'static str>, } +impl Debug for DynamicInfo { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut state = f.debug_struct("DynamicInfo"); + + state + .field("type_name", &self.type_name) + .field("type_name", &self.type_id); + + #[cfg(feature = "documentation")] + state.field("docs", &self.docs); + + state.finish() + } +} + impl DynamicInfo { - pub fn new() -> Self { + pub fn new() -> Self { + fn represents(value: &dyn Reflect) -> Option<&'static TypeInfo> { + let value: &T = value.downcast_ref().unwrap_or_else(|| { + panic!( + "expected dynamic type `{}`, but received `{}`", + std::any::type_name::(), + value.type_name() + ) + }); + value.represents() + } + Self { type_name: std::any::type_name::(), type_id: TypeId::of::(), + represents: represents::, #[cfg(feature = "documentation")] docs: None, } } + /// Returns the [type info] represented by the given dynamic type, if any. + /// + /// # Panics + /// + /// This method will panic if the given value is not the same type as the one + /// represented by this [`DynamicInfo`]. + /// + /// [type info]: TypeInfo + pub fn represents(&self, value: &dyn Reflect) -> Option<&'static TypeInfo> { + (self.represents)(value) + } + /// Sets the docstring for this dynamic value. #[cfg(feature = "documentation")] pub fn with_docs(self, docs: Option<&'static str>) -> Self { @@ -277,3 +321,19 @@ impl DynamicInfo { self.docs } } + +#[cfg(test)] +mod tests { + use crate::{DynamicArray, DynamicList, TypeInfo, Typed}; + + #[test] + #[should_panic( + expected = "expected dynamic type `bevy_reflect::array::DynamicArray`, but received ``" + )] + fn dynamic_represents_should_panic_on_type_mismatch() { + let TypeInfo::Dynamic(info) = DynamicArray::type_info() else { panic!("expected `TypeInfo::Dynamic`") }; + + let value = DynamicList::default(); + info.represents(&value); + } +} From 49616c8fe1bf4aa8ca28add3ee619a95211ec0b0 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 10 Jan 2023 23:18:56 -0700 Subject: [PATCH 02/11] Remove Proxy --- crates/bevy_reflect/src/array.rs | 15 +- crates/bevy_reflect/src/enums/dynamic_enum.rs | 10 +- crates/bevy_reflect/src/lib.rs | 1 - crates/bevy_reflect/src/list.rs | 11 +- crates/bevy_reflect/src/map.rs | 11 +- crates/bevy_reflect/src/proxy.rs | 191 ------------------ crates/bevy_reflect/src/reflect.rs | 16 ++ crates/bevy_reflect/src/struct_trait.rs | 11 +- crates/bevy_reflect/src/tuple.rs | 11 +- crates/bevy_reflect/src/tuple_struct.rs | 11 +- crates/bevy_reflect/src/type_info.rs | 44 +--- 11 files changed, 44 insertions(+), 288 deletions(-) delete mode 100644 crates/bevy_reflect/src/proxy.rs diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 7735ecf895482..e97003eb6c028 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,4 +1,3 @@ -use crate::proxy::Proxy; use crate::{ utility::{reflect_hasher, NonGenericTypeInfoCell}, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, @@ -192,10 +191,9 @@ impl DynamicArray { } } - /// Sets the [type] to be [represented] by this `DynamicArray`. + /// Sets the [type] to be represented by this `DynamicArray`. /// /// [type]: TypeInfo - /// [represented]: Proxy::represents pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { self.represented_type = represented_type; } @@ -282,6 +280,11 @@ impl Reflect for DynamicArray { fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { array_partial_eq(self, value) } + + #[inline] + fn is_dynamic(&self) -> bool { + true + } } impl Array for DynamicArray { @@ -323,12 +326,6 @@ impl Array for DynamicArray { } } -impl Proxy for DynamicArray { - fn represents(&self) -> Option<&'static TypeInfo> { - self.represented_type - } -} - impl Typed for DynamicArray { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index d10c51d8e0d08..70f4e8e482ea1 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -1,4 +1,3 @@ -use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, @@ -115,10 +114,9 @@ impl DynamicEnum { } } - /// Sets the [type] to be [represented] by this `DynamicEnum`. + /// Sets the [type] to be represented by this `DynamicEnum`. /// /// [type]: TypeInfo - /// [represented]: Proxy::represents pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { self.represented_type = represented_type; } @@ -413,12 +411,6 @@ impl Reflect for DynamicEnum { } } -impl Proxy for DynamicEnum { - fn represents(&self) -> Option<&'static TypeInfo> { - self.represented_type - } -} - impl Typed for DynamicEnum { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 28de45cbd7781..8b75615963d69 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -470,7 +470,6 @@ mod impls { } mod enums; -pub mod proxy; pub mod serde; pub mod std_traits; pub mod utility; diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 0f4b7ccf67e4c..3c33bd131e791 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -2,7 +2,6 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher}; -use crate::proxy::Proxy; use crate::utility::{reflect_hasher, NonGenericTypeInfoCell}; use crate::{ DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, @@ -183,10 +182,9 @@ pub struct DynamicList { } impl DynamicList { - /// Sets the [type] to be [represented] by this `DynamicList`. + /// Sets the [type] to be represented by this `DynamicList`. /// /// [type]: TypeInfo - /// [represented]: Proxy::represents pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { self.represented_type = represented_type; } @@ -338,11 +336,10 @@ impl Reflect for DynamicList { list_debug(self, f)?; write!(f, ")") } -} -impl Proxy for DynamicList { - fn represents(&self) -> Option<&'static TypeInfo> { - self.represented_type + #[inline] + fn is_dynamic(&self) -> bool { + true } } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 1a8a4ed032c41..c89942739178d 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -4,7 +4,6 @@ use std::hash::Hash; use bevy_utils::{Entry, HashMap}; -use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed}; @@ -191,10 +190,9 @@ pub struct DynamicMap { } impl DynamicMap { - /// Sets the [type] to be [represented] by this `DynamicMap`. + /// Sets the [type] to be represented by this `DynamicMap`. /// /// [type]: TypeInfo - /// [represented]: Proxy::represents pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { self.represented_type = represented_type; } @@ -353,11 +351,10 @@ impl Reflect for DynamicMap { map_debug(self, f)?; write!(f, ")") } -} -impl Proxy for DynamicMap { - fn represents(&self) -> Option<&'static TypeInfo> { - self.represented_type + #[inline] + fn is_dynamic(&self) -> bool { + true } } diff --git a/crates/bevy_reflect/src/proxy.rs b/crates/bevy_reflect/src/proxy.rs deleted file mode 100644 index 278a8f9a622a7..0000000000000 --- a/crates/bevy_reflect/src/proxy.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::{Reflect, TypeInfo}; - -/// This trait allows for types to behave as proxies to another type. -/// -/// This is mainly used by [dynamic] types such as [`DynamicStruct`], -/// [`DynamicList`], etc. -/// -/// [dynamic]: crate::TypeInfo::Dynamic -/// [`DynamicStruct`]: crate::DynamicStruct -/// [`DynamicList`]: crate::DynamicList -pub trait Proxy: Reflect { - /// Returns the [`TypeInfo`] of the type this proxy represents, if any. - /// - /// This will return `None` if the proxy currently does not represent any concrete type. - fn represents(&self) -> Option<&'static TypeInfo>; -} - -#[cfg(test)] -mod tests { - use super::Proxy; - use crate as bevy_reflect; - use crate::{ - Array, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, - DynamicTupleStruct, Enum, List, Map, Reflect, Struct, Tuple, TupleStruct, TypeInfo, Typed, - }; - use bevy_utils::HashMap; - - macro_rules! assert_proxy { - ($expected_type_info: ident, $proxy: ident) => { - assert_eq!( - $expected_type_info.type_name(), - $proxy.represents().unwrap().type_name() - ); - - let TypeInfo::Dynamic(info) = $proxy.get_type_info() else { panic!("expected `TypeInfo::Dynamic`") }; - assert_eq!( - $expected_type_info.type_name(), - info.represents(&$proxy).unwrap().type_name() - ) - }; - } - - #[test] - fn dynamic_tuple_should_represent_type() { - let expected = <(f32, f32) as Typed>::type_info(); - let mut dyn_tuple = DynamicTuple::default(); - dyn_tuple.insert(1.23_f32); - dyn_tuple.insert(3.21_f32); - - // Inserting to a DynamicTuple clears the represented type - assert!(dyn_tuple.represents().is_none()); - - dyn_tuple.set_represented_type(Some(expected)); - assert_proxy!(expected, dyn_tuple); - - let dyn_tuple = (1.23_f32, 3.21_f32).clone_dynamic(); - assert_proxy!(expected, dyn_tuple); - } - - #[test] - fn dynamic_array_should_represent_type() { - let expected = <[f32; 2] as Typed>::type_info(); - let mut dyn_array = DynamicArray::from_vec(vec![1.23_f32, 3.21_f32]); - - // DynamicArrays initialize without a represented type - assert!(dyn_array.represents().is_none()); - - dyn_array.set_represented_type(Some(expected)); - assert_proxy!(expected, dyn_array); - - let dyn_array = [1.23_f32, 3.21_f32].clone_dynamic(); - assert_proxy!(expected, dyn_array); - } - - #[test] - fn dynamic_list_should_represent_type() { - let expected = as Typed>::type_info(); - let mut dyn_list = DynamicList::default(); - dyn_list.push(1.23_f32); - dyn_list.push(3.21_f32); - - // DynamicLists initialize without a represented type - assert!(dyn_list.represents().is_none()); - - dyn_list.set_represented_type(Some(expected)); - assert_proxy!(expected, dyn_list); - - let dyn_list = List::clone_dynamic(&vec![1.23_f32, 3.21_f32]); - assert_proxy!(expected, dyn_list); - } - - #[test] - fn dynamic_map_should_represent_type() { - let expected = as Typed>::type_info(); - let mut dyn_map = DynamicMap::default(); - dyn_map.insert(0_usize, 1.23_f32); - dyn_map.insert(1_usize, 3.21_f32); - - // DynamicMaps initialize without a represented type - assert!(dyn_map.represents().is_none()); - - dyn_map.set_represented_type(Some(expected)); - assert_proxy!(expected, dyn_map); - - let mut map = HashMap::::new(); - map.insert(0_usize, 1.23_f32); - map.insert(1_usize, 3.21_f32); - let dyn_map = map.clone_dynamic(); - assert_proxy!(expected, dyn_map); - } - - #[test] - fn dynamic_tuple_struct_should_represent_type() { - #[derive(Reflect)] - struct MyTupleStruct(f32, f32); - - let expected = ::type_info(); - let mut dyn_tuple_struct = DynamicTupleStruct::default(); - dyn_tuple_struct.insert(1.23_f32); - dyn_tuple_struct.insert(3.21_f32); - - // DynamicTupleStructs initialize without a represented type - assert!(dyn_tuple_struct.represents().is_none()); - - dyn_tuple_struct.set_represented_type(Some(expected)); - assert_proxy!(expected, dyn_tuple_struct); - - let dyn_tuple_struct = MyTupleStruct(1.23_f32, 3.21_f32).clone_dynamic(); - assert_proxy!(expected, dyn_tuple_struct); - } - - #[test] - fn dynamic_struct_should_represent_type() { - #[derive(Reflect)] - struct MyStruct { - foo: f32, - bar: f32, - } - - let expected = ::type_info(); - let mut dyn_struct = DynamicStruct::default(); - dyn_struct.insert("foo", 1.23_f32); - dyn_struct.insert("bar", 3.21_f32); - - // DynamicStructs initialize without a represented type - assert!(dyn_struct.represents().is_none()); - - dyn_struct.set_represented_type(Some(expected)); - assert_proxy!(expected, dyn_struct); - - let dyn_struct = MyStruct { - foo: 1.23_f32, - bar: 3.21_f32, - } - .clone_dynamic(); - assert_proxy!(expected, dyn_struct); - } - - #[test] - fn dynamic_enum_should_represent_type() { - #[derive(Reflect)] - enum MyEnum { - Unit, - Tuple(f32, f32), - Struct { foo: f32, bar: f32 }, - } - - let expected = ::type_info(); - let mut dyn_enum = DynamicEnum::default(); - dyn_enum.set_variant("Unit", ()); - - // DynamicEnums initialize without a represented type - assert!(dyn_enum.represents().is_none()); - - dyn_enum.set_represented_type(Some(expected)); - assert_proxy!(expected, dyn_enum); - - let dyn_unit_enum = MyEnum::Unit.clone_dynamic(); - assert_proxy!(expected, dyn_unit_enum); - - let dyn_tuple_enum = MyEnum::Tuple(1.23, 3.21).clone_dynamic(); - assert_proxy!(expected, dyn_tuple_enum); - - let dyn_struct_enum = MyEnum::Struct { - foo: 1.23_f32, - bar: 3.21_f32, - } - .clone_dynamic(); - assert_proxy!(expected, dyn_struct_enum); - } -} diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 8abfeef742fbd..bf77793e60c2c 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -216,6 +216,22 @@ pub trait Reflect: Any + Send + Sync { fn serializable(&self) -> Option { None } + + /// Indicates whether or not this type is a _dynamic_ type. + /// + /// Dynamic types include the ones built-in to this [crate], + /// such as [`DynamicStruct`], [`DynamicList`], and [`DynamicTuple`]. + /// However, they may be custom types used as proxies for other types + /// or to facilitate scripting capabilities. + /// + /// By default, this method will return `false`. + /// + /// [`DynamicStruct`]: crate::DynamicStruct + /// [`DynamicList`]: crate::DynamicList + /// [`DynamicTuple`]: crate::DynamicTuple + fn is_dynamic(&self) -> bool { + false + } } impl Debug for dyn Reflect { diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 0555ea3d202f7..a4804132db4d0 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,4 +1,3 @@ -use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, @@ -280,10 +279,9 @@ pub struct DynamicStruct { } impl DynamicStruct { - /// Sets the [type] to be [represented] by this `DynamicStruct`. + /// Sets the [type] to be represented by this `DynamicStruct`. /// /// [type]: TypeInfo - /// [represented]: Proxy::represents pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { self.represented_type = represented_type; } @@ -471,11 +469,10 @@ impl Reflect for DynamicStruct { struct_debug(self, f)?; write!(f, ")") } -} -impl Proxy for DynamicStruct { - fn represents(&self) -> Option<&'static TypeInfo> { - self.represented_type + #[inline] + fn is_dynamic(&self) -> bool { + true } } diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 4933b1065ff18..dec658dcdcc80 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,4 +1,3 @@ -use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, @@ -215,10 +214,9 @@ pub struct DynamicTuple { } impl DynamicTuple { - /// Sets the [type] to be [represented] by this `DynamicTuple`. + /// Sets the [type] to be represented by this `DynamicTuple`. /// /// [type]: TypeInfo - /// [represented]: Proxy::represents pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { if let Some(info) = represented_type { self.name = Cow::Borrowed(info.type_name()); @@ -379,11 +377,10 @@ impl Reflect for DynamicTuple { tuple_debug(self, f)?; write!(f, ")") } -} -impl Proxy for DynamicTuple { - fn represents(&self) -> Option<&'static TypeInfo> { - self.represented_type + #[inline] + fn is_dynamic(&self) -> bool { + true } } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 8e8ee4b953bdf..04049035c9450 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -1,4 +1,3 @@ -use crate::proxy::Proxy; use crate::utility::NonGenericTypeInfoCell; use crate::{ DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, @@ -228,10 +227,9 @@ pub struct DynamicTupleStruct { } impl DynamicTupleStruct { - /// Sets the [type] to be [represented] by this `DynamicTupleStruct`. + /// Sets the [type] to be represented by this `DynamicTupleStruct`. /// /// [type]: TypeInfo - /// [represented]: Proxy::represents pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { self.represented_type = represented_type; } @@ -372,11 +370,10 @@ impl Reflect for DynamicTupleStruct { tuple_struct_debug(self, f)?; write!(f, ")") } -} -impl Proxy for DynamicTupleStruct { - fn represents(&self) -> Option<&'static TypeInfo> { - self.represented_type + #[inline] + fn is_dynamic(&self) -> bool { + true } } diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 50c3d68bd5992..854f838cc3487 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,4 +1,3 @@ -use crate::proxy::Proxy; use crate::{ ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, }; @@ -238,7 +237,6 @@ impl ValueInfo { pub struct DynamicInfo { type_name: &'static str, type_id: TypeId, - represents: fn(&dyn Reflect) -> Option<&'static TypeInfo>, #[cfg(feature = "documentation")] docs: Option<&'static str>, } @@ -259,39 +257,15 @@ impl Debug for DynamicInfo { } impl DynamicInfo { - pub fn new() -> Self { - fn represents(value: &dyn Reflect) -> Option<&'static TypeInfo> { - let value: &T = value.downcast_ref().unwrap_or_else(|| { - panic!( - "expected dynamic type `{}`, but received `{}`", - std::any::type_name::(), - value.type_name() - ) - }); - value.represents() - } - + pub fn new() -> Self { Self { type_name: std::any::type_name::(), type_id: TypeId::of::(), - represents: represents::, #[cfg(feature = "documentation")] docs: None, } } - /// Returns the [type info] represented by the given dynamic type, if any. - /// - /// # Panics - /// - /// This method will panic if the given value is not the same type as the one - /// represented by this [`DynamicInfo`]. - /// - /// [type info]: TypeInfo - pub fn represents(&self, value: &dyn Reflect) -> Option<&'static TypeInfo> { - (self.represents)(value) - } - /// Sets the docstring for this dynamic value. #[cfg(feature = "documentation")] pub fn with_docs(self, docs: Option<&'static str>) -> Self { @@ -321,19 +295,3 @@ impl DynamicInfo { self.docs } } - -#[cfg(test)] -mod tests { - use crate::{DynamicArray, DynamicList, TypeInfo, Typed}; - - #[test] - #[should_panic( - expected = "expected dynamic type `bevy_reflect::array::DynamicArray`, but received ``" - )] - fn dynamic_represents_should_panic_on_type_mismatch() { - let TypeInfo::Dynamic(info) = DynamicArray::type_info() else { panic!("expected `TypeInfo::Dynamic`") }; - - let value = DynamicList::default(); - info.represents(&value); - } -} From 71f20b4cce073c609488cd0f5f0f7aef72dad8ae Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 19 Feb 2023 16:51:24 -0700 Subject: [PATCH 03/11] Rename get_type_info -> represented_type_info --- .../bevy_reflect_derive/src/impls/enums.rs | 2 +- .../bevy_reflect_derive/src/impls/structs.rs | 4 ++-- .../src/impls/tuple_structs.rs | 4 ++-- .../bevy_reflect_derive/src/impls/values.rs | 2 +- crates/bevy_reflect/src/array.rs | 4 ++-- crates/bevy_reflect/src/enums/dynamic_enum.rs | 4 ++-- crates/bevy_reflect/src/impls/smallvec.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 14 ++++++------- crates/bevy_reflect/src/lib.rs | 20 +++++++++---------- crates/bevy_reflect/src/list.rs | 4 ++-- crates/bevy_reflect/src/map.rs | 2 +- crates/bevy_reflect/src/reflect.rs | 9 +++++++-- crates/bevy_reflect/src/serde/ser.rs | 6 +++--- crates/bevy_reflect/src/struct_trait.rs | 4 ++-- crates/bevy_reflect/src/tuple.rs | 6 +++--- crates/bevy_reflect/src/tuple_struct.rs | 2 +- crates/bevy_reflect/src/type_info.rs | 8 ++++---- crates/bevy_reflect/src/utility.rs | 4 ++-- 18 files changed, 53 insertions(+), 48 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index 666283615d985..4c050984a7703 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -192,7 +192,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } #[inline] - fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { + fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { ::type_info() } 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 726a7d9bd1d18..c5e25597f90e3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -151,7 +151,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicStruct { let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default(); - dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::get_type_info(self))); + dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::represented_type_info(self))); #(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } @@ -164,7 +164,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } #[inline] - fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { + fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { ::type_info() } 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 2f5995e6820d8..8ddd4ed0f6f08 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 @@ -122,7 +122,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct { let mut dynamic: #bevy_reflect_path::DynamicTupleStruct = #FQDefault::default(); - dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::get_type_info(self))); + dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::represented_type_info(self))); #(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } @@ -135,7 +135,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } #[inline] - fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { + fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs index 4aa3aed418fb6..d79ff5a8f7e07 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -49,7 +49,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { } #[inline] - fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { + fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index e97003eb6c028..cb835d0c56d5e 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -67,7 +67,7 @@ pub trait Array: Reflect { /// Clones the list, producing a [`DynamicArray`]. fn clone_dynamic(&self) -> DynamicArray { DynamicArray { - represented_type: Some(self.get_type_info()), + represented_type: Some(self.represented_type_info()), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -208,7 +208,7 @@ impl Reflect for DynamicArray { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 70f4e8e482ea1..7da3920659be4 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -150,7 +150,7 @@ impl DynamicEnum { /// /// This is functionally the same as [`DynamicEnum::from`] except it takes a reference. pub fn from_ref(value: &TEnum) -> Self { - let type_info = value.get_type_info(); + let type_info = value.represented_type_info(); let mut dyn_enum = match value.variant_type() { VariantType::Unit => DynamicEnum::new_with_index( value.variant_index(), @@ -283,7 +283,7 @@ impl Reflect for DynamicEnum { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 769c541d9d6cf..11b497a1de2a3 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -82,7 +82,7 @@ where std::any::type_name::() } - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index f88bd5eb96103..7ad88e51c40b2 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -244,7 +244,7 @@ macro_rules! impl_reflect_for_veclike { std::any::type_name::() } - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } @@ -397,7 +397,7 @@ macro_rules! impl_reflect_for_hashmap { fn clone_dynamic(&self) -> DynamicMap { let mut dynamic_map = DynamicMap::default(); - dynamic_map.set_represented_type(Some(self.get_type_info())); + dynamic_map.set_represented_type(Some(self.represented_type_info())); for (k, v) in self { let key = K::from_reflect(k).unwrap_or_else(|| { panic!("Attempted to clone invalid key of type {}.", k.type_name()) @@ -450,7 +450,7 @@ macro_rules! impl_reflect_for_hashmap { std::any::type_name::() } - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } @@ -595,7 +595,7 @@ impl Reflect for [T; N] { std::any::type_name::() } - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } @@ -800,7 +800,7 @@ impl Reflect for Option { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } @@ -965,7 +965,7 @@ impl Reflect for Cow<'static, str> { std::any::type_name::() } - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } @@ -1073,7 +1073,7 @@ impl Reflect for &'static Path { std::any::type_name::() } - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 8b75615963d69..8eddfaf257db3 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1100,7 +1100,7 @@ mod tests { // TypeInfo (instance) let value: &dyn Reflect = &123_i32; - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); // Struct @@ -1133,7 +1133,7 @@ mod tests { } let value: &dyn Reflect = &MyStruct { foo: 123, bar: 321 }; - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); // Struct (generic) @@ -1167,7 +1167,7 @@ mod tests { foo: String::from("Hello!"), bar: 321, }; - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::>()); // Tuple Struct @@ -1203,7 +1203,7 @@ mod tests { } let value: &dyn Reflect = &(123_u32, 1.23_f32, String::from("Hello!")); - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); // List @@ -1220,7 +1220,7 @@ mod tests { } let value: &dyn Reflect = &vec![123_usize]; - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); // List (SmallVec) @@ -1240,7 +1240,7 @@ mod tests { let value: MySmallVec = smallvec::smallvec![String::default(); 2]; let value: &dyn Reflect = &value; - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); } @@ -1259,7 +1259,7 @@ mod tests { } let value: &dyn Reflect = &[1usize, 2usize, 3usize]; - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); // Map @@ -1278,7 +1278,7 @@ mod tests { } let value: &dyn Reflect = &MyMap::new(); - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); // Value @@ -1293,7 +1293,7 @@ mod tests { } let value: &dyn Reflect = &String::from("Hello!"); - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); // Dynamic @@ -1308,7 +1308,7 @@ mod tests { } let value: &dyn Reflect = &DynamicList::default(); - let info = value.get_type_info(); + let info = value.represented_type_info(); assert!(info.is::()); } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 3c33bd131e791..f8bf3a237bd8a 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -97,7 +97,7 @@ pub trait List: Reflect { /// Clones the list, producing a [`DynamicList`]. fn clone_dynamic(&self) -> DynamicList { DynamicList { - represented_type: Some(self.get_type_info()), + represented_type: Some(self.represented_type_info()), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -258,7 +258,7 @@ impl Reflect for DynamicList { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index c89942739178d..31ae9507e2534 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -286,7 +286,7 @@ impl Reflect for DynamicMap { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index bf77793e60c2c..443b3e70bf05c 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -76,7 +76,12 @@ pub trait Reflect: Any + Send + Sync { /// Returns the [type name][std::any::type_name] of the underlying type. fn type_name(&self) -> &str; - /// Returns the [`TypeInfo`] of the underlying type. + /// Returns the [`TypeInfo`] of the type _represented_ by this value. + /// + /// For most types, this will simply return their own `TypeInfo`. + /// However, for dynamic types, such as [`DynamicStruct`] or [`DynamicList`], + /// this will return the type they represent + /// (or `None` if they don't represent any particular type). /// /// This method is great if you have an instance of a type or a `dyn Reflect`, /// and want to access its [`TypeInfo`]. However, if this method is to be called @@ -84,7 +89,7 @@ pub trait Reflect: Any + Send + Sync { /// performant for such use cases. /// /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info - fn get_type_info(&self) -> &'static TypeInfo; + fn represented_type_info(&self) -> &'static TypeInfo; /// Returns the value as a [`Box`][std::any::Any]. fn into_any(self: Box) -> Box; diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index e9e4abe1d852d..9ee1acbf3ccc4 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -187,7 +187,7 @@ impl<'a> Serialize for StructSerializer<'a> { S: serde::Serializer, { let type_info = get_type_info( - self.struct_value.get_type_info(), + self.struct_value.represented_type_info(), self.struct_value.type_name(), self.registry, )?; @@ -236,7 +236,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> { S: serde::Serializer, { let type_info = get_type_info( - self.tuple_struct.get_type_info(), + self.tuple_struct.represented_type_info(), self.tuple_struct.type_name(), self.registry, )?; @@ -284,7 +284,7 @@ impl<'a> Serialize for EnumSerializer<'a> { S: serde::Serializer, { let type_info = get_type_info( - self.enum_value.get_type_info(), + self.enum_value.represented_type_info(), self.enum_value.type_name(), self.registry, )?; diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index a4804132db4d0..e7117f6090a40 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -367,7 +367,7 @@ impl Struct for DynamicStruct { fn clone_dynamic(&self) -> DynamicStruct { DynamicStruct { - represented_type: Some(self.get_type_info()), + represented_type: Some(self.represented_type_info()), field_names: self.field_names.clone(), field_indices: self.field_indices.clone(), fields: self @@ -388,7 +388,7 @@ impl Reflect for DynamicStruct { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index dec658dcdcc80..fa4b0767f3f77 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -305,7 +305,7 @@ impl Reflect for DynamicTuple { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } @@ -505,7 +505,7 @@ macro_rules! impl_reflect_tuple { #[inline] fn clone_dynamic(&self) -> DynamicTuple { - let info = self.get_type_info(); + let info = self.represented_type_info(); DynamicTuple { name: Cow::Borrowed(info.type_name()), represented_type: Some(info), @@ -522,7 +522,7 @@ macro_rules! impl_reflect_tuple { std::any::type_name::() } - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 04049035c9450..4a4e687b01b2e 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -290,7 +290,7 @@ impl Reflect for DynamicTupleStruct { } #[inline] - fn get_type_info(&self) -> &'static TypeInfo { + fn represented_type_info(&self) -> &'static TypeInfo { ::type_info() } diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 854f838cc3487..177a9c1f6b69d 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -50,7 +50,7 @@ use std::fmt::{Debug, Formatter}; /// # /// # impl Reflect for MyStruct { /// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn represented_type_info(&self) -> &'static TypeInfo { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } @@ -79,12 +79,12 @@ pub trait Typed: Reflect { /// Generally, for any given type, this value can be retrieved one of three ways: /// /// 1. [`Typed::type_info`] -/// 2. [`Reflect::get_type_info`] +/// 2. [`Reflect::represented_type_info`] /// 3. [`TypeRegistry::get_type_info`] /// /// Each return a static reference to [`TypeInfo`], but they all have their own use cases. /// For example, if you know the type at compile time, [`Typed::type_info`] is probably -/// the simplest. If all you have is a `dyn Reflect`, you'll probably want [`Reflect::get_type_info`]. +/// the simplest. If all you have is a `dyn Reflect`, you'll probably want [`Reflect::represented_type_info`]. /// Lastly, if all you have is a [`TypeId`] or [type name], you will need to go through /// [`TypeRegistry::get_type_info`]. /// @@ -92,7 +92,7 @@ pub trait Typed: Reflect { /// it can be more performant. This is because those other methods may require attaining a lock on /// the static [`TypeInfo`], while the registry simply checks a map. /// -/// [`Reflect::get_type_info`]: crate::Reflect::get_type_info +/// [`Reflect::represented_type_info`]: crate::Reflect::represented_type_info /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info /// [`TypeId`]: std::any::TypeId /// [type name]: std::any::type_name diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 3af535a1925ca..14c09f58c69e8 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -39,7 +39,7 @@ use std::{ /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn represented_type_info(&self) -> &'static TypeInfo { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } @@ -102,7 +102,7 @@ impl NonGenericTypeInfoCell { /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn represented_type_info(&self) -> &'static TypeInfo { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } From 63e169e56f7e13158d46ed5422f05a5d7debcd35 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 19 Feb 2023 17:17:28 -0700 Subject: [PATCH 04/11] Remove DynamicInfo --- crates/bevy_reflect/src/array.rs | 14 +--- crates/bevy_reflect/src/enums/dynamic_enum.rs | 15 +--- crates/bevy_reflect/src/lib.rs | 15 ---- crates/bevy_reflect/src/list.rs | 15 +--- crates/bevy_reflect/src/map.rs | 12 +-- crates/bevy_reflect/src/serde/de.rs | 7 -- crates/bevy_reflect/src/serde/ser.rs | 38 +-------- crates/bevy_reflect/src/struct_trait.rs | 14 +--- crates/bevy_reflect/src/tuple.rs | 14 +--- crates/bevy_reflect/src/tuple_struct.rs | 14 +--- crates/bevy_reflect/src/type_info.rs | 82 +------------------ 11 files changed, 21 insertions(+), 219 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index cb835d0c56d5e..55375aeedeb74 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,7 +1,4 @@ -use crate::{ - utility::{reflect_hasher, NonGenericTypeInfoCell}, - DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, -}; +use crate::{utility::reflect_hasher, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo}; use std::{ any::{Any, TypeId}, fmt::Debug, @@ -209,7 +206,7 @@ impl Reflect for DynamicArray { #[inline] fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + todo!("make this method return Option<&'static TypeInfo> to support dynamic types") } #[inline] @@ -326,13 +323,6 @@ impl Array for DynamicArray { } } -impl Typed for DynamicArray { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } -} - /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { array: &'a dyn Array, diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 7da3920659be4..ead9a2e983acc 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -1,8 +1,6 @@ -use crate::utility::NonGenericTypeInfoCell; use crate::{ - enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, - Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, Typed, - VariantFieldIter, VariantType, + enum_debug, enum_hash, enum_partial_eq, DynamicStruct, DynamicTuple, Enum, Reflect, ReflectMut, + ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, VariantFieldIter, VariantType, }; use std::any::Any; use std::fmt::Formatter; @@ -284,7 +282,7 @@ impl Reflect for DynamicEnum { #[inline] fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + todo!("make this method return Option<&'static TypeInfo> to support dynamic types") } #[inline] @@ -410,10 +408,3 @@ impl Reflect for DynamicEnum { write!(f, ")") } } - -impl Typed for DynamicEnum { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } -} diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 8eddfaf257db3..81febe1a94d08 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1295,21 +1295,6 @@ mod tests { let value: &dyn Reflect = &String::from("Hello!"); let info = value.represented_type_info(); assert!(info.is::()); - - // Dynamic - type MyDynamic = DynamicList; - - let info = MyDynamic::type_info(); - if let TypeInfo::Dynamic(info) = info { - assert!(info.is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - } else { - panic!("Expected `TypeInfo::Dynamic`"); - } - - let value: &dyn Reflect = &DynamicList::default(); - let info = value.represented_type_info(); - assert!(info.is::()); } #[cfg(feature = "documentation")] diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index f8bf3a237bd8a..0561517349662 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -2,10 +2,8 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher}; -use crate::utility::{reflect_hasher, NonGenericTypeInfoCell}; -use crate::{ - DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, -}; +use crate::utility::reflect_hasher; +use crate::{FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo}; /// A trait used to power [list-like] operations via [reflection]. /// @@ -259,7 +257,7 @@ impl Reflect for DynamicList { #[inline] fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + todo!("make this method return Option<&'static TypeInfo> to support dynamic types") } #[inline] @@ -349,13 +347,6 @@ impl Debug for DynamicList { } } -impl Typed for DynamicList { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } -} - impl IntoIterator for DynamicList { type Item = Box; type IntoIter = std::vec::IntoIter; diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 31ae9507e2534..6f5a26b9b2aae 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -4,8 +4,7 @@ use std::hash::Hash; use bevy_utils::{Entry, HashMap}; -use crate::utility::NonGenericTypeInfoCell; -use crate::{DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed}; +use crate::{Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo}; /// A trait used to power [map-like] operations via [reflection]. /// @@ -287,7 +286,7 @@ impl Reflect for DynamicMap { #[inline] fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + todo!("make this method return Option<&'static TypeInfo> to support dynamic types") } fn into_any(self: Box) -> Box { @@ -364,13 +363,6 @@ impl Debug for DynamicMap { } } -impl Typed for DynamicMap { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } -} - /// An iterator over the key-value pairs of a [`Map`]. pub struct MapIter<'a> { pub(crate) map: &'a dyn Map, diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index ebf0b40a85b00..de7c47438104c 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -470,13 +470,6 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { "the TypeRegistration for {type_name} doesn't have ReflectDeserialize", ))) } - 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}", - ))) - } } } } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 9ee1acbf3ccc4..d34cc72368fc0 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -43,26 +43,6 @@ 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: @@ -186,11 +166,7 @@ impl<'a> Serialize for StructSerializer<'a> { where S: serde::Serializer, { - let type_info = get_type_info( - self.struct_value.represented_type_info(), - self.struct_value.type_name(), - self.registry, - )?; + let type_info = self.struct_value.represented_type_info(); let struct_info = match type_info { TypeInfo::Struct(struct_info) => struct_info, @@ -235,11 +211,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> { where S: serde::Serializer, { - let type_info = get_type_info( - self.tuple_struct.represented_type_info(), - self.tuple_struct.type_name(), - self.registry, - )?; + let type_info = self.tuple_struct.represented_type_info(); let tuple_struct_info = match type_info { TypeInfo::TupleStruct(tuple_struct_info) => tuple_struct_info, @@ -283,11 +255,7 @@ impl<'a> Serialize for EnumSerializer<'a> { where S: serde::Serializer, { - let type_info = get_type_info( - self.enum_value.represented_type_info(), - self.enum_value.type_name(), - self.registry, - )?; + let type_info = self.enum_value.represented_type_info(); let enum_info = match type_info { TypeInfo::Enum(enum_info) => enum_info, diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index e7117f6090a40..629d89ebcb726 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,7 +1,4 @@ -use crate::utility::NonGenericTypeInfoCell; -use crate::{ - DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, -}; +use crate::{NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo}; use bevy_utils::{Entry, HashMap}; use std::fmt::{Debug, Formatter}; use std::{ @@ -389,7 +386,7 @@ impl Reflect for DynamicStruct { #[inline] fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + todo!("make this method return Option<&'static TypeInfo> to support dynamic types") } #[inline] @@ -482,13 +479,6 @@ impl Debug for DynamicStruct { } } -impl Typed for DynamicStruct { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } -} - /// Compares a [`Struct`] with a [`Reflect`] value. /// /// Returns true if and only if all of the following are true: diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index fa4b0767f3f77..454eb11c8b262 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,7 +1,6 @@ -use crate::utility::NonGenericTypeInfoCell; use crate::{ - DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, TypeRegistration, Typed, UnnamedField, + FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + TypeRegistration, Typed, UnnamedField, }; use std::any::{Any, TypeId}; use std::borrow::Cow; @@ -306,7 +305,7 @@ impl Reflect for DynamicTuple { #[inline] fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + todo!("make this method return Option<&'static TypeInfo> to support dynamic types") } #[inline] @@ -384,13 +383,6 @@ impl Reflect for DynamicTuple { } } -impl Typed for DynamicTuple { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } -} - /// Applies the elements of `b` to the corresponding elements of `a`. /// /// # Panics diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 4a4e687b01b2e..87147cd8f6d98 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -1,7 +1,4 @@ -use crate::utility::NonGenericTypeInfoCell; -use crate::{ - DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, -}; +use crate::{Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, UnnamedField}; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::slice::Iter; @@ -291,7 +288,7 @@ impl Reflect for DynamicTupleStruct { #[inline] fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + todo!("make this method return Option<&'static TypeInfo> to support dynamic types") } #[inline] @@ -383,13 +380,6 @@ impl Debug for DynamicTupleStruct { } } -impl Typed for DynamicTupleStruct { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } -} - /// Compares a [`TupleStruct`] with a [`Reflect`] value. /// /// Returns true if and only if all of the following are true: diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 177a9c1f6b69d..d2160e0105768 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -2,7 +2,7 @@ use crate::{ ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, }; use std::any::{Any, TypeId}; -use std::fmt::{Debug, Formatter}; +use std::fmt::Debug; /// A static accessor to compile-time type information. /// @@ -106,10 +106,6 @@ pub enum TypeInfo { Map(MapInfo), Enum(EnumInfo), Value(ValueInfo), - /// Type information for "dynamic" types whose metadata can't be known at compile-time. - /// - /// This includes structs like [`DynamicStruct`](crate::DynamicStruct) and [`DynamicList`](crate::DynamicList). - Dynamic(DynamicInfo), } impl TypeInfo { @@ -124,7 +120,6 @@ impl TypeInfo { Self::Map(info) => info.type_id(), Self::Enum(info) => info.type_id(), Self::Value(info) => info.type_id(), - Self::Dynamic(info) => info.type_id(), } } @@ -141,7 +136,6 @@ impl TypeInfo { Self::Map(info) => info.type_name(), Self::Enum(info) => info.type_name(), Self::Value(info) => info.type_name(), - Self::Dynamic(info) => info.type_name(), } } @@ -162,7 +156,6 @@ impl TypeInfo { Self::Map(info) => info.docs(), Self::Enum(info) => info.docs(), Self::Value(info) => info.docs(), - Self::Dynamic(info) => info.docs(), } } } @@ -222,76 +215,3 @@ impl ValueInfo { self.docs } } - -/// A container for compile-time info related to Bevy's _dynamic_ types, including primitives. -/// -/// This is functionally the same as [`ValueInfo`], however, semantically it refers to dynamic -/// types such as [`DynamicStruct`], [`DynamicTuple`], [`DynamicList`], etc. -/// -/// This struct may also be used to extract the proxied [`TypeInfo`] from a dynamic type. -/// -/// [`DynamicStruct`]: crate::DynamicStruct -/// [`DynamicTuple`]: crate::DynamicTuple -/// [`DynamicList`]: crate::DynamicList -#[derive(Clone)] -pub struct DynamicInfo { - type_name: &'static str, - type_id: TypeId, - #[cfg(feature = "documentation")] - docs: Option<&'static str>, -} - -impl Debug for DynamicInfo { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let mut state = f.debug_struct("DynamicInfo"); - - state - .field("type_name", &self.type_name) - .field("type_name", &self.type_id); - - #[cfg(feature = "documentation")] - state.field("docs", &self.docs); - - state.finish() - } -} - -impl DynamicInfo { - pub fn new() -> Self { - Self { - type_name: std::any::type_name::(), - type_id: TypeId::of::(), - #[cfg(feature = "documentation")] - docs: None, - } - } - - /// Sets the docstring for this dynamic value. - #[cfg(feature = "documentation")] - pub fn with_docs(self, docs: Option<&'static str>) -> Self { - Self { docs, ..self } - } - - /// The [type name] of the dynamic value. - /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name - } - - /// The [`TypeId`] of the dynamic value. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the dynamic value type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } - - /// The docstring of this value, if any. - #[cfg(feature = "documentation")] - pub fn docs(&self) -> Option<&'static str> { - self.docs - } -} From 1358859892820fef4563b6eaffe4cf5332fef7e0 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 19 Feb 2023 17:23:00 -0700 Subject: [PATCH 05/11] Make Reflect::represented_type_info return an Option --- .../bevy_reflect_derive/src/impls/enums.rs | 4 +-- .../bevy_reflect_derive/src/impls/structs.rs | 6 ++--- .../src/impls/tuple_structs.rs | 6 ++--- .../bevy_reflect_derive/src/impls/values.rs | 4 +-- crates/bevy_reflect/src/array.rs | 6 ++--- crates/bevy_reflect/src/enums/dynamic_enum.rs | 6 ++--- crates/bevy_reflect/src/impls/smallvec.rs | 4 +-- crates/bevy_reflect/src/impls/std.rs | 26 +++++++++---------- crates/bevy_reflect/src/lib.rs | 18 ++++++------- crates/bevy_reflect/src/list.rs | 6 ++--- crates/bevy_reflect/src/map.rs | 4 +-- crates/bevy_reflect/src/reflect.rs | 2 +- crates/bevy_reflect/src/serde/ser.rs | 21 ++++++++++++--- crates/bevy_reflect/src/struct_trait.rs | 6 ++--- crates/bevy_reflect/src/tuple.rs | 12 ++++----- crates/bevy_reflect/src/tuple_struct.rs | 4 +-- crates/bevy_reflect/src/type_info.rs | 2 +- crates/bevy_reflect/src/utility.rs | 4 +-- 18 files changed, 78 insertions(+), 63 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index 4c050984a7703..762ccb1347401 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -192,8 +192,8 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { - ::type_info() + fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + #FQOption::Some(::type_info()) } #[inline] 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 c5e25597f90e3..17abb5db72949 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -151,7 +151,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicStruct { let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default(); - dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::represented_type_info(self))); + dynamic.set_represented_type(#bevy_reflect_path::Reflect::represented_type_info(self)); #(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } @@ -164,8 +164,8 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { - ::type_info() + fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + #FQOption::Some(::type_info()) } #[inline] 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 8ddd4ed0f6f08..a654c2ec9556b 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 @@ -122,7 +122,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct { let mut dynamic: #bevy_reflect_path::DynamicTupleStruct = #FQDefault::default(); - dynamic.set_represented_type(#FQOption::Some(#bevy_reflect_path::Reflect::represented_type_info(self))); + dynamic.set_represented_type(#bevy_reflect_path::Reflect::represented_type_info(self)); #(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } @@ -135,8 +135,8 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { - ::type_info() + fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + #FQOption::Some(::type_info()) } #[inline] diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs index d79ff5a8f7e07..524740ce73bd0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -49,8 +49,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo { - ::type_info() + fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + #FQOption::Some(::type_info()) } #[inline] diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 55375aeedeb74..2f622ba9a5993 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -64,7 +64,7 @@ pub trait Array: Reflect { /// Clones the list, producing a [`DynamicArray`]. fn clone_dynamic(&self) -> DynamicArray { DynamicArray { - represented_type: Some(self.represented_type_info()), + represented_type: self.represented_type_info(), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -205,8 +205,8 @@ impl Reflect for DynamicArray { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - todo!("make this method return Option<&'static TypeInfo> to support dynamic types") + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + self.represented_type } #[inline] diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index ead9a2e983acc..ea2df967c22b8 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -180,7 +180,7 @@ impl DynamicEnum { } }; - dyn_enum.set_represented_type(Some(type_info)); + dyn_enum.set_represented_type(type_info); dyn_enum } } @@ -281,8 +281,8 @@ impl Reflect for DynamicEnum { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - todo!("make this method return Option<&'static TypeInfo> to support dynamic types") + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + self.represented_type } #[inline] diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 11b497a1de2a3..45c6d957d5b0e 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -82,8 +82,8 @@ where std::any::type_name::() } - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 7ad88e51c40b2..85d1695d4e88e 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -244,8 +244,8 @@ macro_rules! impl_reflect_for_veclike { std::any::type_name::() } - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } fn into_any(self: Box) -> Box { @@ -397,7 +397,7 @@ macro_rules! impl_reflect_for_hashmap { fn clone_dynamic(&self) -> DynamicMap { let mut dynamic_map = DynamicMap::default(); - dynamic_map.set_represented_type(Some(self.represented_type_info())); + dynamic_map.set_represented_type(self.represented_type_info()); for (k, v) in self { let key = K::from_reflect(k).unwrap_or_else(|| { panic!("Attempted to clone invalid key of type {}.", k.type_name()) @@ -450,8 +450,8 @@ macro_rules! impl_reflect_for_hashmap { std::any::type_name::() } - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } fn into_any(self: Box) -> Box { @@ -595,8 +595,8 @@ impl Reflect for [T; N] { std::any::type_name::() } - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } #[inline] @@ -800,8 +800,8 @@ impl Reflect for Option { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } #[inline] @@ -965,8 +965,8 @@ impl Reflect for Cow<'static, str> { std::any::type_name::() } - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } fn into_any(self: Box) -> Box { @@ -1073,8 +1073,8 @@ impl Reflect for &'static Path { std::any::type_name::() } - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 81febe1a94d08..7d591d396c1b3 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1100,7 +1100,7 @@ mod tests { // TypeInfo (instance) let value: &dyn Reflect = &123_i32; - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); // Struct @@ -1133,7 +1133,7 @@ mod tests { } let value: &dyn Reflect = &MyStruct { foo: 123, bar: 321 }; - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); // Struct (generic) @@ -1167,7 +1167,7 @@ mod tests { foo: String::from("Hello!"), bar: 321, }; - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::>()); // Tuple Struct @@ -1203,7 +1203,7 @@ mod tests { } let value: &dyn Reflect = &(123_u32, 1.23_f32, String::from("Hello!")); - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); // List @@ -1220,7 +1220,7 @@ mod tests { } let value: &dyn Reflect = &vec![123_usize]; - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); // List (SmallVec) @@ -1240,7 +1240,7 @@ mod tests { let value: MySmallVec = smallvec::smallvec![String::default(); 2]; let value: &dyn Reflect = &value; - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); } @@ -1259,7 +1259,7 @@ mod tests { } let value: &dyn Reflect = &[1usize, 2usize, 3usize]; - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); // Map @@ -1278,7 +1278,7 @@ mod tests { } let value: &dyn Reflect = &MyMap::new(); - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); // Value @@ -1293,7 +1293,7 @@ mod tests { } let value: &dyn Reflect = &String::from("Hello!"); - let info = value.represented_type_info(); + let info = value.represented_type_info().unwrap(); assert!(info.is::()); } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 0561517349662..a5149b27535a5 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -95,7 +95,7 @@ pub trait List: Reflect { /// Clones the list, producing a [`DynamicList`]. fn clone_dynamic(&self) -> DynamicList { DynamicList { - represented_type: Some(self.represented_type_info()), + represented_type: self.represented_type_info(), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -256,8 +256,8 @@ impl Reflect for DynamicList { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - todo!("make this method return Option<&'static TypeInfo> to support dynamic types") + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + self.represented_type } #[inline] diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 6f5a26b9b2aae..cf7730ae9eb81 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -285,8 +285,8 @@ impl Reflect for DynamicMap { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - todo!("make this method return Option<&'static TypeInfo> to support dynamic types") + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + self.represented_type } fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 443b3e70bf05c..f394547759dcf 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -89,7 +89,7 @@ pub trait Reflect: Any + Send + Sync { /// performant for such use cases. /// /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info - fn represented_type_info(&self) -> &'static TypeInfo; + fn represented_type_info(&self) -> Option<&'static TypeInfo>; /// Returns the value as a [`Box`][std::any::Any]. fn into_any(self: Box) -> Box; diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index d34cc72368fc0..abb7cd2f038b8 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -166,7 +166,12 @@ impl<'a> Serialize for StructSerializer<'a> { where S: serde::Serializer, { - let type_info = self.struct_value.represented_type_info(); + let type_info = self.struct_value.represented_type_info().ok_or_else(|| { + Error::custom(format_args!( + "cannot get type info for {}", + self.struct_value.type_name() + )) + })?; let struct_info = match type_info { TypeInfo::Struct(struct_info) => struct_info, @@ -211,7 +216,12 @@ impl<'a> Serialize for TupleStructSerializer<'a> { where S: serde::Serializer, { - let type_info = self.tuple_struct.represented_type_info(); + let type_info = self.tuple_struct.represented_type_info().ok_or_else(|| { + Error::custom(format_args!( + "cannot get type info for {}", + self.tuple_struct.type_name() + )) + })?; let tuple_struct_info = match type_info { TypeInfo::TupleStruct(tuple_struct_info) => tuple_struct_info, @@ -255,7 +265,12 @@ impl<'a> Serialize for EnumSerializer<'a> { where S: serde::Serializer, { - let type_info = self.enum_value.represented_type_info(); + let type_info = self.enum_value.represented_type_info().ok_or_else(|| { + Error::custom(format_args!( + "cannot get type info for {}", + self.enum_value.type_name() + )) + })?; let enum_info = match type_info { TypeInfo::Enum(enum_info) => enum_info, diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 629d89ebcb726..fd2ebc9f78243 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -364,7 +364,7 @@ impl Struct for DynamicStruct { fn clone_dynamic(&self) -> DynamicStruct { DynamicStruct { - represented_type: Some(self.represented_type_info()), + represented_type: self.represented_type_info(), field_names: self.field_names.clone(), field_indices: self.field_indices.clone(), fields: self @@ -385,8 +385,8 @@ impl Reflect for DynamicStruct { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - todo!("make this method return Option<&'static TypeInfo> to support dynamic types") + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + self.represented_type } #[inline] diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 454eb11c8b262..ee61a4f53b460 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -304,8 +304,8 @@ impl Reflect for DynamicTuple { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - todo!("make this method return Option<&'static TypeInfo> to support dynamic types") + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + self.represented_type } #[inline] @@ -499,8 +499,8 @@ macro_rules! impl_reflect_tuple { fn clone_dynamic(&self) -> DynamicTuple { let info = self.represented_type_info(); DynamicTuple { - name: Cow::Borrowed(info.type_name()), - represented_type: Some(info), + name: Cow::Borrowed(::core::any::type_name::()), + represented_type: info, fields: self .iter_fields() .map(|value| value.clone_value()) @@ -514,8 +514,8 @@ macro_rules! impl_reflect_tuple { std::any::type_name::() } - fn represented_type_info(&self) -> &'static TypeInfo { - ::type_info() + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + Some(::type_info()) } fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 87147cd8f6d98..91ebfe39ab2aa 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -287,8 +287,8 @@ impl Reflect for DynamicTupleStruct { } #[inline] - fn represented_type_info(&self) -> &'static TypeInfo { - todo!("make this method return Option<&'static TypeInfo> to support dynamic types") + fn represented_type_info(&self) -> Option<&'static TypeInfo> { + self.represented_type } #[inline] diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index d2160e0105768..c329d115ff9aa 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -50,7 +50,7 @@ use std::fmt::Debug; /// # /// # impl Reflect for MyStruct { /// # fn type_name(&self) -> &str { todo!() } -/// # fn represented_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 14c09f58c69e8..8ea84c976a464 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -39,7 +39,7 @@ use std::{ /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn represented_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } @@ -102,7 +102,7 @@ impl NonGenericTypeInfoCell { /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn represented_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } From 1b3fdd75b3be8a89c830dfa61d4778cdf838991a Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 19 Feb 2023 17:30:17 -0700 Subject: [PATCH 06/11] Unwrap dynamic Reflect::type_name as std::any::type_name:: --- crates/bevy_reflect/src/array.rs | 2 +- crates/bevy_reflect/src/list.rs | 2 +- crates/bevy_reflect/src/map.rs | 2 +- crates/bevy_reflect/src/serde/mod.rs | 12 ++++++++++++ crates/bevy_reflect/src/struct_trait.rs | 2 +- crates/bevy_reflect/src/tuple_struct.rs | 2 +- 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 2f622ba9a5993..71f01a3323020 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -201,7 +201,7 @@ impl Reflect for DynamicArray { fn type_name(&self) -> &str { self.represented_type .map(|info| info.type_name()) - .unwrap_or_default() + .unwrap_or_else(|| std::any::type_name::()) } #[inline] diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index a5149b27535a5..0743d51fefbe0 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -252,7 +252,7 @@ impl Reflect for DynamicList { fn type_name(&self) -> &str { self.represented_type .map(|info| info.type_name()) - .unwrap_or_default() + .unwrap_or_else(|| std::any::type_name::()) } #[inline] diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index cf7730ae9eb81..dadc9993543a9 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -281,7 +281,7 @@ impl Reflect for DynamicMap { fn type_name(&self) -> &str { self.represented_type .map(|info| info.type_name()) - .unwrap_or_default() + .unwrap_or_else(|| std::any::type_name::()) } #[inline] diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index 3355ed38d0b11..58231b2654ac2 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -92,4 +92,16 @@ mod tests { "Expected {expected:?} found {deserialized:?}" ); } + + #[test] + #[should_panic(expected = "cannot get type info for bevy_reflect::struct_trait::DynamicStruct")] + fn unproxied_dynamic_should_not_serialize() { + let registry = TypeRegistry::default(); + + let mut value = DynamicStruct::default(); + value.insert("foo", 123_u32); + + let serializer = ReflectSerializer::new(&value, ®istry); + ron::ser::to_string(&serializer).unwrap(); + } } diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index fd2ebc9f78243..9c6d5bf62c363 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -381,7 +381,7 @@ impl Reflect for DynamicStruct { fn type_name(&self) -> &str { self.represented_type .map(|info| info.type_name()) - .unwrap_or_default() + .unwrap_or_else(|| std::any::type_name::()) } #[inline] diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 91ebfe39ab2aa..adce82148d555 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -283,7 +283,7 @@ impl Reflect for DynamicTupleStruct { fn type_name(&self) -> &str { self.represented_type .map(|info| info.type_name()) - .unwrap_or_default() + .unwrap_or_else(|| std::any::type_name::()) } #[inline] From 20e57c1b159bcf3669729a6b2c91b272814bec0d Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 19 Feb 2023 18:17:17 -0700 Subject: [PATCH 07/11] Fix doc errors --- crates/bevy_reflect/src/lib.rs | 2 +- crates/bevy_reflect/src/reflect.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 7d591d396c1b3..f406fb84adc48 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -169,7 +169,7 @@ //! ``` //! # use bevy_reflect::{DynamicEnum, Reflect}; //! let mut value = Some(123_i32); -//! let patch = DynamicEnum::new(std::any::type_name::>(), "None", ()); +//! let patch = DynamicEnum::new("None", ()); //! value.apply(&patch); //! assert_eq!(None, value); //! ``` diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index f394547759dcf..43cfe1b7058dd 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -88,6 +88,8 @@ pub trait Reflect: Any + Send + Sync { /// frequently, consider using [`TypeRegistry::get_type_info`] as it can be more /// performant for such use cases. /// + /// [`DynamicStruct`]: crate::DynamicStruct + /// [`DynamicList`]: crate::DynamicList /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info fn represented_type_info(&self) -> Option<&'static TypeInfo>; From bc946f84eb6da601281577522027aeaa901d8c44 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 16 Apr 2023 22:10:18 -0700 Subject: [PATCH 08/11] Rename to get_represented_type_info --- .../bevy_reflect_derive/src/impls/enums.rs | 2 +- .../bevy_reflect_derive/src/impls/structs.rs | 4 +-- .../src/impls/tuple_structs.rs | 4 +-- .../bevy_reflect_derive/src/impls/values.rs | 2 +- crates/bevy_reflect/src/array.rs | 4 +-- crates/bevy_reflect/src/enums/dynamic_enum.rs | 4 +-- crates/bevy_reflect/src/impls/smallvec.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 14 ++++---- crates/bevy_reflect/src/lib.rs | 18 +++++------ crates/bevy_reflect/src/list.rs | 4 +-- crates/bevy_reflect/src/map.rs | 2 +- crates/bevy_reflect/src/reflect.rs | 2 +- crates/bevy_reflect/src/serde/ser.rs | 32 +++++++++++-------- crates/bevy_reflect/src/struct_trait.rs | 4 +-- crates/bevy_reflect/src/tuple.rs | 6 ++-- crates/bevy_reflect/src/tuple_struct.rs | 2 +- crates/bevy_reflect/src/type_info.rs | 8 ++--- crates/bevy_reflect/src/utility.rs | 4 +-- 18 files changed, 62 insertions(+), 56 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index 762ccb1347401..2f2f5cf5e3582 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -192,7 +192,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } 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 17abb5db72949..4e168bc03c210 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -151,7 +151,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicStruct { let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default(); - dynamic.set_represented_type(#bevy_reflect_path::Reflect::represented_type_info(self)); + dynamic.set_represented_type(#bevy_reflect_path::Reflect::get_represented_type_info(self)); #(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } @@ -164,7 +164,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } 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 a654c2ec9556b..c74d4d9064f80 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 @@ -122,7 +122,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct { let mut dynamic: #bevy_reflect_path::DynamicTupleStruct = #FQDefault::default(); - dynamic.set_represented_type(#bevy_reflect_path::Reflect::represented_type_info(self)); + dynamic.set_represented_type(#bevy_reflect_path::Reflect::get_represented_type_info(self)); #(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* dynamic } @@ -135,7 +135,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs index 524740ce73bd0..964ef1f2ce8a8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -49,7 +49,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { } #[inline] - fn represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { + fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 71f01a3323020..d3bcae95df815 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -64,7 +64,7 @@ pub trait Array: Reflect { /// Clones the list, producing a [`DynamicArray`]. fn clone_dynamic(&self) -> DynamicArray { DynamicArray { - represented_type: self.represented_type_info(), + represented_type: self.get_represented_type_info(), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -205,7 +205,7 @@ impl Reflect for DynamicArray { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index ea2df967c22b8..2e4261322a744 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -148,7 +148,7 @@ impl DynamicEnum { /// /// This is functionally the same as [`DynamicEnum::from`] except it takes a reference. pub fn from_ref(value: &TEnum) -> Self { - let type_info = value.represented_type_info(); + let type_info = value.get_represented_type_info(); let mut dyn_enum = match value.variant_type() { VariantType::Unit => DynamicEnum::new_with_index( value.variant_index(), @@ -281,7 +281,7 @@ impl Reflect for DynamicEnum { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 45c6d957d5b0e..918dc849b62eb 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -82,7 +82,7 @@ where std::any::type_name::() } - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 85d1695d4e88e..db8baa3d9d768 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -244,7 +244,7 @@ macro_rules! impl_reflect_for_veclike { std::any::type_name::() } - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } @@ -397,7 +397,7 @@ macro_rules! impl_reflect_for_hashmap { fn clone_dynamic(&self) -> DynamicMap { let mut dynamic_map = DynamicMap::default(); - dynamic_map.set_represented_type(self.represented_type_info()); + dynamic_map.set_represented_type(self.get_represented_type_info()); for (k, v) in self { let key = K::from_reflect(k).unwrap_or_else(|| { panic!("Attempted to clone invalid key of type {}.", k.type_name()) @@ -450,7 +450,7 @@ macro_rules! impl_reflect_for_hashmap { std::any::type_name::() } - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } @@ -595,7 +595,7 @@ impl Reflect for [T; N] { std::any::type_name::() } - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } @@ -800,7 +800,7 @@ impl Reflect for Option { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } @@ -965,7 +965,7 @@ impl Reflect for Cow<'static, str> { std::any::type_name::() } - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } @@ -1073,7 +1073,7 @@ impl Reflect for &'static Path { std::any::type_name::() } - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index f406fb84adc48..069203c3003c0 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1100,7 +1100,7 @@ mod tests { // TypeInfo (instance) let value: &dyn Reflect = &123_i32; - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); // Struct @@ -1133,7 +1133,7 @@ mod tests { } let value: &dyn Reflect = &MyStruct { foo: 123, bar: 321 }; - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); // Struct (generic) @@ -1167,7 +1167,7 @@ mod tests { foo: String::from("Hello!"), bar: 321, }; - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::>()); // Tuple Struct @@ -1203,7 +1203,7 @@ mod tests { } let value: &dyn Reflect = &(123_u32, 1.23_f32, String::from("Hello!")); - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); // List @@ -1220,7 +1220,7 @@ mod tests { } let value: &dyn Reflect = &vec![123_usize]; - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); // List (SmallVec) @@ -1240,7 +1240,7 @@ mod tests { let value: MySmallVec = smallvec::smallvec![String::default(); 2]; let value: &dyn Reflect = &value; - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); } @@ -1259,7 +1259,7 @@ mod tests { } let value: &dyn Reflect = &[1usize, 2usize, 3usize]; - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); // Map @@ -1278,7 +1278,7 @@ mod tests { } let value: &dyn Reflect = &MyMap::new(); - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); // Value @@ -1293,7 +1293,7 @@ mod tests { } let value: &dyn Reflect = &String::from("Hello!"); - let info = value.represented_type_info().unwrap(); + let info = value.get_represented_type_info().unwrap(); assert!(info.is::()); } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 0743d51fefbe0..286853bf7924e 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -95,7 +95,7 @@ pub trait List: Reflect { /// Clones the list, producing a [`DynamicList`]. fn clone_dynamic(&self) -> DynamicList { DynamicList { - represented_type: self.represented_type_info(), + represented_type: self.get_represented_type_info(), values: self.iter().map(|value| value.clone_value()).collect(), } } @@ -256,7 +256,7 @@ impl Reflect for DynamicList { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index dadc9993543a9..3732cee839d63 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -285,7 +285,7 @@ impl Reflect for DynamicMap { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 43cfe1b7058dd..c0749f5067caa 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -91,7 +91,7 @@ pub trait Reflect: Any + Send + Sync { /// [`DynamicStruct`]: crate::DynamicStruct /// [`DynamicList`]: crate::DynamicList /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info - fn represented_type_info(&self) -> Option<&'static TypeInfo>; + fn get_represented_type_info(&self) -> Option<&'static TypeInfo>; /// Returns the value as a [`Box`][std::any::Any]. fn into_any(self: Box) -> Box; diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index abb7cd2f038b8..38d4529a3a40b 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -166,12 +166,15 @@ impl<'a> Serialize for StructSerializer<'a> { where S: serde::Serializer, { - let type_info = self.struct_value.represented_type_info().ok_or_else(|| { - Error::custom(format_args!( - "cannot get type info for {}", - self.struct_value.type_name() - )) - })?; + let type_info = self + .struct_value + .get_represented_type_info() + .ok_or_else(|| { + Error::custom(format_args!( + "cannot get type info for {}", + self.struct_value.type_name() + )) + })?; let struct_info = match type_info { TypeInfo::Struct(struct_info) => struct_info, @@ -216,12 +219,15 @@ impl<'a> Serialize for TupleStructSerializer<'a> { where S: serde::Serializer, { - let type_info = self.tuple_struct.represented_type_info().ok_or_else(|| { - Error::custom(format_args!( - "cannot get type info for {}", - self.tuple_struct.type_name() - )) - })?; + let type_info = self + .tuple_struct + .get_represented_type_info() + .ok_or_else(|| { + Error::custom(format_args!( + "cannot get type info for {}", + self.tuple_struct.type_name() + )) + })?; let tuple_struct_info = match type_info { TypeInfo::TupleStruct(tuple_struct_info) => tuple_struct_info, @@ -265,7 +271,7 @@ impl<'a> Serialize for EnumSerializer<'a> { where S: serde::Serializer, { - let type_info = self.enum_value.represented_type_info().ok_or_else(|| { + let type_info = self.enum_value.get_represented_type_info().ok_or_else(|| { Error::custom(format_args!( "cannot get type info for {}", self.enum_value.type_name() diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 9c6d5bf62c363..779c63bdb506f 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -364,7 +364,7 @@ impl Struct for DynamicStruct { fn clone_dynamic(&self) -> DynamicStruct { DynamicStruct { - represented_type: self.represented_type_info(), + represented_type: self.get_represented_type_info(), field_names: self.field_names.clone(), field_indices: self.field_indices.clone(), fields: self @@ -385,7 +385,7 @@ impl Reflect for DynamicStruct { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index ee61a4f53b460..2daf52105bc72 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -304,7 +304,7 @@ impl Reflect for DynamicTuple { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } @@ -497,7 +497,7 @@ macro_rules! impl_reflect_tuple { #[inline] fn clone_dynamic(&self) -> DynamicTuple { - let info = self.represented_type_info(); + let info = self.get_represented_type_info(); DynamicTuple { name: Cow::Borrowed(::core::any::type_name::()), represented_type: info, @@ -514,7 +514,7 @@ macro_rules! impl_reflect_tuple { std::any::type_name::() } - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index adce82148d555..19d9daa3ec606 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -287,7 +287,7 @@ impl Reflect for DynamicTupleStruct { } #[inline] - fn represented_type_info(&self) -> Option<&'static TypeInfo> { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index c329d115ff9aa..c99beece3a9a4 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -50,7 +50,7 @@ use std::fmt::Debug; /// # /// # impl Reflect for MyStruct { /// # fn type_name(&self) -> &str { todo!() } -/// # fn represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } +/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } @@ -79,12 +79,12 @@ pub trait Typed: Reflect { /// Generally, for any given type, this value can be retrieved one of three ways: /// /// 1. [`Typed::type_info`] -/// 2. [`Reflect::represented_type_info`] +/// 2. [`Reflect::get_represented_type_info`] /// 3. [`TypeRegistry::get_type_info`] /// /// Each return a static reference to [`TypeInfo`], but they all have their own use cases. /// For example, if you know the type at compile time, [`Typed::type_info`] is probably -/// the simplest. If all you have is a `dyn Reflect`, you'll probably want [`Reflect::represented_type_info`]. +/// the simplest. If all you have is a `dyn Reflect`, you'll probably want [`Reflect::get_represented_type_info`]. /// Lastly, if all you have is a [`TypeId`] or [type name], you will need to go through /// [`TypeRegistry::get_type_info`]. /// @@ -92,7 +92,7 @@ pub trait Typed: Reflect { /// it can be more performant. This is because those other methods may require attaining a lock on /// the static [`TypeInfo`], while the registry simply checks a map. /// -/// [`Reflect::represented_type_info`]: crate::Reflect::represented_type_info +/// [`Reflect::get_represented_type_info`]: crate::Reflect::get_represented_type_info /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info /// [`TypeId`]: std::any::TypeId /// [type name]: std::any::type_name diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 8ea84c976a464..7c203631aa785 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -39,7 +39,7 @@ use std::{ /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } +/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } @@ -102,7 +102,7 @@ impl NonGenericTypeInfoCell { /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } +/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } From f7b96659ada8c931c7d3899ef10a45ddd0900447 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 16 Apr 2023 22:24:21 -0700 Subject: [PATCH 09/11] Add assertion --- crates/bevy_reflect/src/array.rs | 12 ++++++++++++ crates/bevy_reflect/src/enums/dynamic_enum.rs | 12 ++++++++++++ crates/bevy_reflect/src/lib.rs | 15 +++++++++++++++ crates/bevy_reflect/src/list.rs | 11 +++++++++++ crates/bevy_reflect/src/map.rs | 12 ++++++++++++ crates/bevy_reflect/src/struct_trait.rs | 12 ++++++++++++ crates/bevy_reflect/src/tuple.rs | 14 ++++++++++++-- crates/bevy_reflect/src/tuple_struct.rs | 12 ++++++++++++ 8 files changed, 98 insertions(+), 2 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index d3bcae95df815..0367e1add4f79 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -190,8 +190,20 @@ impl DynamicArray { /// Sets the [type] to be represented by this `DynamicArray`. /// + /// # Panics + /// + /// Panics if the given [type] is not a [`TypeInfo::Array`]. + /// /// [type]: TypeInfo pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + if let Some(represented_type) = represented_type { + assert!( + matches!(represented_type, TypeInfo::Array(_)), + "expected TypeInfo::Array but received: {:?}", + represented_type + ); + } + self.represented_type = represented_type; } } diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 2e4261322a744..1e4cce12780d7 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -114,8 +114,20 @@ impl DynamicEnum { /// Sets the [type] to be represented by this `DynamicEnum`. /// + /// # Panics + /// + /// Panics if the given [type] is not a [`TypeInfo::Enum`]. + /// /// [type]: TypeInfo pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + if let Some(represented_type) = represented_type { + assert!( + matches!(represented_type, TypeInfo::Enum(_)), + "expected TypeInfo::Enum but received: {:?}", + represented_type + ); + } + self.represented_type = represented_type; } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 069203c3003c0..4823fe93b7c2c 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1297,6 +1297,21 @@ mod tests { assert!(info.is::()); } + #[test] + fn should_permit_valid_represented_type_for_dynamic() { + let type_info = <[i32; 2] as Typed>::type_info(); + let mut dynamic_array = [123; 2].clone_dynamic(); + dynamic_array.set_represented_type(Some(type_info)); + } + + #[test] + #[should_panic(expected = "expected TypeInfo::Array but received")] + fn should_prohibit_invalid_represented_type_for_dynamic() { + let type_info = <(i32, i32) as Typed>::type_info(); + let mut dynamic_array = [123; 2].clone_dynamic(); + dynamic_array.set_represented_type(Some(type_info)); + } + #[cfg(feature = "documentation")] mod docstrings { use super::*; diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 286853bf7924e..6b17527302f02 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -181,9 +181,20 @@ pub struct DynamicList { impl DynamicList { /// Sets the [type] to be represented by this `DynamicList`. + /// # Panics + /// + /// Panics if the given [type] is not a [`TypeInfo::List`]. /// /// [type]: TypeInfo pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + if let Some(represented_type) = represented_type { + assert!( + matches!(represented_type, TypeInfo::List(_)), + "expected TypeInfo::List but received: {:?}", + represented_type + ); + } + self.represented_type = represented_type; } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 3732cee839d63..6e997ffd32e26 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -191,8 +191,20 @@ pub struct DynamicMap { impl DynamicMap { /// Sets the [type] to be represented by this `DynamicMap`. /// + /// # Panics + /// + /// Panics if the given [type] is not a [`TypeInfo::Map`]. + /// /// [type]: TypeInfo pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + if let Some(represented_type) = represented_type { + assert!( + matches!(represented_type, TypeInfo::Map(_)), + "expected TypeInfo::Map but received: {:?}", + represented_type + ); + } + self.represented_type = represented_type; } diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 779c63bdb506f..ede4ddec4d04d 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -278,8 +278,20 @@ pub struct DynamicStruct { impl DynamicStruct { /// Sets the [type] to be represented by this `DynamicStruct`. /// + /// # Panics + /// + /// Panics if the given [type] is not a [`TypeInfo::Struct`]. + /// /// [type]: TypeInfo pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + if let Some(represented_type) = represented_type { + assert!( + matches!(represented_type, TypeInfo::Struct(_)), + "expected TypeInfo::Struct but received: {:?}", + represented_type + ); + } + self.represented_type = represented_type; } diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 2daf52105bc72..8f0340bcbb55e 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -215,10 +215,20 @@ pub struct DynamicTuple { impl DynamicTuple { /// Sets the [type] to be represented by this `DynamicTuple`. /// + /// # Panics + /// + /// Panics if the given [type] is not a [`TypeInfo::Tuple`]. + /// /// [type]: TypeInfo pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { - if let Some(info) = represented_type { - self.name = Cow::Borrowed(info.type_name()); + if let Some(represented_type) = represented_type { + assert!( + matches!(represented_type, TypeInfo::Tuple(_)), + "expected TypeInfo::Tuple but received: {:?}", + represented_type + ); + + self.name = Cow::Borrowed(represented_type.type_name()); } self.represented_type = represented_type; } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 19d9daa3ec606..9b7466d5757ad 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -226,8 +226,20 @@ pub struct DynamicTupleStruct { impl DynamicTupleStruct { /// Sets the [type] to be represented by this `DynamicTupleStruct`. /// + /// # Panics + /// + /// Panics if the given [type] is not a [`TypeInfo::TupleStruct`]. + /// /// [type]: TypeInfo pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) { + if let Some(represented_type) = represented_type { + assert!( + matches!(represented_type, TypeInfo::TupleStruct(_)), + "expected TypeInfo::TupleStruct but received: {:?}", + represented_type + ); + } + self.represented_type = represented_type; } From 78b8430545072519e6913035be5676d8956f6879 Mon Sep 17 00:00:00 2001 From: Gino Valente <49806985+MrGVSV@users.noreply.github.com> Date: Sun, 16 Apr 2023 22:25:14 -0700 Subject: [PATCH 10/11] Update crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs Co-authored-by: radiish --- crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4e168bc03c210..2b7fd1815c607 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -165,7 +165,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { - #FQOption::Some(::type_info()) + #FQOption::Some(::type_info()) } #[inline] From 69106c3e2e67acdbb734bc7456eb43053d4f14dd Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Tue, 25 Apr 2023 16:52:57 -0700 Subject: [PATCH 11/11] Fix benches not compiling --- benches/benches/bevy_reflect/struct.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benches/benches/bevy_reflect/struct.rs b/benches/benches/bevy_reflect/struct.rs index 782d5e0b73d9d..0495701807c9e 100644 --- a/benches/benches/bevy_reflect/struct.rs +++ b/benches/benches/bevy_reflect/struct.rs @@ -148,14 +148,14 @@ fn concrete_struct_type_info(criterion: &mut Criterion) { BenchmarkId::new("NonGeneric", field_count), &standard, |bencher, s| { - bencher.iter(|| black_box(s.get_type_info())); + bencher.iter(|| black_box(s.get_represented_type_info())); }, ); group.bench_with_input( BenchmarkId::new("Generic", field_count), &generic, |bencher, s| { - bencher.iter(|| black_box(s.get_type_info())); + bencher.iter(|| black_box(s.get_represented_type_info())); }, ); }