mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
bevy_reflect: Add Type
type (#14838)
# Objective Closes #7622. I was working on adding support for reflecting generic functions and found that I wanted to use an argument's `TypeId` for hashing and comparison, but its `TypePath` for debugging and error messaging. While I could just keep them separate, place them in a tuple or a local struct or something, I think I see an opportunity to make a dedicate type for this. Additionally, we can use this type to clean up some duplication amongst the type info structs in a manner similar to #7622. ## Solution Added the `Type` type. This should be seen as the most basic representation of a type apart from `TypeId`. It stores both the `TypeId` of the type as well as its `TypePathTable`. The `Hash` and `PartialEq` implementations rely on the `TypeId`, while the `Debug` implementation relies on the `TypePath`. This makes it especially useful as a key in a `HashMap` since we get the speed of the `TypeId` hashing/comparisons with the readability of `TypePath`. With this type, we're able to reduce the duplication across the type info structs by removing individual fields for `TypeId` and `TypePathTable`, replacing them with a single `Type` field. Similarly, we can remove many duplicate methods and replace it with a macro that delegates to the stored `Type`. ### Caveats It should be noted that this type is currently 3x larger than `TypeId`. On my machine, it's 48 bytes compared to `TypeId`'s 16. While this doesn't matter for `TypeInfo` since it would contain that data regardless, it is something to keep in mind when using elsewhere. ## Testing All tests should pass as normal: ``` cargo test --package bevy_reflect ``` --- ## Showcase `bevy_reflect` now exports a `Type` struct. This type contains both the `TypeId` and the `TypePathTable` of the given type, allowing it to be used like `TypeId` but have the debuggability of `TypePath`. ```rust // We can create this for any type implementing `TypePath`: let ty = Type::of::<String>(); // It has `Hash` and `Eq` impls powered by `TypeId`, making it useful for maps: let mut map = HashMap::<Type, i32>::new(); map.insert(ty, 25); // And it has a human-readable `Debug` representation: let debug = format!("{:?}", map); assert_eq!(debug, "{alloc::string::String: 25}"); ``` ## Migration Guide Certain type info structs now only return their item types as `Type` instead of exposing direct methods on them. The following methods have been removed: - `ArrayInfo::item_type_path_table` - `ArrayInfo::item_type_id` - `ArrayInfo::item_is` - `ListInfo::item_type_path_table` - `ListInfo::item_type_id` - `ListInfo::item_is` - `SetInfo::value_type_path_table` - `SetInfo::value_type_id` - `SetInfo::value_is` - `MapInfo::key_type_path_table` - `MapInfo::key_type_id` - `MapInfo::key_is` - `MapInfo::value_type_path_table` - `MapInfo::value_type_id` - `MapInfo::value_is` Instead, access the `Type` directly using one of the new methods: - `ArrayInfo::item_ty` - `ListInfo::item_ty` - `SetInfo::value_ty` - `MapInfo::key_ty` - `MapInfo::value_ty` For example: ```rust // BEFORE let type_id = array_info.item_type_id(); // AFTER let type_id = array_info.item_ty().id(); ```
This commit is contained in:
parent
f9d7a2ca02
commit
3892adcb47
14 changed files with 343 additions and 513 deletions
|
@ -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::<TArray>(),
|
||||
type_id: TypeId::of::<TArray>(),
|
||||
ty: Type::of::<TArray>(),
|
||||
item_info: TItem::maybe_type_info,
|
||||
item_type_path: TypePathTable::of::<TItem>(),
|
||||
item_type_id: TypeId::of::<TItem>(),
|
||||
item_ty: Type::of::<TItem>(),
|
||||
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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == 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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.item_type_id
|
||||
/// [type]: Type
|
||||
pub fn item_ty(&self) -> Type {
|
||||
self.item_ty
|
||||
}
|
||||
|
||||
/// The docstring of this array, if any.
|
||||
|
|
|
@ -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::<TEnum>(),
|
||||
type_id: TypeId::of::<TEnum>(),
|
||||
ty: Type::of::<TEnum>(),
|
||||
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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id
|
||||
}
|
||||
impl_type_methods!(ty);
|
||||
|
||||
/// The docstring of this enum, if any.
|
||||
#[cfg(feature = "documentation")]
|
||||
|
|
|
@ -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<CustomAttributes>,
|
||||
#[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::<T>(),
|
||||
type_id: TypeId::of::<T>(),
|
||||
ty: Type::of::<T>(),
|
||||
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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == 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<CustomAttributes>,
|
||||
#[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::<T>(),
|
||||
type_id: TypeId::of::<T>(),
|
||||
ty: Type::of::<T>(),
|
||||
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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id
|
||||
}
|
||||
impl_type_methods!(ty);
|
||||
|
||||
/// The docstring of this field, if any.
|
||||
#[cfg(feature = "documentation")]
|
||||
|
|
|
@ -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<Cow<'static, str>>,
|
||||
/// 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::<T>(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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<T: TypePath + GetOwnership>() -> Self {
|
||||
Self {
|
||||
type_path: T::type_path(),
|
||||
ty: Type::of::<T>(),
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1719,10 +1719,10 @@ mod tests {
|
|||
let info = MyList::type_info().as_list().unwrap();
|
||||
|
||||
assert!(info.is::<MyList>());
|
||||
assert!(info.item_is::<usize>());
|
||||
assert!(info.item_ty().is::<usize>());
|
||||
assert!(info.item_info().unwrap().is::<usize>());
|
||||
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::<MySmallVec>());
|
||||
assert!(info.item_is::<String>());
|
||||
assert!(info.item_ty().is::<String>());
|
||||
assert!(info.item_info().unwrap().is::<String>());
|
||||
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::<MyArray>());
|
||||
assert!(info.item_is::<usize>());
|
||||
assert!(info.item_ty().is::<usize>());
|
||||
assert!(info.item_info().unwrap().is::<usize>());
|
||||
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::<MyCowSlice>());
|
||||
assert!(info.item_is::<u8>());
|
||||
assert!(info.item_ty().is::<u8>());
|
||||
assert!(info.item_info().unwrap().is::<u8>());
|
||||
assert_eq!(std::any::type_name::<MyCowSlice>(), info.type_path());
|
||||
assert_eq!(
|
||||
std::any::type_name::<u8>(),
|
||||
info.item_type_path_table().path()
|
||||
);
|
||||
assert_eq!(std::any::type_name::<u8>(), 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::<MyMap>());
|
||||
assert!(info.key_is::<usize>());
|
||||
assert!(info.value_is::<f32>());
|
||||
assert!(info.key_ty().is::<usize>());
|
||||
assert!(info.value_ty().is::<f32>());
|
||||
assert!(info.key_info().unwrap().is::<usize>());
|
||||
assert!(info.value_info().unwrap().is::<f32>());
|
||||
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();
|
||||
|
|
|
@ -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<TList: List + TypePath, TItem: FromReflect + MaybeTyped + TypePath>() -> Self {
|
||||
Self {
|
||||
type_path: TypePathTable::of::<TList>(),
|
||||
type_id: TypeId::of::<TList>(),
|
||||
ty: Type::of::<TList>(),
|
||||
item_info: TItem::maybe_type_info,
|
||||
item_type_path: TypePathTable::of::<TItem>(),
|
||||
item_type_id: TypeId::of::<TItem>(),
|
||||
item_ty: Type::of::<TItem>(),
|
||||
#[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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == 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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.item_type_id
|
||||
/// [type]: Type
|
||||
pub fn item_ty(&self) -> Type {
|
||||
self.item_ty
|
||||
}
|
||||
|
||||
/// The docstring of this list, if any.
|
||||
|
|
|
@ -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::<TMap>(),
|
||||
type_id: TypeId::of::<TMap>(),
|
||||
ty: Type::of::<TMap>(),
|
||||
key_info: TKey::maybe_type_info,
|
||||
key_type_path: TypePathTable::of::<TKey>(),
|
||||
key_type_id: TypeId::of::<TKey>(),
|
||||
key_ty: Type::of::<TKey>(),
|
||||
value_info: TValue::maybe_type_info,
|
||||
value_type_path: TypePathTable::of::<TValue>(),
|
||||
value_type_id: TypeId::of::<TValue>(),
|
||||
value_ty: Type::of::<TValue>(),
|
||||
#[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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == 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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == 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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.value_type_id
|
||||
/// [type]: Type
|
||||
pub fn value_ty(&self) -> Type {
|
||||
self.value_ty
|
||||
}
|
||||
|
||||
/// The docstring of this map, if any.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<TSet: Set + TypePath, TValue: Reflect + TypePath>() -> Self {
|
||||
Self {
|
||||
type_path: TypePathTable::of::<TSet>(),
|
||||
type_id: TypeId::of::<TSet>(),
|
||||
value_type_path: TypePathTable::of::<TValue>(),
|
||||
value_type_id: TypeId::of::<TValue>(),
|
||||
ty: Type::of::<TSet>(),
|
||||
value_ty: Type::of::<TValue>(),
|
||||
#[cfg(feature = "documentation")]
|
||||
docs: None,
|
||||
}
|
||||
|
@ -109,48 +105,13 @@ impl SetInfo {
|
|||
Self { docs, ..self }
|
||||
}
|
||||
|
||||
/// A representation of the type path of the set.
|
||||
impl_type_methods!(ty);
|
||||
|
||||
/// The [type] 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 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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id
|
||||
}
|
||||
|
||||
/// A representation of the type path 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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.value_type_id
|
||||
/// [type]: Type
|
||||
pub fn value_ty(&self) -> Type {
|
||||
self.value_ty
|
||||
}
|
||||
|
||||
/// The docstring of this set, if any.
|
||||
|
|
|
@ -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::<T>(),
|
||||
type_id: TypeId::of::<T>(),
|
||||
ty: Type::of::<T>(),
|
||||
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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id
|
||||
}
|
||||
impl_type_methods!(ty);
|
||||
|
||||
/// The docstring of this struct, if any.
|
||||
#[cfg(feature = "documentation")]
|
||||
|
|
|
@ -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<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
|
||||
Self {
|
||||
type_path: TypePathTable::of::<T>(),
|
||||
type_id: TypeId::of::<T>(),
|
||||
ty: Type::of::<T>(),
|
||||
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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id
|
||||
}
|
||||
impl_type_methods!(ty);
|
||||
|
||||
/// The docstring of this tuple, if any.
|
||||
#[cfg(feature = "documentation")]
|
||||
|
|
|
@ -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<CustomAttributes>,
|
||||
#[cfg(feature = "documentation")]
|
||||
|
@ -75,8 +74,7 @@ impl TupleStructInfo {
|
|||
///
|
||||
pub fn new<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
|
||||
Self {
|
||||
type_path: TypePathTable::of::<T>(),
|
||||
type_id: TypeId::of::<T>(),
|
||||
ty: Type::of::<T>(),
|
||||
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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id
|
||||
}
|
||||
impl_type_methods!(ty);
|
||||
|
||||
/// The docstring of this struct, if any.
|
||||
#[cfg(feature = "documentation")]
|
||||
|
|
|
@ -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 underlying Rust [type].
|
||||
///
|
||||
/// [type]: Type
|
||||
pub fn ty(&self) -> &Type {
|
||||
match self {
|
||||
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 {
|
||||
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.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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id()
|
||||
self.ty().is::<T>()
|
||||
}
|
||||
|
||||
/// 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: ?Sized + TypePath>(t: &T) -> Result<(), String> {
|
||||
/// let ty = Type::of::<T>();
|
||||
/// if Type::of::<char>() == 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<T: TypePath + ?Sized>() -> Self {
|
||||
Self {
|
||||
type_path_table: TypePathTable::of::<T>(),
|
||||
type_id: TypeId::of::<T>(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == 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<H: std::hash::Hasher>(&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<T: ::std::any::Any>(&self) -> bool {
|
||||
self.$field.is::<T>()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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<T: Reflect + TypePath + ?Sized>() -> Self {
|
||||
Self {
|
||||
type_path: TypePathTable::of::<T>(),
|
||||
type_id: TypeId::of::<T>(),
|
||||
ty: Type::of::<T>(),
|
||||
#[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<T: Any>(&self) -> bool {
|
||||
TypeId::of::<T>() == self.type_id
|
||||
}
|
||||
impl_type_methods!(ty);
|
||||
|
||||
/// The docstring of this dynamic value, if any.
|
||||
#[cfg(feature = "documentation")]
|
||||
|
|
Loading…
Reference in a new issue