Skip to content

Commit

Permalink
Revert "Create default Enum impls"
Browse files Browse the repository at this point in the history
This reverts commit 91409a061106a5ba64ce579c09e6fce4af710197.

This was done in response to the poor performance of using TypeInfo
directly: bevyengine#4042 (comment)
  • Loading branch information
MrGVSV committed Jun 27, 2022
1 parent 2bdc56b commit a723c0c
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 96 deletions.
74 changes: 73 additions & 1 deletion crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
variant_info,
enum_field,
enum_field_at,
enum_index_of,
enum_name_at,
enum_field_len,
enum_variant_name,
enum_variant_type,
} = generate_impls(reflect_enum, &ref_index, &ref_name);

let EnumVariantConstructors {
Expand All @@ -37,7 +41,10 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}
}
});
let debug_fn = reflect_enum.meta().traits().get_debug_impl();
let debug_fn = reflect_enum
.meta()
.traits()
.get_debug_impl();
let partial_eq_fn = reflect_enum
.meta()
.traits()
Expand Down Expand Up @@ -99,10 +106,32 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}
}

fn index_of(&self, #ref_name: &str) -> Option<usize> {
match self {
#(#enum_index_of,)*
_ => None,
}
}

fn name_at(&self, #ref_index: usize) -> Option<&str> {
match self {
#(#enum_name_at,)*
_ => None,
}
}

fn iter_fields(&self) -> #bevy_reflect_path::VariantFieldIter {
#bevy_reflect_path::VariantFieldIter::new(self)
}

#[inline]
fn field_len(&self) -> usize {
match self {
#(#enum_field_len,)*
_ => 0,
}
}

#[inline]
fn variant_name(&self) -> &str {
match self {
Expand All @@ -111,6 +140,14 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}
}

#[inline]
fn variant_type(&self) -> #bevy_reflect_path::VariantType {
match self {
#(#enum_variant_type,)*
_ => unreachable!(),
}
}

fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicEnum {
#bevy_reflect_path::DynamicEnum::from_ref::<Self>(self)
}
Expand Down Expand Up @@ -212,7 +249,11 @@ struct EnumImpls {
variant_info: Vec<proc_macro2::TokenStream>,
enum_field: Vec<proc_macro2::TokenStream>,
enum_field_at: Vec<proc_macro2::TokenStream>,
enum_index_of: Vec<proc_macro2::TokenStream>,
enum_name_at: Vec<proc_macro2::TokenStream>,
enum_field_len: Vec<proc_macro2::TokenStream>,
enum_variant_name: Vec<proc_macro2::TokenStream>,
enum_variant_type: Vec<proc_macro2::TokenStream>,
}

fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Ident) -> EnumImpls {
Expand All @@ -221,7 +262,11 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
let mut variant_info: Vec<proc_macro2::TokenStream> = Vec::new();
let mut enum_field: Vec<proc_macro2::TokenStream> = Vec::new();
let mut enum_field_at: Vec<proc_macro2::TokenStream> = Vec::new();
let mut enum_index_of: Vec<proc_macro2::TokenStream> = Vec::new();
let mut enum_name_at: Vec<proc_macro2::TokenStream> = Vec::new();
let mut enum_field_len: Vec<proc_macro2::TokenStream> = Vec::new();
let mut enum_variant_name: Vec<proc_macro2::TokenStream> = Vec::new();
let mut enum_variant_type: Vec<proc_macro2::TokenStream> = Vec::new();

for variant in reflect_enum.active_variants() {
let ident = &variant.data.ident;
Expand All @@ -238,6 +283,9 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
enum_variant_name.push(quote! {
#unit => #name
});
enum_variant_type.push(quote! {
#unit => #bevy_reflect_path::VariantType::Unit
});
}
EnumVariantFields::Unnamed(fields) => {
let mut field_info = Vec::new();
Expand All @@ -261,9 +309,16 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
field_idx += 1;
}

let field_len = field_idx;
enum_field_len.push(quote! {
#unit(..) => #field_len
});
enum_variant_name.push(quote! {
#unit(..) => #name
});
enum_variant_type.push(quote! {
#unit(..) => #bevy_reflect_path::VariantType::Tuple
});
variant_info.push(quote! {
#bevy_reflect_path::VariantInfo::Tuple(
#bevy_reflect_path::TupleVariantInfo::new(#name, &[
Expand All @@ -290,6 +345,12 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
enum_field_at.push(quote! {
#unit{ #field_ident, .. } if #ref_index == #field_idx => Some(#field_ident)
});
enum_index_of.push(quote! {
#unit{ .. } if #ref_name == #field_name => Some(#field_idx)
});
enum_name_at.push(quote! {
#unit{ .. } if #ref_index == #field_idx => Some(#field_name)
});

let field_ty = &field.data.ty;
field_info.push(quote! {
Expand All @@ -299,9 +360,16 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
field_idx += 1;
}

let field_len = field_idx;
enum_field_len.push(quote! {
#unit{..} => #field_len
});
enum_variant_name.push(quote! {
#unit{..} => #name
});
enum_variant_type.push(quote! {
#unit{..} => #bevy_reflect_path::VariantType::Struct
});
variant_info.push(quote! {
#bevy_reflect_path::VariantInfo::Struct(
#bevy_reflect_path::StructVariantInfo::new(#name, &[
Expand All @@ -317,6 +385,10 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
variant_info,
enum_field,
enum_field_at,
enum_index_of,
enum_name_at,
enum_field_len,
enum_variant_name,
enum_variant_type,
}
}
84 changes: 14 additions & 70 deletions crates/bevy_reflect/src/enums/enum_trait.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{DynamicEnum, Reflect, TypeInfo, VariantInfo, VariantType};
use crate::{DynamicEnum, Reflect, VariantInfo, VariantType};
use bevy_utils::HashMap;
use std::any::{Any, TypeId};
use std::borrow::{Borrow, Cow};
use std::borrow::Cow;
use std::slice::Iter;

/// A trait representing a [reflected] enum.
Expand Down Expand Up @@ -93,61 +93,24 @@ pub trait Enum: Reflect {
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>;
/// Returns a mutable reference to the value of the field (in the current variant) at the given index.
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
/// Returns the index of the field (in the current variant) with the given name.
///
/// For non-[`VariantType::Struct`] variants, this should return `None`.
fn index_of(&self, name: &str) -> Option<usize>;
/// Returns the name of the field (in the current variant) with the given index.
///
/// For non-[`VariantType::Struct`] variants, this should return `None`.
fn name_at(&self, index: usize) -> Option<&str>;
/// Returns an iterator over the values of the current variant's fields.
fn iter_fields(&self) -> VariantFieldIter;
/// Returns the number of fields in the current variant.
fn field_len(&self) -> usize;
/// The name of the current variant.
fn variant_name(&self) -> &str;
/// The type of the current variant.
fn variant_type(&self) -> VariantType;
// Clones the enum into a [`DynamicEnum`].
fn clone_dynamic(&self) -> DynamicEnum;
/// The type of the current variant.
fn variant_type(&self) -> VariantType {
if let TypeInfo::Enum(info) = self.get_type_info() {
if let Some(variant) = info.variant(self.variant_name()) {
variant.variant_type()
} else {
panic!("invalid variant: `{}`", self.variant_name());
}
} else {
panic!(
"`{:?}` is not `TypeInfo::Enum`",
std::any::type_name::<Self>()
);
}
}
/// Returns the name of the field (in the current variant) with the given index.
///
/// For non-[`VariantType::Struct`] variants, this should return `None`.
fn name_at(&self, index: usize) -> Option<&str> {
if let TypeInfo::Enum(info) = self.get_type_info() {
match info.variant(self.variant_name())? {
VariantInfo::Struct(variant) => {
variant.field_at(index).map(|field| field.name().borrow())
}
_ => None,
}
} else {
panic!(
"`{:?}` is not `TypeInfo::Enum`",
std::any::type_name::<Self>()
);
}
}
/// Returns the index of the field (in the current variant) with the given name.
///
/// For non-[`VariantType::Struct`] variants, this should return `None`.
fn index_of(&self, name: &str) -> Option<usize> {
if let TypeInfo::Enum(info) = self.get_type_info() {
match info.variant(self.variant_name())? {
VariantInfo::Struct(variant) => variant.index_of(name),
_ => None,
}
} else {
panic!(
"`{:?}` is not `TypeInfo::Enum`",
std::any::type_name::<Self>()
);
}
}
/// Returns true if the current variant's type matches the given one.
fn is_variant(&self, variant_type: VariantType) -> bool {
self.variant_type() == variant_type
Expand All @@ -156,25 +119,6 @@ pub trait Enum: Reflect {
fn variant_path(&self) -> String {
format!("{}::{}", self.type_name(), self.variant_name())
}
/// Returns the number of fields in the current variant.
fn field_len(&self) -> usize {
if let TypeInfo::Enum(info) = self.get_type_info() {
if let Some(variant) = info.variant(self.variant_name()) {
match variant {
VariantInfo::Unit(..) => 0,
VariantInfo::Tuple(variant_info) => variant_info.field_len(),
VariantInfo::Struct(variant_info) => variant_info.field_len(),
}
} else {
panic!("invalid variant: `{}`", self.variant_name());
}
} else {
panic!(
"`{:?}` is not `TypeInfo::Enum`",
std::any::type_name::<Self>()
);
}
}
}

/// A container for compile-time enum info.
Expand Down
7 changes: 0 additions & 7 deletions crates/bevy_reflect/src/enums/variants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,6 @@ impl VariantInfo {
Self::Unit(info) => info.name(),
}
}
pub fn variant_type(&self) -> VariantType {
match self {
Self::Struct(..) => VariantType::Struct,
Self::Tuple(..) => VariantType::Tuple,
Self::Unit(..) => VariantType::Unit,
}
}
}

/// Type info for struct variants.
Expand Down
36 changes: 18 additions & 18 deletions crates/bevy_reflect/src/impls/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,10 +561,26 @@ impl<T: Reflect + Clone> Enum for Option<T> {
}
}

fn index_of(&self, _name: &str) -> Option<usize> {
None
}

fn name_at(&self, _index: usize) -> Option<&str> {
None
}

fn iter_fields(&self) -> VariantFieldIter {
VariantFieldIter::new(self)
}

#[inline]
fn field_len(&self) -> usize {
match self {
Some(..) => 1,
None => 0,
}
}

#[inline]
fn variant_name(&self) -> &str {
match self {
Expand All @@ -573,10 +589,6 @@ impl<T: Reflect + Clone> Enum for Option<T> {
}
}

fn clone_dynamic(&self) -> DynamicEnum {
DynamicEnum::from_ref::<Self>(self)
}

#[inline]
fn variant_type(&self) -> VariantType {
match self {
Expand All @@ -585,20 +597,8 @@ impl<T: Reflect + Clone> Enum for Option<T> {
}
}

fn name_at(&self, _index: usize) -> Option<&str> {
None
}

fn index_of(&self, _name: &str) -> Option<usize> {
None
}

#[inline]
fn field_len(&self) -> usize {
match self {
Some(..) => 1,
None => 0,
}
fn clone_dynamic(&self) -> DynamicEnum {
DynamicEnum::from_ref::<Self>(self)
}
}

Expand Down

0 comments on commit a723c0c

Please sign in to comment.