diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index a7d6ef8828aff..42498da3b6203 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,10 +1,11 @@ +use crate::type_info::impl_type_methods; use crate::{ self as bevy_reflect, utility::reflect_hasher, ApplyError, MaybeTyped, PartialReflect, Reflect, - ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, + ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; use bevy_reflect_derive::impl_type_path; use std::{ - any::{Any, TypeId}, + any::Any, fmt::{Debug, Formatter}, hash::{Hash, Hasher}, }; @@ -77,11 +78,9 @@ pub trait Array: PartialReflect { /// A container for compile-time array info. #[derive(Clone, Debug)] pub struct ArrayInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, item_info: fn() -> Option<&'static TypeInfo>, - item_type_path: TypePathTable, - item_type_id: TypeId, + item_ty: Type, capacity: usize, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -98,11 +97,9 @@ impl ArrayInfo { capacity: usize, ) -> Self { Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), item_info: TItem::maybe_type_info, - item_type_path: TypePathTable::of::(), - item_type_id: TypeId::of::(), + item_ty: Type::of::(), capacity, #[cfg(feature = "documentation")] docs: None, @@ -120,32 +117,7 @@ impl ArrayInfo { self.capacity } - /// A representation of the type path of the array. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the array. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// 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(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The [`TypeInfo`] of the array item. /// @@ -155,21 +127,11 @@ impl ArrayInfo { (self.item_info)() } - /// A representation of the type path of the array item. + /// The [type] of the array item. /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn item_type_path_table(&self) -> &TypePathTable { - &self.item_type_path - } - - /// 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(&self) -> bool { - TypeId::of::() == self.item_type_id + /// [type]: Type + pub fn item_ty(&self) -> Type { + self.item_ty } /// The docstring of this array, if any. diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index 993f08a7c110f..f3fe336fccb55 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -1,7 +1,7 @@ use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; -use crate::{DynamicEnum, PartialReflect, TypePath, TypePathTable, VariantInfo, VariantType}; +use crate::type_info::impl_type_methods; +use crate::{DynamicEnum, PartialReflect, Type, TypePath, VariantInfo, VariantType}; use bevy_utils::HashMap; -use std::any::{Any, TypeId}; use std::slice::Iter; use std::sync::Arc; @@ -135,8 +135,7 @@ pub trait Enum: PartialReflect { /// A container for compile-time enum info, used by [`TypeInfo`](crate::TypeInfo). #[derive(Clone, Debug)] pub struct EnumInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, variants: Box<[VariantInfo]>, variant_names: Box<[&'static str]>, variant_indices: HashMap<&'static str, usize>, @@ -162,8 +161,7 @@ impl EnumInfo { let variant_names = variants.iter().map(VariantInfo::name).collect(); Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), variants: variants.to_vec().into_boxed_slice(), variant_names, variant_indices, @@ -231,32 +229,7 @@ impl EnumInfo { self.variants.len() } - /// A representation of the type path of the value. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the value. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the enum. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the enum type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The docstring of this enum, if any. #[cfg(feature = "documentation")] diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index e20d952ac5097..56f6a25879098 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,6 +1,6 @@ use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; -use crate::{MaybeTyped, PartialReflect, TypeInfo, TypePath, TypePathTable}; -use std::any::{Any, TypeId}; +use crate::type_info::impl_type_methods; +use crate::{MaybeTyped, PartialReflect, Type, TypeInfo, TypePath}; use std::sync::Arc; /// The named field of a reflected struct. @@ -8,8 +8,7 @@ use std::sync::Arc; pub struct NamedField { name: &'static str, type_info: fn() -> Option<&'static TypeInfo>, - type_path: TypePathTable, - type_id: TypeId, + ty: Type, custom_attributes: Arc, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -21,8 +20,7 @@ impl NamedField { Self { name, type_info: T::maybe_type_info, - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), custom_attributes: Arc::new(CustomAttributes::default()), #[cfg(feature = "documentation")] docs: None, @@ -57,32 +55,7 @@ impl NamedField { (self.type_info)() } - /// A representation of the type path of the field. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the field. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the field. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the field type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The docstring of this field, if any. #[cfg(feature = "documentation")] @@ -98,8 +71,7 @@ impl NamedField { pub struct UnnamedField { index: usize, type_info: fn() -> Option<&'static TypeInfo>, - type_path: TypePathTable, - type_id: TypeId, + ty: Type, custom_attributes: Arc, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -110,8 +82,7 @@ impl UnnamedField { Self { index, type_info: T::maybe_type_info, - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), custom_attributes: Arc::new(CustomAttributes::default()), #[cfg(feature = "documentation")] docs: None, @@ -146,32 +117,7 @@ impl UnnamedField { (self.type_info)() } - /// A representation of the type path of the field. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the field. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the field. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the field type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The docstring of this field, if any. #[cfg(feature = "documentation")] diff --git a/crates/bevy_reflect/src/func/args/info.rs b/crates/bevy_reflect/src/func/args/info.rs index e932e77be3f33..3c1098637c17e 100644 --- a/crates/bevy_reflect/src/func/args/info.rs +++ b/crates/bevy_reflect/src/func/args/info.rs @@ -1,7 +1,8 @@ use alloc::borrow::Cow; use crate::func::args::{GetOwnership, Ownership}; -use crate::TypePath; +use crate::type_info::impl_type_methods; +use crate::{Type, TypePath}; /// Type information for an [`Arg`] used in a [`DynamicFunction`] or [`DynamicFunctionMut`]. /// @@ -16,10 +17,10 @@ pub struct ArgInfo { name: Option>, /// The ownership of the argument. ownership: Ownership, - /// The [type path] of the argument. + /// The [type] of the argument. /// - /// [type path]: TypePath::type_path - type_path: &'static str, + /// [type]: Type + ty: Type, } impl ArgInfo { @@ -31,7 +32,7 @@ impl ArgInfo { index, name: None, ownership: T::ownership(), - type_path: T::type_path(), + ty: Type::of::(), } } @@ -72,12 +73,7 @@ impl ArgInfo { self.ownership } - /// The [type path] of the argument. - /// - /// [type path]: TypePath::type_path - pub fn type_path(&self) -> &'static str { - self.type_path - } + impl_type_methods!(ty); /// Get an ID representing the argument. /// diff --git a/crates/bevy_reflect/src/func/info.rs b/crates/bevy_reflect/src/func/info.rs index 413af8a3ed511..8627424dd0188 100644 --- a/crates/bevy_reflect/src/func/info.rs +++ b/crates/bevy_reflect/src/func/info.rs @@ -3,7 +3,8 @@ use alloc::borrow::Cow; use bevy_utils::all_tuples; use crate::func::args::{ArgInfo, GetOwnership, Ownership}; -use crate::TypePath; +use crate::type_info::impl_type_methods; +use crate::{Type, TypePath}; /// Type information for a [`DynamicFunction`] or [`DynamicFunctionMut`]. /// @@ -140,7 +141,7 @@ impl FunctionInfo { /// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut #[derive(Debug, Clone)] pub struct ReturnInfo { - type_path: &'static str, + ty: Type, ownership: Ownership, } @@ -148,17 +149,14 @@ impl ReturnInfo { /// Create a new [`ReturnInfo`] representing the given type, `T`. pub fn new() -> Self { Self { - type_path: T::type_path(), + ty: Type::of::(), ownership: T::ownership(), } } - /// The type path of the return type. - pub fn type_path(&self) -> &'static str { - self.type_path - } + impl_type_methods!(ty); - /// The ownership of the return type. + /// The ownership of this type. pub fn ownership(&self) -> Ownership { self.ownership } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 941105a851e99..29829130feeac 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1719,10 +1719,10 @@ mod tests { let info = MyList::type_info().as_list().unwrap(); assert!(info.is::()); - assert!(info.item_is::()); + assert!(info.item_ty().is::()); assert!(info.item_info().unwrap().is::()); assert_eq!(MyList::type_path(), info.type_path()); - assert_eq!(usize::type_path(), info.item_type_path_table().path()); + assert_eq!(usize::type_path(), info.item_ty().path()); let value: &dyn Reflect = &vec![123_usize]; let info = value.get_represented_type_info().unwrap(); @@ -1735,10 +1735,10 @@ mod tests { let info = MySmallVec::type_info().as_list().unwrap(); assert!(info.is::()); - assert!(info.item_is::()); + assert!(info.item_ty().is::()); assert!(info.item_info().unwrap().is::()); assert_eq!(MySmallVec::type_path(), info.type_path()); - assert_eq!(String::type_path(), info.item_type_path_table().path()); + assert_eq!(String::type_path(), info.item_ty().path()); let value: MySmallVec = smallvec::smallvec![String::default(); 2]; let value: &dyn Reflect = &value; @@ -1751,10 +1751,10 @@ mod tests { let info = MyArray::type_info().as_array().unwrap(); assert!(info.is::()); - assert!(info.item_is::()); + assert!(info.item_ty().is::()); assert!(info.item_info().unwrap().is::()); assert_eq!(MyArray::type_path(), info.type_path()); - assert_eq!(usize::type_path(), info.item_type_path_table().path()); + assert_eq!(usize::type_path(), info.item_ty().path()); assert_eq!(3, info.capacity()); let value: &dyn Reflect = &[1usize, 2usize, 3usize]; @@ -1779,13 +1779,10 @@ mod tests { let info = MyCowSlice::type_info().as_list().unwrap(); assert!(info.is::()); - assert!(info.item_is::()); + assert!(info.item_ty().is::()); assert!(info.item_info().unwrap().is::()); assert_eq!(std::any::type_name::(), info.type_path()); - assert_eq!( - std::any::type_name::(), - info.item_type_path_table().path() - ); + assert_eq!(std::any::type_name::(), info.item_ty().path()); let value: &dyn Reflect = &Cow::<'static, [u8]>::Owned(vec![0, 1, 2, 3]); let info = value.get_represented_type_info().unwrap(); @@ -1797,13 +1794,13 @@ mod tests { let info = MyMap::type_info().as_map().unwrap(); assert!(info.is::()); - assert!(info.key_is::()); - assert!(info.value_is::()); + assert!(info.key_ty().is::()); + assert!(info.value_ty().is::()); assert!(info.key_info().unwrap().is::()); assert!(info.value_info().unwrap().is::()); assert_eq!(MyMap::type_path(), info.type_path()); - assert_eq!(usize::type_path(), info.key_type_path_table().path()); - assert_eq!(f32::type_path(), info.value_type_path_table().path()); + assert_eq!(usize::type_path(), info.key_ty().path()); + assert_eq!(f32::type_path(), info.value_ty().path()); let value: &dyn Reflect = &MyMap::new(); let info = value.get_represented_type_info().unwrap(); diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 3a29c5733e659..b44a7e1c0db78 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -1,13 +1,14 @@ -use std::any::{Any, TypeId}; +use std::any::Any; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher}; use bevy_reflect_derive::impl_type_path; +use crate::type_info::impl_type_methods; use crate::utility::reflect_hasher; use crate::{ self as bevy_reflect, ApplyError, FromReflect, MaybeTyped, PartialReflect, Reflect, - ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, + ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; /// A trait used to power [list-like] operations via [reflection]. @@ -108,11 +109,9 @@ pub trait List: PartialReflect { /// A container for compile-time list info. #[derive(Clone, Debug)] pub struct ListInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, item_info: fn() -> Option<&'static TypeInfo>, - item_type_path: TypePathTable, - item_type_id: TypeId, + item_ty: Type, #[cfg(feature = "documentation")] docs: Option<&'static str>, } @@ -121,11 +120,9 @@ impl ListInfo { /// Create a new [`ListInfo`]. pub fn new() -> Self { Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), item_info: TItem::maybe_type_info, - item_type_path: TypePathTable::of::(), - item_type_id: TypeId::of::(), + item_ty: Type::of::(), #[cfg(feature = "documentation")] docs: None, } @@ -137,32 +134,7 @@ impl ListInfo { Self { docs, ..self } } - /// A representation of the type path of the list. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the list. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the list. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the list type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The [`TypeInfo`] of the list item. /// @@ -172,21 +144,11 @@ impl ListInfo { (self.item_info)() } - /// A representation of the type path of the list item. + /// The [type] of the list item. /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn item_type_path_table(&self) -> &TypePathTable { - &self.item_type_path - } - - /// The [`TypeId`] of the list item. - pub fn item_type_id(&self) -> TypeId { - self.item_type_id - } - - /// Check if the given type matches the list item type. - pub fn item_is(&self) -> bool { - TypeId::of::() == self.item_type_id + /// [type]: Type + pub fn item_ty(&self) -> Type { + self.item_ty } /// The docstring of this list, if any. diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index b619a091eff2c..4b192d6b75c97 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -1,12 +1,12 @@ -use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; +use crate::type_info::impl_type_methods; use crate::{ self as bevy_reflect, ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, + ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; /// A trait used to power [map-like] operations via [reflection]. @@ -97,14 +97,11 @@ pub trait Map: PartialReflect { /// A container for compile-time map info. #[derive(Clone, Debug)] pub struct MapInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, key_info: fn() -> Option<&'static TypeInfo>, - key_type_path: TypePathTable, - key_type_id: TypeId, + key_ty: Type, value_info: fn() -> Option<&'static TypeInfo>, - value_type_path: TypePathTable, - value_type_id: TypeId, + value_ty: Type, #[cfg(feature = "documentation")] docs: Option<&'static str>, } @@ -117,14 +114,11 @@ impl MapInfo { TValue: Reflect + MaybeTyped + TypePath, >() -> Self { Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), key_info: TKey::maybe_type_info, - key_type_path: TypePathTable::of::(), - key_type_id: TypeId::of::(), + key_ty: Type::of::(), value_info: TValue::maybe_type_info, - value_type_path: TypePathTable::of::(), - value_type_id: TypeId::of::(), + value_ty: Type::of::(), #[cfg(feature = "documentation")] docs: None, } @@ -136,32 +130,7 @@ impl MapInfo { Self { docs, ..self } } - /// A representation of the type path of the map. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the map. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the map. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the map type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The [`TypeInfo`] of the key type. /// @@ -171,21 +140,11 @@ impl MapInfo { (self.key_info)() } - /// A representation of the type path of the key type. + /// The [type] of the key type. /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn key_type_path_table(&self) -> &TypePathTable { - &self.key_type_path - } - - /// The [`TypeId`] of the key. - pub fn key_type_id(&self) -> TypeId { - self.key_type_id - } - - /// Check if the given type matches the key type. - pub fn key_is(&self) -> bool { - TypeId::of::() == self.key_type_id + /// [type]: Type + pub fn key_ty(&self) -> Type { + self.key_ty } /// The [`TypeInfo`] of the value type. @@ -196,21 +155,11 @@ impl MapInfo { (self.value_info)() } - /// A representation of the type path of the value type. + /// The [type] of the value type. /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn value_type_path_table(&self) -> &TypePathTable { - &self.value_type_path - } - - /// The [`TypeId`] of the value. - pub fn value_type_id(&self) -> TypeId { - self.value_type_id - } - - /// Check if the given type matches the value type. - pub fn value_is(&self) -> bool { - TypeId::of::() == self.value_type_id + /// [type]: Type + pub fn value_ty(&self) -> Type { + self.value_ty } /// The docstring of this map, if any. diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 26fff47100e48..5563d9192f5e9 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -730,8 +730,8 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { { let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default()); let registration = get_registration( - self.array_info.item_type_id(), - self.array_info.item_type_path_table().path(), + self.array_info.item_ty().id(), + self.array_info.item_ty().path(), self.registry, )?; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { @@ -770,8 +770,8 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { { let mut list = DynamicList::default(); let registration = get_registration( - self.list_info.item_type_id(), - self.list_info.item_type_path_table().path(), + self.list_info.item_ty().id(), + self.list_info.item_ty().path(), self.registry, )?; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { @@ -802,13 +802,13 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { { let mut dynamic_map = DynamicMap::default(); let key_registration = get_registration( - self.map_info.key_type_id(), - self.map_info.key_type_path_table().path(), + self.map_info.key_ty().id(), + self.map_info.key_ty().path(), self.registry, )?; let value_registration = get_registration( - self.map_info.value_type_id(), - self.map_info.value_type_path_table().path(), + self.map_info.value_ty().id(), + self.map_info.value_ty().path(), self.registry, )?; while let Some(key) = map.next_key_seed(TypedReflectDeserializer { @@ -844,8 +844,8 @@ impl<'a, 'de> Visitor<'de> for SetVisitor<'a> { { let mut dynamic_set = DynamicSet::default(); let value_registration = get_registration( - self.set_info.value_type_id(), - self.set_info.value_type_path_table().path(), + self.set_info.value_ty().id(), + self.set_info.value_ty().path(), self.registry, )?; while let Some(value) = set.next_element_seed(TypedReflectDeserializer { diff --git a/crates/bevy_reflect/src/set.rs b/crates/bevy_reflect/src/set.rs index 08bcf4c163ece..3eb92470c84b5 100644 --- a/crates/bevy_reflect/src/set.rs +++ b/crates/bevy_reflect/src/set.rs @@ -1,13 +1,13 @@ -use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use bevy_reflect_derive::impl_type_path; use bevy_utils::hashbrown::hash_table::OccupiedEntry as HashTableOccupiedEntry; use bevy_utils::hashbrown::HashTable; +use crate::type_info::impl_type_methods; use crate::{ self as bevy_reflect, hash_error, ApplyError, PartialReflect, Reflect, ReflectKind, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, + ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; /// A trait used to power [set-like] operations via [reflection]. @@ -82,10 +82,8 @@ pub trait Set: PartialReflect { /// A container for compile-time set info. #[derive(Clone, Debug)] pub struct SetInfo { - type_path: TypePathTable, - type_id: TypeId, - value_type_path: TypePathTable, - value_type_id: TypeId, + ty: Type, + value_ty: Type, #[cfg(feature = "documentation")] docs: Option<&'static str>, } @@ -94,10 +92,8 @@ impl SetInfo { /// Create a new [`SetInfo`]. pub fn new() -> Self { Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), - value_type_path: TypePathTable::of::(), - value_type_id: TypeId::of::(), + ty: Type::of::(), + value_ty: Type::of::(), #[cfg(feature = "documentation")] docs: None, } @@ -109,48 +105,13 @@ impl SetInfo { Self { docs, ..self } } - /// A representation of the type path of the set. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the set. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the set. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the set type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); - /// A representation of the type path of the value type. + /// The [type] of the value. /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn value_type_path_table(&self) -> &TypePathTable { - &self.value_type_path - } - - /// The [`TypeId`] of the value. - pub fn value_type_id(&self) -> TypeId { - self.value_type_id - } - - /// Check if the given type matches the value type. - pub fn value_is(&self) -> bool { - TypeId::of::() == self.value_type_id + /// [type]: Type + pub fn value_ty(&self) -> Type { + self.value_ty } /// The docstring of this set, if any. diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 52dce37f91b94..d3c9493386209 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,17 +1,14 @@ use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; +use crate::type_info::impl_type_methods; use crate::{ self as bevy_reflect, ApplyError, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, + ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::HashMap; use std::fmt::{Debug, Formatter}; use std::sync::Arc; -use std::{ - any::{Any, TypeId}, - borrow::Cow, - slice::Iter, -}; +use std::{borrow::Cow, slice::Iter}; /// A trait used to power [struct-like] operations via [reflection]. /// @@ -78,8 +75,7 @@ pub trait Struct: PartialReflect { /// A container for compile-time named struct info. #[derive(Clone, Debug)] pub struct StructInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, fields: Box<[NamedField]>, field_names: Box<[&'static str]>, field_indices: HashMap<&'static str, usize>, @@ -105,8 +101,7 @@ impl StructInfo { let field_names = fields.iter().map(NamedField::name).collect(); Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), fields: fields.to_vec().into_boxed_slice(), field_names, field_indices, @@ -162,32 +157,7 @@ impl StructInfo { self.fields.len() } - /// A representation of the type path of the struct. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the struct. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the struct. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the struct type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The docstring of this struct, if any. #[cfg(feature = "documentation")] diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index b63a5f6c777e8..fe200ca1197bc 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,13 +1,14 @@ use bevy_reflect_derive::impl_type_path; use bevy_utils::all_tuples; +use crate::type_info::impl_type_methods; use crate::{ self as bevy_reflect, utility::GenericTypePathCell, ApplyError, FromReflect, - GetTypeRegistration, MaybeTyped, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + GetTypeRegistration, MaybeTyped, Reflect, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, TypeRegistration, TypeRegistry, Typed, UnnamedField, }; -use crate::{PartialReflect, ReflectKind, TypePathTable}; -use std::any::{Any, TypeId}; +use crate::{PartialReflect, ReflectKind}; +use std::any::Any; use std::fmt::{Debug, Formatter}; use std::slice::Iter; @@ -139,8 +140,7 @@ impl GetTupleField for dyn Tuple { /// A container for compile-time tuple info. #[derive(Clone, Debug)] pub struct TupleInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, fields: Box<[UnnamedField]>, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -155,8 +155,7 @@ impl TupleInfo { /// pub fn new(fields: &[UnnamedField]) -> Self { Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), fields: fields.to_vec().into_boxed_slice(), #[cfg(feature = "documentation")] docs: None, @@ -184,32 +183,7 @@ impl TupleInfo { self.fields.len() } - /// A representation of the type path of the tuple. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the tuple. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the tuple. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the tuple type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The docstring of this tuple, if any. #[cfg(feature = "documentation")] diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index dd923e47be795..6cdd3031f0489 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -1,11 +1,11 @@ use bevy_reflect_derive::impl_type_path; use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; +use crate::type_info::impl_type_methods; use crate::{ self as bevy_reflect, ApplyError, DynamicTuple, PartialReflect, Reflect, ReflectKind, - ReflectMut, ReflectOwned, ReflectRef, Tuple, TypeInfo, TypePath, TypePathTable, UnnamedField, + ReflectMut, ReflectOwned, ReflectRef, Tuple, Type, TypeInfo, TypePath, UnnamedField, }; -use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::slice::Iter; use std::sync::Arc; @@ -58,8 +58,7 @@ pub trait TupleStruct: PartialReflect { /// A container for compile-time tuple struct info. #[derive(Clone, Debug)] pub struct TupleStructInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, fields: Box<[UnnamedField]>, custom_attributes: Arc, #[cfg(feature = "documentation")] @@ -75,8 +74,7 @@ impl TupleStructInfo { /// pub fn new(fields: &[UnnamedField]) -> Self { Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), fields: fields.to_vec().into_boxed_slice(), custom_attributes: Arc::new(CustomAttributes::default()), #[cfg(feature = "documentation")] @@ -113,32 +111,7 @@ impl TupleStructInfo { self.fields.len() } - /// A representation of the type path of the struct. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the struct. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the tuple struct. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the tuple struct type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The docstring of this struct, if any. #[cfg(feature = "documentation")] diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index a6a7ceb240424..d3450239e6d3f 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -3,8 +3,10 @@ use crate::{ DynamicTupleStruct, EnumInfo, ListInfo, MapInfo, PartialReflect, Reflect, ReflectKind, SetInfo, StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable, }; +use core::fmt::Formatter; use std::any::{Any, TypeId}; use std::fmt::Debug; +use std::hash::Hash; use thiserror::Error; /// A static accessor to compile-time type information. @@ -178,36 +180,33 @@ pub enum TypeInfo { } impl TypeInfo { - /// The [`TypeId`] of the underlying type. - pub fn type_id(&self) -> TypeId { + /// The underlying Rust [type]. + /// + /// [type]: Type + pub fn ty(&self) -> &Type { match self { - Self::Struct(info) => info.type_id(), - Self::TupleStruct(info) => info.type_id(), - Self::Tuple(info) => info.type_id(), - Self::List(info) => info.type_id(), - Self::Array(info) => info.type_id(), - Self::Map(info) => info.type_id(), - Self::Set(info) => info.type_id(), - Self::Enum(info) => info.type_id(), - Self::Value(info) => info.type_id(), + Self::Struct(info) => info.ty(), + Self::TupleStruct(info) => info.ty(), + Self::Tuple(info) => info.ty(), + Self::List(info) => info.ty(), + Self::Array(info) => info.ty(), + Self::Map(info) => info.ty(), + Self::Set(info) => info.ty(), + Self::Enum(info) => info.ty(), + Self::Value(info) => info.ty(), } } + /// The [`TypeId`] of the underlying type. + pub fn type_id(&self) -> TypeId { + self.ty().id() + } + /// A representation of the type path of the underlying type. /// /// Provides dynamic access to all methods on [`TypePath`]. pub fn type_path_table(&self) -> &TypePathTable { - match self { - Self::Struct(info) => info.type_path_table(), - Self::TupleStruct(info) => info.type_path_table(), - Self::Tuple(info) => info.type_path_table(), - Self::List(info) => info.type_path_table(), - Self::Array(info) => info.type_path_table(), - Self::Map(info) => info.type_path_table(), - Self::Set(info) => info.type_path_table(), - Self::Enum(info) => info.type_path_table(), - Self::Value(info) => info.type_path_table(), - } + self.ty().type_path_table() } /// The [stable, full type path] of the underlying type. @@ -217,12 +216,16 @@ impl TypeInfo { /// [stable, full type path]: TypePath /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_table().path() + self.ty().path() } - /// Check if the given type matches the underlying type. + /// Check if the given type matches this one. + /// + /// This only compares the [`TypeId`] of the types + /// and does not verify they share the same [`TypePath`] + /// (though it implies they do). pub fn is(&self) -> bool { - TypeId::of::() == self.type_id() + self.ty().is::() } /// The docstring of the underlying type, if any. @@ -287,6 +290,199 @@ impl TypeInfo { impl_cast_method!(as_value: Value => ValueInfo); } +/// The base representation of a Rust type. +/// +/// When possible, it is recommended to use [`&'static TypeInfo`] instead of this +/// as it provides more information as well as being smaller +/// (since a reference only takes the same number of bytes as a `usize`). +/// +/// However, where a static reference to [`TypeInfo`] is not possible, +/// such as with trait objects and other types that can't implement [`Typed`], +/// this type can be used instead. +/// +/// It only requires that the type implements [`TypePath`]. +/// +/// And unlike [`TypeInfo`], this type implements [`Copy`], [`Eq`], and [`Hash`], +/// making it useful as a key type. +/// +/// It's especially helpful when compared to [`TypeId`] as it can provide the +/// actual [type path] when debugging, while still having the same performance +/// as hashing/comparing [`TypeId`] directly—at the cost of a little more memory. +/// +/// # Examples +/// +/// ``` +/// use bevy_reflect::{Type, TypePath}; +/// +/// fn assert_char(t: &T) -> Result<(), String> { +/// let ty = Type::of::(); +/// if Type::of::() == ty { +/// Ok(()) +/// } else { +/// Err(format!("expected `char`, got `{}`", ty.path())) +/// } +/// } +/// +/// assert_eq!( +/// assert_char(&'a'), +/// Ok(()) +/// ); +/// assert_eq!( +/// assert_char(&String::from("Hello, world!")), +/// Err(String::from("expected `char`, got `alloc::string::String`")) +/// ); +/// ``` +/// +/// [`&'static TypeInfo`]: TypeInfo +#[derive(Copy, Clone)] +pub struct Type { + type_path_table: TypePathTable, + type_id: TypeId, +} + +impl Type { + /// Create a new [`Type`] from a type that implements [`TypePath`]. + pub fn of() -> Self { + Self { + type_path_table: TypePathTable::of::(), + type_id: TypeId::of::(), + } + } + + /// Returns the [`TypeId`] of the type. + pub fn id(&self) -> TypeId { + self.type_id + } + + /// See [`TypePath::type_path`]. + pub fn path(&self) -> &'static str { + self.type_path_table.path() + } + + /// See [`TypePath::short_type_path`]. + pub fn short_path(&self) -> &'static str { + self.type_path_table.short_path() + } + + /// See [`TypePath::type_ident`]. + pub fn ident(&self) -> Option<&'static str> { + self.type_path_table.ident() + } + + /// See [`TypePath::crate_name`]. + pub fn crate_name(&self) -> Option<&'static str> { + self.type_path_table.crate_name() + } + + /// See [`TypePath::module_path`]. + pub fn module_path(&self) -> Option<&'static str> { + self.type_path_table.module_path() + } + + /// A representation of the type path of this. + /// + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_table(&self) -> &TypePathTable { + &self.type_path_table + } + + /// Check if the given type matches this one. + /// + /// This only compares the [`TypeId`] of the types + /// and does not verify they share the same [`TypePath`] + /// (though it implies they do). + pub fn is(&self) -> bool { + TypeId::of::() == self.type_id + } +} + +/// This implementation will only output the [type path] of the type. +/// +/// If you need to include the [`TypeId`] in the output, +/// you can access it through [`Type::id`]. +/// +/// [type path]: TypePath +impl Debug for Type { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.type_path_table.path()) + } +} + +impl Eq for Type {} + +/// This implementation purely relies on the [`TypeId`] of the type, +/// and not on the [type path]. +/// +/// [type path]: TypePath +impl PartialEq for Type { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.type_id == other.type_id + } +} + +/// This implementation purely relies on the [`TypeId`] of the type, +/// and not on the [type path]. +/// +/// [type path]: TypePath +impl Hash for Type { + #[inline] + fn hash(&self, state: &mut H) { + self.type_id.hash(state); + } +} + +macro_rules! impl_type_methods { + ($field:ident) => { + /// The underlying Rust [type]. + /// + /// [type]: crate::type_info::Type + pub fn ty(&self) -> &$crate::type_info::Type { + &self.$field + } + + /// The [`TypeId`] of this type. + /// + /// [`TypeId`]: std::any::TypeId + pub fn type_id(&self) -> ::std::any::TypeId { + self.$field.id() + } + + /// The [stable, full type path] of this type. + /// + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. + /// + /// [stable, full type path]: TypePath + /// [`type_path_table`]: Self::type_path_table + pub fn type_path(&self) -> &'static str { + self.$field.path() + } + + /// A representation of the type path of this type. + /// + /// Provides dynamic access to all methods on [`TypePath`]. + /// + /// [`TypePath`]: crate::type_path::TypePath + pub fn type_path_table(&self) -> &$crate::type_path::TypePathTable { + &self.$field.type_path_table() + } + + /// Check if the given type matches this one. + /// + /// This only compares the [`TypeId`] of the types + /// and does not verify they share the same [`TypePath`] + /// (though it implies they do). + /// + /// [`TypeId`]: std::any::TypeId + /// [`TypePath`]: crate::type_path::TypePath + pub fn is(&self) -> bool { + self.$field.is::() + } + }; +} + +pub(crate) use impl_type_methods; + /// A container for compile-time info related to general value types, including primitives. /// /// This typically represents a type which cannot be broken down any further. This is often @@ -297,8 +493,7 @@ impl TypeInfo { /// it _as_ a struct. It therefore makes more sense to represent it as a [`ValueInfo`]. #[derive(Debug, Clone)] pub struct ValueInfo { - type_path: TypePathTable, - type_id: TypeId, + ty: Type, #[cfg(feature = "documentation")] docs: Option<&'static str>, } @@ -306,8 +501,7 @@ pub struct ValueInfo { impl ValueInfo { pub fn new() -> Self { Self { - type_path: TypePathTable::of::(), - type_id: TypeId::of::(), + ty: Type::of::(), #[cfg(feature = "documentation")] docs: None, } @@ -319,32 +513,7 @@ impl ValueInfo { Self { docs: doc, ..self } } - /// A representation of the type path of the value. - /// - /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_table(&self) -> &TypePathTable { - &self.type_path - } - - /// The [stable, full type path] of the value. - /// - /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. - /// - /// [stable, full type path]: TypePath - /// [`type_path_table`]: Self::type_path_table - pub fn type_path(&self) -> &'static str { - self.type_path_table().path() - } - - /// The [`TypeId`] of the value. - pub fn type_id(&self) -> TypeId { - self.type_id - } - - /// Check if the given type matches the value type. - pub fn is(&self) -> bool { - TypeId::of::() == self.type_id - } + impl_type_methods!(ty); /// The docstring of this dynamic value, if any. #[cfg(feature = "documentation")]