Skip to content
Closed
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
ed5e997
Added TypeInfo
MrGVSV Feb 26, 2022
bfcfa25
Added tests
MrGVSV Feb 26, 2022
190dbc2
Fix clippy warnings
MrGVSV Feb 26, 2022
ea49152
Formatting
MrGVSV Feb 26, 2022
0ec2270
Apply suggestions from code review
MrGVSV Feb 26, 2022
b0dfaa9
Added relevant TypeIds to info structs
MrGVSV Feb 27, 2022
23e276a
Formatting
MrGVSV Feb 27, 2022
83c5e6e
Added convenience methods to TypeInfo
MrGVSV Feb 27, 2022
81c1298
Added Typed trait
MrGVSV Mar 5, 2022
8ad235c
Formatting
MrGVSV Mar 5, 2022
e9f39cf
Impl Typed for dyn Reflect
MrGVSV Mar 5, 2022
ad786ad
Formatting
MrGVSV Mar 5, 2022
a5ca84d
Replaced Cow<'static, str> with &'static str
MrGVSV Mar 5, 2022
f8e57a9
Store fields as Box<[T]>
MrGVSV Mar 5, 2022
fea5343
Added documentation for DynamicInfo
MrGVSV Mar 5, 2022
091e5e8
Added TypeIdentity
MrGVSV Mar 5, 2022
8cf5029
Integrated TypeIdentity across type info structs
MrGVSV Mar 5, 2022
9cbaf28
Fixed doc error
MrGVSV Mar 6, 2022
f6cbb1d
Remove duplicated data
MrGVSV Mar 8, 2022
55e023b
Removed unnecessary methods
MrGVSV Mar 8, 2022
000c327
Clarify comments
MrGVSV Mar 8, 2022
097b1f2
Added static_new method to create field with static str
MrGVSV Mar 8, 2022
d1ddb1f
Use the cow
MrGVSV Mar 8, 2022
4fcc07f
Merge branch 'main' into reflect-type-info
MrGVSV Apr 27, 2022
1f89001
Merge branch 'main' into reflect-type-info
MrGVSV May 9, 2022
018a125
Merge branch 'main' into reflect-type-info
MrGVSV May 11, 2022
8d93a67
Merge branch 'main' into reflect-type-info
MrGVSV May 13, 2022
be284d6
Merge branch 'reflect-type-info' of https://github.com/MrGVSV/bevy in…
MrGVSV May 13, 2022
ab8d022
Resolve merge conflict
MrGVSV May 13, 2022
9a41c85
Formatting
MrGVSV May 13, 2022
16d3ab6
Fix doc wording
MrGVSV May 13, 2022
ea9d34b
Add Reflect::get_type_info
MrGVSV May 18, 2022
d2f8f9f
Merge branch 'main' into reflect-type-info
MrGVSV May 18, 2022
5544557
Renamed name -> type_name
MrGVSV May 18, 2022
5d97ea5
Formatting
MrGVSV May 18, 2022
43dda0a
Remove unused import
MrGVSV May 18, 2022
51e1214
Removed TypeIdentity
MrGVSV May 25, 2022
4c0040a
Change doc wording
MrGVSV May 25, 2022
c3c54cb
Combine constructors
MrGVSV May 25, 2022
a877911
Return static TypeInfo from Typed::type_info()
MrGVSV May 26, 2022
63c284f
Remove extraneous import
MrGVSV May 26, 2022
aa5178e
Fix clippy warnings
MrGVSV May 27, 2022
c18cf5c
Merge branch 'main' into reflect-type-info
MrGVSV May 30, 2022
e87c24b
Fix incorrect non-generic TypeInfoCell
MrGVSV May 30, 2022
1e7cbd8
Use TypeInfo to default trait methods
MrGVSV May 30, 2022
87f1069
Merge branch 'main' into reflect-type-info
MrGVSV May 30, 2022
ee38b76
Improve docs
MrGVSV Jun 4, 2022
f8b4d07
Remove ListInfo capacity
MrGVSV Jun 4, 2022
38b2611
Replace list capacity references
MrGVSV Jun 4, 2022
16b7938
Revert "Use TypeInfo to default trait methods"
MrGVSV Jun 9, 2022
c0495e5
Split up TypeInfoCell
MrGVSV Jun 9, 2022
0fc6b64
Change wording in docs
MrGVSV Jun 9, 2022
6ddb85a
Merge remote-tracking branch 'origin/main' into pr/MrGVSV/4042-1
cart Jun 9, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/bevy_reflect/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ erased-serde = "0.3"
downcast-rs = "1.2"
parking_lot = "0.11.0"
thiserror = "1.0"
once_cell = "1.11"
serde = "1"
smallvec = { version = "1.6", features = ["serde", "union", "const_generics"], optional = true }
glam = { version = "0.20.0", features = ["serde"], optional = true }
Expand Down
137 changes: 102 additions & 35 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {
.unwrap_or_else(|| Member::Unnamed(Index::from(field.index)))
})
.collect::<Vec<_>>();
let field_count = field_idents.len();
let field_indices = (0..field_count).collect::<Vec<usize>>();
let field_types = derive_data
.active_fields()
.map(|field| field.data.ty.clone())
.collect::<Vec<_>>();

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 @@ -49,12 +51,27 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {
});
let debug_fn = derive_data.traits().get_debug_impl();

let typed_impl = impl_typed(
struct_name,
derive_data.generics(),
quote! {
let fields = [
#(#bevy_reflect_path::NamedField::new::<#field_types, _>(#field_names),)*
];
let info = #bevy_reflect_path::StructInfo::new::<Self>(&fields);
#bevy_reflect_path::TypeInfo::Struct(info)
},
bevy_reflect_path,
);

let get_type_registration_impl = derive_data.get_type_registration();
let (impl_generics, ty_generics, where_clause) = derive_data.generics().split_for_impl();

TokenStream::from(quote! {
#get_type_registration_impl

#typed_impl

impl #impl_generics #bevy_reflect_path::Struct for #struct_name #ty_generics #where_clause {
fn field(&self, name: &str) -> Option<&dyn #bevy_reflect_path::Reflect> {
match name {
Expand All @@ -70,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 All @@ -114,6 +106,11 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {
std::any::type_name::<Self>()
}

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

#[inline]
fn any(&self) -> &dyn std::any::Any {
self
Expand Down Expand Up @@ -184,8 +181,10 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream
.active_fields()
.map(|field| Member::Unnamed(Index::from(field.index)))
.collect::<Vec<_>>();
let field_count = field_idents.len();
let field_indices = (0..field_count).collect::<Vec<usize>>();
let field_types = derive_data
.active_fields()
.map(|field| field.data.ty.clone())
.collect::<Vec<_>>();

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 @@ -201,29 +200,40 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream
});
let debug_fn = derive_data.traits().get_debug_impl();

let typed_impl = impl_typed(
struct_name,
derive_data.generics(),
quote! {
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)
},
bevy_reflect_path,
);

let (impl_generics, ty_generics, where_clause) = derive_data.generics().split_for_impl();
TokenStream::from(quote! {
#get_type_registration_impl

#typed_impl

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 All @@ -243,6 +253,11 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream
std::any::type_name::<Self>()
}

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

#[inline]
fn any(&self) -> &dyn std::any::Any {
self
Expand Down Expand Up @@ -315,17 +330,34 @@ pub(crate) fn impl_value(
let partial_eq_fn = reflect_traits.get_partial_eq_impl(bevy_reflect_path);
let debug_fn = reflect_traits.get_debug_impl();

let typed_impl = impl_typed(
type_name,
generics,
quote! {
let info = #bevy_reflect_path::ValueInfo::new::<Self>();
#bevy_reflect_path::TypeInfo::Value(info)
},
bevy_reflect_path,
);

let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
TokenStream::from(quote! {
#get_type_registration_impl

#typed_impl

// SAFE: any and any_mut both return self
unsafe impl #impl_generics #bevy_reflect_path::Reflect for #type_name #ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}

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

#[inline]
fn any(&self) -> &dyn std::any::Any {
self
Expand Down Expand Up @@ -385,3 +417,38 @@ pub(crate) fn impl_value(
}
})
}

fn impl_typed(
type_name: &Ident,
generics: &Generics,
generator: proc_macro2::TokenStream,
bevy_reflect_path: &Path,
) -> proc_macro2::TokenStream {
let is_generic = !generics.params.is_empty();

let static_generator = if is_generic {
quote! {
static CELL: #bevy_reflect_path::utility::TypeInfoCell = #bevy_reflect_path::utility::TypeInfoCell::generic();
CELL.get_or_insert::<Self, _>(|| {
#generator
})
}
} else {
quote! {
static CELL: #bevy_reflect_path::utility::TypeInfoCell = #bevy_reflect_path::utility::TypeInfoCell::non_generic();
CELL.get_or_insert::<Self, _>(|| {
#generator
})
}
};

let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

quote! {
impl #impl_generics #bevy_reflect_path::Typed for #type_name #ty_generics #where_clause {
fn type_info() -> &'static #bevy_reflect_path::TypeInfo {
#static_generator
}
}
}
}
86 changes: 83 additions & 3 deletions crates/bevy_reflect/src/array.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{serde::Serializable, Reflect, ReflectMut, ReflectRef};
use std::fmt::Debug;
use crate::utility::TypeInfoCell;
use crate::{serde::Serializable, DynamicInfo, Reflect, ReflectMut, ReflectRef, TypeInfo, Typed};
use std::{
any::Any,
any::{Any, TypeId},
fmt::Debug,
hash::{Hash, Hasher},
};

Expand Down Expand Up @@ -37,6 +38,73 @@ pub trait Array: Reflect {
}
}

/// A container for compile-time array info.
#[derive(Clone, Debug)]
pub struct ArrayInfo {
type_name: &'static str,
type_id: TypeId,
item_type_name: &'static str,
item_type_id: TypeId,
capacity: usize,
}

impl ArrayInfo {
/// Create a new [`ArrayInfo`].
///
/// # Arguments
///
/// * `capacity`: The maximum capacity of the underlying array.
///
pub fn new<TArray: Array, TItem: Reflect>(capacity: usize) -> Self {
Self {
type_name: std::any::type_name::<TArray>(),
type_id: TypeId::of::<TArray>(),
item_type_name: std::any::type_name::<TItem>(),
item_type_id: TypeId::of::<TItem>(),
capacity,
}
}

/// The compile-time capacity of the array.
pub fn capacity(&self) -> usize {
self.capacity
}

/// The [type name] of the array.
///
/// [type name]: std::any::type_name
pub fn type_name(&self) -> &'static str {
self.type_name
}

/// The [`TypeId`] of the array.
pub fn type_id(&self) -> TypeId {
self.type_id
}

/// Check if the given type matches the array type.
pub fn is<T: Any>(&self) -> bool {
TypeId::of::<T>() == self.type_id
}

/// The [type name] of the array item.
///
/// [type name]: std::any::type_name
pub fn item_type_name(&self) -> &'static str {
self.item_type_name
}

/// The [`TypeId`] of the array item.
pub fn item_type_id(&self) -> TypeId {
self.item_type_id
}

/// Check if the given type matches the array item type.
pub fn item_is<T: Any>(&self) -> bool {
TypeId::of::<T>() == self.item_type_id
}
}

/// A fixed-size list of reflected values.
///
/// This differs from [`DynamicList`] in that the size of the [`DynamicArray`]
Expand Down Expand Up @@ -89,6 +157,11 @@ unsafe impl Reflect for DynamicArray {
self.name.as_str()
}

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

#[inline]
fn any(&self) -> &dyn Any {
self
Expand Down Expand Up @@ -185,6 +258,13 @@ impl Array for DynamicArray {
}
}

impl Typed for DynamicArray {
fn type_info() -> &'static TypeInfo {
static CELL: TypeInfoCell = TypeInfoCell::non_generic();
CELL.get_or_insert::<Self, _>(|| TypeInfo::Dynamic(DynamicInfo::new::<Self>()))
}
}

/// An iterator over an [`Array`].
pub struct ArrayIter<'a> {
pub(crate) array: &'a dyn Array,
Expand Down
Loading