Skip to content

Commit

Permalink
Use TypeInfo to default trait methods
Browse files Browse the repository at this point in the history
  • Loading branch information
MrGVSV committed May 30, 2022
1 parent e87c24b commit 1e7cbd8
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 64 deletions.
43 changes: 5 additions & 38 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {
.active_fields()
.map(|field| field.data.ty.clone())
.collect::<Vec<_>>();
let field_count = field_idents.len();
let field_indices = (0..field_count).collect::<Vec<usize>>();

let hash_fn = derive_data.traits().get_hash_impl(bevy_reflect_path);
let serialize_fn = derive_data.traits().get_serialize_impl(bevy_reflect_path);
Expand All @@ -57,7 +55,7 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {
struct_name,
derive_data.generics(),
quote! {
let fields: [#bevy_reflect_path::NamedField; #field_count] = [
let fields = [
#(#bevy_reflect_path::NamedField::new::<#field_types, _>(#field_names),)*
];
let info = #bevy_reflect_path::StructInfo::new::<Self>(&fields);
Expand Down Expand Up @@ -89,31 +87,6 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {
}
}

fn field_at(&self, index: usize) -> Option<&dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&self.#field_idents),)*
_ => None,
}
}

fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&mut self.#field_idents),)*
_ => None,
}
}

fn name_at(&self, index: usize) -> Option<&str> {
match index {
#(#field_indices => Some(#field_names),)*
_ => None,
}
}

fn field_len(&self) -> usize {
#field_count
}

fn iter_fields(&self) -> #bevy_reflect_path::FieldIter {
#bevy_reflect_path::FieldIter::new(self)
}
Expand Down Expand Up @@ -212,8 +185,6 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream
.active_fields()
.map(|field| field.data.ty.clone())
.collect::<Vec<_>>();
let field_count = field_idents.len();
let field_indices = (0..field_count).collect::<Vec<usize>>();

let hash_fn = derive_data.traits().get_hash_impl(bevy_reflect_path);
let serialize_fn = derive_data.traits().get_serialize_impl(bevy_reflect_path);
Expand All @@ -233,8 +204,8 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream
struct_name,
derive_data.generics(),
quote! {
let fields: [#bevy_reflect_path::UnnamedField; #field_count] = [
#(#bevy_reflect_path::UnnamedField::new::<#field_types>(#field_indices),)*
let fields = [
#(#bevy_reflect_path::UnnamedField::new::<#field_types>(#field_idents),)*
];
let info = #bevy_reflect_path::TupleStructInfo::new::<Self>(&fields);
#bevy_reflect_path::TypeInfo::TupleStruct(info)
Expand All @@ -251,22 +222,18 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream
impl #impl_generics #bevy_reflect_path::TupleStruct for #struct_name #ty_generics #where_clause {
fn field(&self, index: usize) -> Option<&dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&self.#field_idents),)*
#(#field_idents => Some(&self.#field_idents),)*
_ => None,
}
}

fn field_mut(&mut self, index: usize) -> Option<&mut dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&mut self.#field_idents),)*
#(#field_idents => Some(&mut self.#field_idents),)*
_ => None,
}
}

fn field_len(&self) -> usize {
#field_count
}

fn iter_fields(&self) -> #bevy_reflect_path::TupleStructFieldIter {
#bevy_reflect_path::TupleStructFieldIter::new(self)
}
Expand Down
95 changes: 81 additions & 14 deletions crates/bevy_reflect/src/struct_trait.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::utility::TypeInfoCell;
use crate::{DynamicInfo, NamedField, Reflect, ReflectMut, ReflectRef, TypeInfo, Typed};
use bevy_utils::{Entry, HashMap};
use std::borrow::Borrow;
use std::fmt::{Debug, Formatter};
use std::{
any::{Any, TypeId},
Expand Down Expand Up @@ -45,25 +46,91 @@ pub trait Struct: Reflect {
/// `&mut dyn Reflect`.
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>;

/// Returns a reference to the value of the field with index `index` as a
/// `&dyn Reflect`.
fn field_at(&self, index: usize) -> Option<&dyn Reflect>;

/// Returns a mutable reference to the value of the field with index `index`
/// as a `&mut dyn Reflect`.
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;

/// Returns the name of the field with index `index`.
fn name_at(&self, index: usize) -> Option<&str>;

/// Returns the number of fields in the struct.
fn field_len(&self) -> usize;

/// Returns an iterator over the values of the struct's fields.
fn iter_fields(&self) -> FieldIter;

/// Clones the struct into a [`DynamicStruct`].
fn clone_dynamic(&self) -> DynamicStruct;

/// Returns the number of fields in the struct.
///
/// # Panics
///
/// Panics if the [`TypeInfo`] returned by [`Reflect::get_type_info()`] is not
/// [`TypeInfo::Struct`]— which should almost never be the case. Notable exceptions
/// include [`DynamicStruct`] which uses its own implementation of this method to
/// prevent the panic.
fn field_len(&self) -> usize {
if let TypeInfo::Struct(info) = self.get_type_info() {
info.field_len()
} else {
panic!(
"tuple `{:?}` is not `TypeInfo::Struct`",
std::any::type_name::<Self>()
);
}
}

/// Returns the name of the field with index `index`.
///
/// # Panics
///
/// Panics if the [`TypeInfo`] returned by [`Reflect::get_type_info()`] is not
/// [`TypeInfo::Struct`]— which should almost never be the case. Notable exceptions
/// include [`DynamicStruct`] which uses its own implementation of this method to
/// prevent the panic.
fn name_at(&self, index: usize) -> Option<&str> {
if let TypeInfo::Struct(info) = self.get_type_info() {
info.field_at(index).map(|field| field.name().borrow())
} else {
panic!(
"tuple `{:?}` is not `TypeInfo::Struct`",
std::any::type_name::<Self>()
);
}
}

/// Returns a reference to the value of the field with index `index` as a
/// `&dyn Reflect`.
///
/// # Panics
///
/// Panics if the [`TypeInfo`] returned by [`Reflect::get_type_info()`] is not
/// [`TypeInfo::Struct`]— which should almost never be the case. Notable exceptions
/// include [`DynamicStruct`] which uses its own implementation of this method to
/// prevent the panic.
fn field_at(&self, index: usize) -> Option<&dyn Reflect> {
if let TypeInfo::Struct(info) = self.get_type_info() {
let name = info.field_at(index)?.name();
self.field(name)
} else {
panic!(
"tuple `{:?}` is not `TypeInfo::Struct`",
std::any::type_name::<Self>()
);
}
}

/// Returns a mutable reference to the value of the field with index `index`
/// as a `&mut dyn Reflect`.
///
/// # Panics
///
/// Panics if the [`TypeInfo`] returned by [`Reflect::get_type_info()`] is not
/// [`TypeInfo::Struct`]— which should almost never be the case. Notable exceptions
/// include [`DynamicStruct`] which uses its own implementation of this method to
/// prevent the panic.
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
if let TypeInfo::Struct(info) = self.get_type_info() {
let name = info.field_at(index)?.name();
self.field_mut(name)
} else {
panic!(
"tuple `{:?}` is not `TypeInfo::Struct`",
std::any::type_name::<Self>()
);
}
}
}

/// A container for compile-time struct info
Expand Down
28 changes: 19 additions & 9 deletions crates/bevy_reflect/src/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,30 @@ pub trait Tuple: Reflect {
/// as a `&mut dyn Reflect`.
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;

/// Returns the number of fields in the tuple.
fn field_len(&self) -> usize;

/// Returns an iterator over the values of the tuple's fields.
fn iter_fields(&self) -> TupleFieldIter;

/// Clones the struct into a [`DynamicTuple`].
fn clone_dynamic(&self) -> DynamicTuple;

/// Returns the number of fields in the tuple.
///
/// # Panics
///
/// Panics if the [`TypeInfo`] returned by [`Reflect::get_type_info()`] is not
/// [`TypeInfo::Tuple`]— which should almost never be the case. Notable exceptions
/// include [`DynamicTuple`] which uses its own implementation of this method to
/// prevent the panic.
fn field_len(&self) -> usize {
if let TypeInfo::Tuple(info) = self.get_type_info() {
info.field_len()
} else {
panic!(
"tuple `{:?}` is not `TypeInfo::Tuple`",
std::any::type_name::<Self>()
);
}
}
}

/// An iterator over the field values of a tuple.
Expand Down Expand Up @@ -432,12 +448,6 @@ macro_rules! impl_reflect_tuple {
}
}

#[inline]
fn field_len(&self) -> usize {
let indices: &[usize] = &[$($index as usize),*];
indices.len()
}

#[inline]
fn iter_fields(&self) -> TupleFieldIter {
TupleFieldIter {
Expand Down
19 changes: 16 additions & 3 deletions crates/bevy_reflect/src/tuple_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,27 @@ pub trait TupleStruct: Reflect {
/// as a `&mut dyn Reflect`.
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;

/// Returns the number of fields in the tuple struct.
fn field_len(&self) -> usize;

/// Returns an iterator over the values of the tuple struct's fields.
fn iter_fields(&self) -> TupleStructFieldIter;

/// Clones the struct into a [`DynamicTupleStruct`].
fn clone_dynamic(&self) -> DynamicTupleStruct;

/// Returns the number of fields in the tuple struct.
///
/// # Panics
///
/// Panics if the [`TypeInfo`] returned by [`Reflect::get_type_info()`] is not
/// [`TypeInfo::TupleStruct`]— which should almost never be the case. Notable exceptions
/// include [`DynamicTupleStruct`] which uses its own implementation of this method to
/// prevent the panic.
fn field_len(&self) -> usize {
if let TypeInfo::TupleStruct(info) = self.get_type_info() {
info.field_len()
} else {
0
}
}
}

/// A container for compile-time tuple struct info
Expand Down

0 comments on commit 1e7cbd8

Please sign in to comment.