Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bevy_reflect: Better proxies #6971

Merged
merged 11 commits into from
Apr 26, 2023
4 changes: 2 additions & 2 deletions benches/benches/bevy_reflect/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
},
);
}
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}

#[inline]
fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo {
<Self as #bevy_reflect_path::Typed>::type_info()
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
}

#[inline]
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(#bevy_reflect_path::Reflect::get_represented_type_info(self));
#(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)*
dynamic
}
Expand All @@ -164,8 +164,8 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}

#[inline]
fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo {
<Self as #bevy_reflect_path::Typed>::type_info()
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
}

#[inline]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(#bevy_reflect_path::Reflect::get_represented_type_info(self));
#(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)*
dynamic
}
Expand All @@ -135,8 +135,8 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}

#[inline]
fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo {
<Self as #bevy_reflect_path::Typed>::type_info()
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
}

#[inline]
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
}

#[inline]
fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo {
<Self as #bevy_reflect_path::Typed>::type_info()
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
}

#[inline]
Expand Down
58 changes: 32 additions & 26 deletions crates/bevy_reflect/src/array.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -67,7 +64,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: self.get_represented_type_info(),
values: self.iter().map(|value| value.clone_value()).collect(),
}
}
Expand Down Expand Up @@ -167,22 +164,22 @@ 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<dyn Reflect>]>,
}

impl DynamicArray {
#[inline]
pub fn new(values: Box<[Box<dyn Reflect>]>) -> Self {
Self {
name: String::default(),
represented_type: None,
values,
}
}

pub fn from_vec<T: Reflect>(values: Vec<T>) -> Self {
Self {
name: String::default(),
represented_type: None,
values: values
.into_iter()
.map(|field| Box::new(field) as Box<dyn Reflect>)
Expand All @@ -191,26 +188,37 @@ impl DynamicArray {
}
}

#[inline]
pub fn name(&self) -> &str {
&self.name
}
/// 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
);
}

#[inline]
pub fn set_name(&mut self, name: String) {
self.name = name;
self.represented_type = represented_type;
MrGVSV marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl Reflect for DynamicArray {
#[inline]
fn type_name(&self) -> &str {
self.name.as_str()
self.represented_type
.map(|info| info.type_name())
.unwrap_or_else(|| std::any::type_name::<Self>())
}

#[inline]
fn get_type_info(&self) -> &'static TypeInfo {
<Self as Typed>::type_info()
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
self.represented_type
}

#[inline]
Expand Down Expand Up @@ -281,6 +289,11 @@ impl Reflect for DynamicArray {
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
array_partial_eq(self, value)
}

#[inline]
fn is_dynamic(&self) -> bool {
true
}
}

impl Array for DynamicArray {
Expand Down Expand Up @@ -312,7 +325,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()
Expand All @@ -322,13 +335,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::<Self>()))
}
}

/// An iterator over an [`Array`].
pub struct ArrayIter<'a> {
array: &'a dyn Array,
Expand Down
77 changes: 36 additions & 41 deletions crates/bevy_reflect/src/enums/dynamic_enum.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -58,7 +56,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
/// );
Expand All @@ -71,7 +68,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,
Expand All @@ -82,17 +79,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<I: Into<String>, V: Into<DynamicVariant>>(
name: I,
variant_name: I,
variant: V,
) -> Self {
pub fn new<I: Into<String>, V: Into<DynamicVariant>>(variant_name: I, variant: V) -> Self {
Self {
name: name.into(),
represented_type: None,
variant_index: 0,
variant_name: variant_name.into(),
variant: variant.into(),
Expand All @@ -103,33 +95,40 @@ 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<I: Into<String>, V: Into<DynamicVariant>>(
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] 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
);
}

/// Sets the type name of the enum.
pub fn set_name(&mut self, name: String) {
self.name = name;
self.represented_type = represented_type;
}

/// Set the current enum variant represented by this struct.
Expand All @@ -142,11 +141,11 @@ impl DynamicEnum {
pub fn set_variant_with_index<I: Into<String>, V: Into<DynamicVariant>>(
&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();
}

Expand All @@ -161,9 +160,9 @@ impl DynamicEnum {
///
/// This is functionally the same as [`DynamicEnum::from`] except it takes a reference.
pub fn from_ref<TEnum: Enum>(value: &TEnum) -> Self {
match value.variant_type() {
let type_info = value.get_represented_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,
Expand All @@ -174,7 +173,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),
Expand All @@ -187,13 +185,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(type_info);
dyn_enum
}
}

Expand Down Expand Up @@ -276,7 +276,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(),
Expand All @@ -287,12 +287,14 @@ 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]
fn get_type_info(&self) -> &'static TypeInfo {
<Self as Typed>::type_info()
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
self.represented_type
}

#[inline]
Expand Down Expand Up @@ -418,10 +420,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::<Self>()))
}
}
Loading