diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index 4d3c27caecb9b..086441a311270 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -41,7 +41,89 @@ use type_uuid::TypeUuidDef; pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect"; pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value"; -#[proc_macro_derive(Reflect, attributes(reflect, reflect_value, module))] +/// The main derive macro used by `bevy_reflect` for deriving its `Reflect` trait. +/// +/// This macro can be used on all structs and enums (unions are not supported). +/// It will automatically generate the implementations for `Reflect`, `Typed`, and `GetTypeRegistration`. +/// And, depending on the item's structure, will either implement `Struct`, `TupleStruct`, or `Enum`. +/// +/// # Container Attributes +/// +/// This macro comes with some helper attributes that can be added to the container item +/// in order to provide additional functionality or alter the generated implementations. +/// +/// ## `#[reflect(Ident)]` +/// +/// The `#[reflect(Ident)]` attribute is used to add type data registrations to the `GetTypeRegistration` +/// implementation corresponding to the given identifier, prepended by `Reflect`. +/// +/// For example, `#[reflect(Foo, Bar)]` would add two registrations: +/// one for `ReflectFoo` and another for `ReflectBar`. +/// This assumes these types are indeed in-scope wherever this macro is called. +/// +/// This is often used with traits that have been marked by the [`#[reflect_trait]`](macro@reflect_trait) +/// macro in order to register the type's implementation of that trait. +/// +/// ### Special Identifiers +/// +/// There are a few "special" identifiers that work a bit differently: +/// +/// * `#[reflect(Debug)]` will force the implementation of `Reflect::reflect_debug` to rely on +/// the type's [`Debug`] implementation. +/// A custom implementation may be provided using `#[reflect(Debug(my_debug_func))]` where +/// `my_debug_func` is the path to a function matching the signature: +/// `(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result`. +/// * `#[reflect(PartialEq)]` will force the implementation of `Reflect::reflect_partial_eq` to rely on +/// the type's [`PartialEq`] implementation. +/// A custom implementation may be provided using `#[reflect(PartialEq(my_partial_eq_func))]` where +/// `my_partial_eq_func` is the path to a function matching the signature: +/// `(&self, value: &dyn #bevy_reflect_path::Reflect) -> bool`. +/// * `#[reflect(Hash)]` will force the implementation of `Reflect::reflect_hash` to rely on +/// the type's [`Hash`] implementation. +/// A custom implementation may be provided using `#[reflect(Hash(my_hash_func))]` where +/// `my_hash_func` is the path to a function matching the signature: `(&self) -> u64`. +/// * `#[reflect(Default)]` will register the `ReflectDefault` type data as normal. +/// However, it will also affect how certain other operations are performed in order +/// to improve performance and/or robustness. +/// An example of where this is used is in the [`FromReflect`] derive macro, +/// where adding this attribute will cause the `FromReflect` implementation to create +/// a base value using its [`Default`] implementation avoiding issues with ignored fields. +/// +/// ## `#[reflect_value]` +/// +/// The `#[reflect_value]` attribute (which may also take the form `#[reflect_value(Ident)]`), +/// denotes that the item should implement `Reflect` as though it were a base value type. +/// This means that it will forgo implementing `Struct`, `TupleStruct`, or `Enum`. +/// +/// Furthermore, it requires that the type implements [`Clone`]. +/// If planning to serialize this type using the reflection serializers, +/// then the `Serialize` and `Deserialize` traits will need to be implemented and registered as well. +/// +/// # Field Attributes +/// +/// Along with the container attributes, this macro comes with some attributes that may be applied +/// to the contained fields themselves. +/// +/// ## `#[reflect(ignore)]` +/// +/// This attribute simply marks a field to be ignored by the reflection API. +/// +/// This allows fields to completely opt-out of reflection, +/// which may be useful for maintaining invariants, keeping certain data private, +/// or allowing the use of types that do not implement `Reflect` within the container. +/// +/// ## `#[reflect(skip_serializing)]` +/// +/// This works similar to `#[reflect(ignore)]`, but rather than opting out of _all_ of reflection, +/// it simply opts the field out of both serialization and deserialization. +/// This can be useful when a field should be accessible via reflection, but may not make +/// sense in a serialized form, such as computed data. +/// +/// What this does is register the `SerializationData` type within the `GetTypeRegistration` implementation, +/// which will be used by the reflection serializers to determine whether or not the field is serializable. +/// +/// [`reflect_trait`]: macro@reflect_trait +#[proc_macro_derive(Reflect, attributes(reflect, reflect_value))] pub fn derive_reflect(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); @@ -62,11 +144,30 @@ pub fn derive_reflect(input: TokenStream) -> TokenStream { /// Derives the `FromReflect` trait. /// -/// This macro supports the following field attributes: -/// * `#[reflect(ignore)]`: Ignores the field. This requires the field to implement [`Default`]. -/// * `#[reflect(default)]`: If the field's value cannot be read, uses its [`Default`] implementation. -/// * `#[reflect(default = "some_func")]`: If the field's value cannot be read, uses the function with the given name. +/// # Field Attributes +/// +/// ## `#[reflect(ignore)]` /// +/// The `#[reflect(ignore)]` attribute is shared with the [`#[derive(Reflect)]`](Reflect) macro and has much of the same +/// functionality in that it denotes that a field will be ignored by the reflection API. +/// +/// The only major difference is that using it with this derive requires that the field implements [`Default`]. +/// Without this requirement, there would be no way for `FromReflect` to automatically construct missing fields +/// that have been ignored. +/// +/// ## `#[reflect(default)]` +/// +/// If a field cannot be read, this attribute specifies a default value to be used in its place. +/// +/// By default, this attribute denotes that the field's type implements [`Default`]. +/// However, it can also take in a path string to a user-defined function that will return the default value. +/// This takes the form: `#[reflect(default = "path::to::my_function)]` where `my_function` is a parameterless +/// function that must return some default value for the type. +/// +/// Specifying a custom default can be used to give different fields their own specialized defaults, +/// or to remove the `Default` requirement on fields marked with `#[reflect(ignore)]`. +/// Additionally, either form of this attribute can be used to fill in fields that are simply missing, +/// such as when converting a partially-constructed dynamic type to a concrete one. #[proc_macro_derive(FromReflect, attributes(reflect))] pub fn derive_from_reflect(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); @@ -92,11 +193,82 @@ pub fn derive_type_uuid(input: TokenStream) -> TokenStream { type_uuid::type_uuid_derive(input) } +/// A macro that automatically generates type data for traits, which their implementors can then register. +/// +/// The output of this macro is a struct that takes reflected instances of the implementor's type +/// and returns the value as a trait object. +/// Because of this, **it can only be used on [object-safe] traits.** +/// +/// For a trait named `MyTrait`, this will generate the struct `ReflectMyTrait`. +/// The generated struct can be created using `FromType` with any type that implements the trait. +/// The creation and registration of this generated struct as type data can be automatically handled +/// by [`#[derive(Reflect)]`](Reflect). +/// +/// # Example +/// +/// ```ignore +/// # use std::any::TypeId; +/// # use bevy_reflect_derive::{Reflect, reflect_trait}; +/// #[reflect_trait] // Generates `ReflectMyTrait` +/// trait MyTrait { +/// fn print(&self) -> &str; +/// } +/// +/// #[derive(Reflect)] +/// #[reflect(MyTrait)] // Automatically registers `ReflectMyTrait` +/// struct SomeStruct; +/// +/// impl MyTrait for SomeStruct { +/// fn print(&self) -> &str { +/// "Hello, World!" +/// } +/// } +/// +/// // We can create the type data manually if we wanted: +/// let my_trait: ReflectMyTrait = FromType::::from_type(); +/// +/// // Or we can simply get it from the registry: +/// let mut registry = TypeRegistry::default(); +/// registry.register::(); +/// let my_trait = registry +/// .get_type_data::(TypeId::of::()) +/// .unwrap(); +/// +/// // Then use it on reflected data +/// let reflected: Box = Box::new(SomeStruct); +/// let reflected_my_trait: &dyn MyTrait = my_trait.get(&*reflected).unwrap(); +/// assert_eq!("Hello, World!", reflected_my_trait.print()); +/// ``` +/// +/// [object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety #[proc_macro_attribute] pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream { trait_reflection::reflect_trait(&args, input) } +/// A macro used to generate reflection trait implementations for the given type. +/// +/// This is functionally the same as [deriving `Reflect`] using the `#[reflect_value]` container attribute. +/// +/// The only reason for this macro's existence is so that `bevy_reflect` can easily implement the reflection traits +/// on primitives and other Rust types internally. +/// +/// # Examples +/// +/// Types can be passed with or without registering type data: +/// +/// ```ignore +/// impl_reflect_value!(foo); +/// impl_reflect_value!(bar(Debug, Default, Serialize, Deserialize)); +/// ``` +/// +/// Generic types can also specify their parameters and bounds: +/// +/// ```ignore +/// impl_reflect_value!(foo where T1: Bar (Default, Serialize, Deserialize)); +/// ``` +/// +/// [deriving `Reflect`]: Reflect #[proc_macro] pub fn impl_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); @@ -178,6 +350,22 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream { } } +/// A macro used to generate a `FromReflect` trait implementation for the given type. +/// +/// This is functionally the same as [deriving `FromReflect`] on a type that [derives `Reflect`] using +/// the `#[reflect_value]` container attribute. +/// +/// The only reason this macro exists is so that `bevy_reflect` can easily implement `FromReflect` on +/// primitives and other Rust types internally. +/// +/// # Examples +/// +/// ```ignore +/// impl_from_reflect_value!(foo where T1: Bar); +/// ``` +/// +/// [deriving `FromReflect`]: FromReflect +/// [derives `Reflect`]: Reflect #[proc_macro] pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index a7a6088fda177..947601a1548e5 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -8,16 +8,41 @@ use std::{ hash::{Hash, Hasher}, }; -/// A static-sized array of [`Reflect`] items. +/// A trait used to power [array-like] operations via [reflection]. /// -/// This corresponds to types like `[T; N]` (arrays). +/// This corresponds to true Rust arrays like `[T; N]`, +/// but also to any fixed-size linear sequence types. +/// It is expected that implementors of this trait uphold this contract +/// and maintain a fixed size as returned by the [`Array::len`] method. /// -/// Currently, this only supports arrays of up to 32 items. It can technically -/// contain more than 32, but the blanket [`GetTypeRegistration`] is only -/// implemented up to the 32 item limit due to a [limitation] on `Deserialize`. +/// Due to the [type-erasing] nature of the reflection API as a whole, +/// this trait does not make any guarantees that the implementor's elements +/// are homogenous (i.e. all the same type). /// +/// This trait has a blanket implementation over Rust arrays of up to 32 items. +/// This implementation can technically contain more than 32, +/// but the blanket [`GetTypeRegistration`] is only implemented up to the 32 +/// item limit due to a [limitation] on [`Deserialize`]. +/// +/// # Example +/// +/// ``` +/// use bevy_reflect::{Reflect, Array}; +/// +/// let foo: &dyn Array = &[123_u32, 456_u32, 789_u32]; +/// assert_eq!(foo.len(), 3); +/// +/// let field: &dyn Reflect = foo.get(0).unwrap(); +/// assert_eq!(field.downcast_ref::(), Some(&123)); +/// ``` +/// +/// [array-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-array-type +/// [reflection]: crate +/// [`List`]: crate::List +/// [type-erasing]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html /// [`GetTypeRegistration`]: crate::GetTypeRegistration /// [limitation]: https://github.com/serde-rs/serde/issues/1937 +/// [`Deserialize`]: ::serde::Deserialize pub trait Array: Reflect { /// Returns a reference to the element at `index`, or `None` if out of bounds. fn get(&self, index: usize) -> Option<&dyn Reflect>; diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index 5d5a04c91d53a..a4b9bec2a4512 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -3,7 +3,7 @@ use bevy_utils::HashMap; use std::any::{Any, TypeId}; use std::slice::Iter; -/// A trait representing a [reflected] enum. +/// A trait used to power [enum-like] operations via [reflection]. /// /// This allows enums to be processed and modified dynamically at runtime without /// necessarily knowing the actual type. @@ -39,7 +39,7 @@ use std::slice::Iter; /// /// # Implementation /// -/// > đź’ˇ This trait can be automatically implemented using the [`Reflect`] derive macro +/// > đź’ˇ This trait can be automatically implemented using [`#[derive(Reflect)]`](derive@crate::Reflect) /// > on an enum definition. /// /// Despite the fact that enums can represent multiple states, traits only exist in one state @@ -52,7 +52,7 @@ use std::slice::Iter; /// accessing fields! /// Again, this is to account for _all three_ variant types. /// -/// We recommend using the built-in [`Reflect`] derive macro to automatically handle all the +/// We recommend using the built-in [`#[derive(Reflect)]`](derive@crate::Reflect) macro to automatically handle all the /// implementation details for you. /// However, if you _must_ implement this trait manually, there are a few things to keep in mind... /// @@ -82,7 +82,8 @@ use std::slice::Iter; /// It's preferred that these strings be converted to their proper `usize` representations and /// the [`Enum::field_at[_mut]`](Enum::field_at) methods be used instead. /// -/// [reflected]: crate +/// [enum-like]: https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html +/// [reflection]: crate /// [`None`]: core::option::Option::None /// [`Some`]: core::option::Option::Some /// [`Reflect`]: bevy_reflect_derive::Reflect diff --git a/crates/bevy_reflect/src/from_reflect.rs b/crates/bevy_reflect/src/from_reflect.rs index 41c4c3582bd3a..4d98698398bf0 100644 --- a/crates/bevy_reflect/src/from_reflect.rs +++ b/crates/bevy_reflect/src/from_reflect.rs @@ -1,15 +1,26 @@ use crate::{FromType, Reflect}; -/// A trait for types which can be constructed from a reflected type. +/// A trait that enables types to be dynamically constructed from reflected data. /// -/// This trait can be derived on types which implement [`Reflect`]. Some complex -/// types (such as `Vec`) may only be reflected if their element types +/// It's recommended to use the [derive macro] rather than manually implementing this trait. +/// +/// `FromReflect` allows dynamic proxy types, like [`DynamicStruct`], to be used to generate +/// their concrete counterparts. +/// It can also be used to partially or fully clone a type (depending on whether it has +/// ignored fields or not). +/// +/// In some cases, this trait may even be required. +/// Deriving [`Reflect`] on an enum requires all its fields to implement `FromReflect`. +/// Additionally, some complex types like `Vec` require that their element types /// implement this trait. +/// The reason for such requirements is that some operations require new data to be constructed, +/// such as swapping to a new variant or pushing data to a homogenous list. /// -/// For structs and tuple structs, fields marked with the `#[reflect(ignore)]` -/// attribute will be constructed using the `Default` implementation of the -/// field type, rather than the corresponding field value (if any) of the -/// reflected value. +/// See the [crate-level documentation] to see how this trait can be used. +/// +/// [derive macro]: bevy_reflect_derive::FromReflect +/// [`DynamicStruct`]: crate::DynamicStruct +/// [crate-level documentation]: crate pub trait FromReflect: Reflect + Sized { /// Constructs a concrete instance of `Self` from a reflected value. fn from_reflect(reflect: &dyn Reflect) -> Option; diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index c56debd98302d..c7d87436707fc 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1,4 +1,440 @@ -#![doc = include_str!("../README.md")] +//! Reflection in Rust. +//! +//! [Reflection] is a powerful tool provided within many programming languages +//! that allows for meta-programming: using information _about_ the program to +//! _affect_ the program. +//! In other words, reflection allows us to inspect the program itself, its +//! syntax, and its type information at runtime. +//! +//! This crate adds this missing reflection functionality to Rust. +//! Though it was made with the [Bevy] game engine in mind, +//! it's a general-purpose solution that can be used in any Rust project. +//! +//! At a very high level, this crate allows you to: +//! * Dynamically interact with Rust values +//! * Access type metadata at runtime +//! * Serialize and deserialize (i.e. save and load) data +//! +//! It's important to note that because of missing features in Rust, +//! there are some [limitations] with this crate. +//! +//! # The `Reflect` Trait +//! +//! At the core of [`bevy_reflect`] is the [`Reflect`] trait. +//! +//! One of its primary purposes is to allow all implementors to be passed around +//! as a `dyn Reflect` trait object. +//! This allows any such type to be operated upon completely dynamically (at a small [runtime cost]). +//! +//! Implementing the trait is easily done using the provided [derive macro]: +//! +//! ``` +//! # use bevy_reflect::Reflect; +//! #[derive(Reflect)] +//! struct MyStruct { +//! foo: i32 +//! } +//! ``` +//! +//! This will automatically generate the implementation of `Reflect` for any struct or enum. +//! +//! It will also generate other very important trait implementations used for reflection: +//! * [`GetTypeRegistration`] +//! * [`Typed`] +//! * [`Struct`], [`TupleStruct`], or [`Enum`] depending on the type +//! +//! ## Requirements +//! +//! We can implement `Reflect` on any type that satisfies _both_ of the following conditions: +//! * The type implements `Any`. +//! This is true if and only if the type itself has a [`'static` lifetime]. +//! * All fields and sub-elements themselves implement `Reflect` +//! (see the [derive macro documentation] for details on how to ignore certain fields when deriving). +//! +//! Additionally, using the derive macro on enums requires a third condition to be met: +//! * All fields and sub-elements must implement [`FromReflect`]— +//! another important reflection trait discussed in a later section. +//! +//! # The `Reflect` Subtraits +//! +//! Since [`Reflect`] is meant to cover any and every type, this crate also comes with a few +//! more traits to accompany `Reflect` and provide more specific interactions. +//! We refer to these traits as the _reflection subtraits_ since they all have `Reflect` as a supertrait. +//! The current list of reflection subtraits include: +//! * [`Tuple`] +//! * [`Array`] +//! * [`List`] +//! * [`Map`] +//! * [`Struct`] +//! * [`TupleStruct`] +//! * [`Enum`] +//! +//! As mentioned previously, the last three are automatically implemented by the [derive macro]. +//! +//! Each of these traits come with their own methods specific to their respective category. +//! For example, we can access our struct's fields by name using the [`Struct::field`] method. +//! +//! ``` +//! # use bevy_reflect::{Reflect, Struct}; +//! # #[derive(Reflect)] +//! # struct MyStruct { +//! # foo: i32 +//! # } +//! let my_struct: Box = Box::new(MyStruct { +//! foo: 123 +//! }); +//! let foo: &dyn Reflect = my_struct.field("foo").unwrap(); +//! assert_eq!(Some(&123), foo.downcast_ref::()); +//! ``` +//! +//! Since most data is passed around as `dyn Reflect`, +//! the `Reflect` trait has methods for going to and from these subtraits. +//! +//! [`Reflect::reflect_ref`], [`Reflect::reflect_mut`], and [`Reflect::reflect_owned`] all return +//! an enum that respectively contains immutable, mutable, and owned access to the type as a subtrait object. +//! +//! For example, we can get out a `dyn Tuple` from our reflected tuple type using one of these methods. +//! +//! ``` +//! # use bevy_reflect::{Reflect, ReflectRef}; +//! let my_tuple: Box = Box::new((1, 2, 3)); +//! let ReflectRef::Tuple(my_tuple) = my_tuple.reflect_ref() else { unreachable!() }; +//! assert_eq!(3, my_tuple.field_len()); +//! ``` +//! +//! And to go back to a general-purpose `dyn Reflect`, +//! we can just use the matching [`Reflect::as_reflect`], [`Reflect::as_reflect_mut`], +//! or [`Reflect::into_reflect`] methods. +//! +//! ## Value Types +//! +//! Types that do not fall under one of the above subtraits, +//! such as for primitives (e.g. `bool`, `usize`, etc.) +//! and simple types (e.g. `String`, `Duration`), +//! are referred to as _value_ types +//! since methods like [`Reflect::reflect_ref`] return a [`ReflectRef::Value`] variant. +//! While most other types contain their own `dyn Reflect` fields and data, +//! these types generally cannot be broken down any further. +//! +//! # Dynamic Types +//! +//! Each subtrait comes with a corresponding _dynamic_ type. +//! +//! The available dynamic types are: +//! * [`DynamicTuple`] +//! * [`DynamicArray`] +//! * [`DynamicList`] +//! * [`DynamicMap`] +//! * [`DynamicStruct`] +//! * [`DynamicTupleStruct`] +//! * [`DynamicEnum`] +//! +//! These dynamic types may contain any arbitrary reflected data. +//! +//! ``` +//! # use bevy_reflect::{DynamicStruct, Struct}; +//! let mut data = DynamicStruct::default(); +//! data.insert("foo", 123_i32); +//! assert_eq!(Some(&123), data.field("foo").unwrap().downcast_ref::()) +//! ``` +//! +//! They are most commonly used as "proxies" for other types, +//! where they contain the same data as— and therefore, represent— a concrete type. +//! The [`Reflect::clone_value`] method will return a dynamic type for all non-value types, +//! allowing all types to essentially be "cloned". +//! And since dynamic types themselves implement [`Reflect`], +//! we may pass them around just like any other reflected type. +//! +//! ``` +//! # use bevy_reflect::{DynamicStruct, Reflect}; +//! # #[derive(Reflect)] +//! # struct MyStruct { +//! # foo: i32 +//! # } +//! let original: Box = Box::new(MyStruct { +//! foo: 123 +//! }); +//! +//! // `cloned` will be a `DynamicStruct` representing a `MyStruct` +//! let cloned: Box = original.clone_value(); +//! assert!(cloned.represents::()); +//! assert!(cloned.is::()); +//! ``` +//! +//! ## Patching +//! +//! These dynamic types come in handy when needing to apply multiple changes to another type. +//! This is known as "patching" and is done using the [`Reflect::apply`] method. +//! +//! ``` +//! # use bevy_reflect::{DynamicEnum, Reflect}; +//! let mut value = Some(123_i32); +//! let patch = DynamicEnum::new(std::any::type_name::>(), "None", ()); +//! value.apply(&patch); +//! assert_eq!(None, value); +//! ``` +//! +//! ## `FromReflect` +//! +//! It's important to remember that dynamic types are _not_ the concrete type they may be representing. +//! A common mistake is to treat them like such when trying to cast back to the original type +//! or when trying to make use of a reflected trait which expects the actual type. +//! +//! ```should_panic +//! # use bevy_reflect::{DynamicStruct, Reflect}; +//! # #[derive(Reflect)] +//! # struct MyStruct { +//! # foo: i32 +//! # } +//! let original: Box = Box::new(MyStruct { +//! foo: 123 +//! }); +//! +//! let cloned: Box = original.clone_value(); +//! let value = cloned.take::().unwrap(); // PANIC! +//! ``` +//! +//! To resolve this issue, we'll need to convert the dynamic type to the concrete one. +//! This is where [`FromReflect`] comes in. +//! +//! `FromReflect` is a derivable trait that allows an instance of a type to be generated from a +//! dynamic representation— even partial ones. +//! And since the [`FromReflect::from_reflect`] method takes the data by reference, +//! this can be used to effectively clone data (to an extent). +//! +//! This trait can be derived on any type whose fields and sub-elements also implement `FromReflect`. +//! +//! ``` +//! # use bevy_reflect::{Reflect, FromReflect}; +//! #[derive(Reflect, FromReflect)] +//! struct MyStruct { +//! foo: i32 +//! } +//! let original: Box = Box::new(MyStruct { +//! foo: 123 +//! }); +//! +//! let cloned: Box = original.clone_value(); +//! let value = ::from_reflect(&*cloned).unwrap(); // OK! +//! ``` +//! +//! With the derive macro, fields can be ignored or given default values for when a field is missing +//! in the passed value. +//! See the [derive macro documentation](derive@crate::FromReflect) for details. +//! +//! All primitives and simple types implement `FromReflect` by relying on their [`Default`] implementation. +//! +//! # Type Registration +//! +//! This crate also comes with a [`TypeRegistry`] that can be used to store and retrieve additional type metadata at runtime, +//! such as helper types and trait implementations. +//! +//! The [derive macro] for [`Reflect`] also generates an implementation of the [`GetTypeRegistration`] trait, +//! which is used by the registry to generate a [`TypeRegistration`] struct for that type. +//! We can then register additional [type data] we want associated with that type. +//! +//! For example, we can register [`ReflectDefault`] on our type so that its `Default` implementation +//! may be used dynamically. +//! +//! ``` +//! # use bevy_reflect::{Reflect, TypeRegistry, prelude::ReflectDefault}; +//! #[derive(Reflect, Default)] +//! struct MyStruct { +//! foo: i32 +//! } +//! let mut registry = TypeRegistry::empty(); +//! registry.register::(); +//! registry.register_type_data::(); +//! +//! let registration = registry.get(std::any::TypeId::of::()).unwrap(); +//! let reflect_default = registration.data::().unwrap(); +//! +//! let new_value: Box = reflect_default.default(); +//! assert!(new_value.is::()); +//! ``` +//! +//! Because this operation is so common, the derive macro actually has a shorthand for it. +//! By using the `#[reflect(Trait)]` attribute, the derive macro will automatically register a matching, +//! in-scope `ReflectTrait` type within the `GetTypeRegistration` implementation. +//! +//! ``` +//! use bevy_reflect::prelude::{Reflect, ReflectDefault}; +//! +//! #[derive(Reflect, Default)] +//! #[reflect(Default)] +//! struct MyStruct { +//! foo: i32 +//! } +//! ``` +//! +//! ## Reflecting Traits +//! +//! Type data doesn't have to be tied to a trait, but it's often extremely useful to create trait type data. +//! These allow traits to be used directly on a `dyn Reflect` while utilizing the underlying type's implementation. +//! +//! For any [object-safe] trait, we can easily generate a corresponding `ReflectTrait` type for our trait +//! using the [`#[reflect_trait]`](reflect_trait) macro. +//! +//! ``` +//! # use bevy_reflect::{Reflect, reflect_trait, TypeRegistry}; +//! #[reflect_trait] // Generates a `ReflectMyTrait` type +//! pub trait MyTrait {} +//! impl MyTrait for T {} +//! +//! let mut registry = TypeRegistry::new(); +//! registry.register_type_data::(); +//! ``` +//! +//! The generated type data can be used to convert a valid `dyn Reflect` into a `dyn MyTrait`. +//! See the [trait reflection example](https://github.com/bevyengine/bevy/blob/latest/examples/reflection/trait_reflection.rs) +//! for more information and usage details. +//! +//! # Serialization +//! +//! By using reflection, we are also able to get serialization capabilities for free. +//! In fact, using [`bevy_reflect`] can result in faster compile times and reduced code generation over +//! directly deriving the [`serde`] traits. +//! +//! The way it works is by moving the serialization logic into common serializers and deserializers: +//! * [`ReflectSerializer`] +//! * [`TypedReflectSerializer`] +//! * [`UntypedReflectDeserializer`] +//! * [`TypedReflectDeserializer`] +//! +//! All of these structs require a reference to the [registry] so that [type information] can be retrieved, +//! as well as registered type data, such as [`ReflectSerialize`] and [`ReflectDeserialize`]. +//! +//! The general entry point are the "untyped" versions of these structs. +//! These will automatically extract the type information and pass them into their respective "typed" version. +//! +//! The output of the `ReflectSerializer` will be a map, where the key is the [type name] +//! and the value is the serialized data. +//! The `TypedReflectSerializer` will simply output the serialized data. +//! +//! The `UntypedReflectDeserializer` can be used to deserialize this map and return a `Box`, +//! where the underlying type will be a dynamic type representing some concrete type (except for value types). +//! +//! Again, it's important to remember that dynamic types may need to be converted to their concrete counterparts +//! in order to be used in certain cases. +//! This can be achieved using [`FromReflect`]. +//! +//! ``` +//! # use serde::de::DeserializeSeed; +//! # use bevy_reflect::{ +//! # serde::{ReflectSerializer, UntypedReflectDeserializer}, +//! # Reflect, FromReflect, TypeRegistry +//! # }; +//! #[derive(Reflect, FromReflect, PartialEq, Debug)] +//! struct MyStruct { +//! foo: i32 +//! } +//! +//! let original_value = MyStruct { +//! foo: 123 +//! }; +//! +//! // Register +//! let mut registry = TypeRegistry::new(); +//! registry.register::(); +//! +//! // Serialize +//! let reflect_serializer = ReflectSerializer::new(&original_value, ®istry); +//! let serialized_value: String = ron::to_string(&reflect_serializer).unwrap(); +//! +//! // Deserialize +//! let reflect_deserializer = UntypedReflectDeserializer::new(®istry); +//! let deserialized_value: Box = reflect_deserializer.deserialize( +//! &mut ron::Deserializer::from_str(&serialized_value).unwrap() +//! ).unwrap(); +//! +//! // Convert +//! let converted_value = ::from_reflect(&*deserialized_value).unwrap(); +//! +//! assert_eq!(original_value, converted_value); +//! ``` +//! +//! # Limitations +//! +//! While this crate offers a lot in terms of adding reflection to Rust, +//! it does come with some limitations that don't make it as featureful as reflection +//! in other programming languages. +//! +//! ## Non-Static Lifetimes +//! +//! One of the most obvious limitations is the `'static` requirement. +//! Rust requires fields to define a lifetime for referenced data, +//! but [`Reflect`] requires all types to have a `'static` lifetime. +//! This makes it impossible to reflect any type with non-static borrowed data. +//! +//! ## Function Reflection +//! +//! Another limitation is the inability to fully reflect functions and methods. +//! Most languages offer some way of calling methods dynamically, +//! but Rust makes this very difficult to do. +//! For non-generic methods, this can be done by registering custom [type data] that +//! contains function pointers. +//! For generic methods, the same can be done but will typically require manual monomorphization +//! (i.e. manually specifying the types the generic method can take). +//! +//! ## Manual Registration +//! +//! Since Rust doesn't provide built-in support for running initialization code before `main`, +//! there is no way for `bevy_reflect` to automatically register types into the [type registry]. +//! This means types must manually be registered, including their desired monomorphized +//! representations if generic. +//! +//! # Features +//! +//! ## `bevy` +//! +//! | Default | Dependencies | +//! | :-----: | :---------------------------------------: | +//! | ❌ | [`bevy_math`], [`glam`], [`smallvec`] | +//! +//! This feature makes it so that the appropriate reflection traits are implemented on all the types +//! necessary for the [Bevy] game engine. +//! enables the optional dependencies: [`bevy_math`], [`glam`], and [`smallvec`]. +//! These dependencies are used by the [Bevy] game engine and must define their reflection implementations +//! within this crate due to Rust's [orphan rule]. +//! +//! ## `documentation` +//! +//! | Default | Dependencies | +//! | :-----: | :-------------------------------------------: | +//! | ❌ | [`bevy_reflect_derive/documentation`] | +//! +//! This feature enables capturing doc comments as strings for items that [derive `Reflect`]. +//! Documentation information can then be accessed at runtime on the [`TypeInfo`] of that item. +//! +//! This can be useful for generating documentation for scripting language interop or +//! for displaying tooltips in an editor. +//! +//! [Reflection]: https://en.wikipedia.org/wiki/Reflective_programming +//! [Bevy]: https://bevyengine.org/ +//! [limitations]: #limitations +//! [`bevy_reflect`]: crate +//! [runtime cost]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch +//! [derive macro]: derive@crate::Reflect +//! [`'static` lifetime]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound +//! [derive macro documentation]: derive@crate::Reflect +//! [type data]: TypeData +//! [`ReflectDefault`]: std_traits::ReflectDefault +//! [object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety +//! [`serde`]: ::serde +//! [`ReflectSerializer`]: serde::ReflectSerializer +//! [`TypedReflectSerializer`]: serde::TypedReflectSerializer +//! [`UntypedReflectDeserializer`]: serde::UntypedReflectDeserializer +//! [`TypedReflectDeserializer`]: serde::TypedReflectDeserializer +//! [registry]: TypeRegistry +//! [type information]: TypeInfo +//! [type name]: Reflect::type_name +//! [type registry]: TypeRegistry +//! [`bevy_math`]: https://docs.rs/bevy_math/latest/bevy_math/ +//! [`glam`]: https://docs.rs/glam/latest/glam/ +//! [`smallvec`]: https://docs.rs/smallvec/latest/smallvec/ +//! [orphan rule]: https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type:~:text=But%20we%20can%E2%80%99t,implementation%20to%20use. +//! [`bevy_reflect_derive/documentation`]: bevy_reflect_derive +//! [derive `Reflect`]: derive@crate::Reflect mod array; mod fields; diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 5cbc21cb329b4..d13e7776f0693 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -7,19 +7,44 @@ use crate::{ DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, }; -/// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`]. +/// A trait used to power [list-like] operations via [reflection]. /// -/// Unlike the [`Array`](crate::Array) trait, implementors of this type are not expected to +/// This corresponds to types, like [`Vec`], which contain an ordered sequence +/// of elements that implement [`Reflect`]. +/// +/// Unlike the [`Array`](crate::Array) trait, implementors of this trait are not expected to /// maintain a constant length. /// Methods like [insertion](List::insert) and [removal](List::remove) explicitly allow for their /// internal size to change. /// -/// This trait expects index 0 to contain the _front_ element. -/// The _back_ element must refer to the element with the largest index. -/// These two rules above should be upheld by manual implementors. -/// /// [`push`](List::push) and [`pop`](List::pop) have default implementations, -/// however it may be faster to implement them manually. +/// however it will generally be more performant to implement them manually +/// as the default implementation uses a very naive approach to find the correct position. +/// +/// This trait expects its elements to be ordered linearly from front to back. +/// The _front_ element starts at index 0 with the _back_ element ending at the largest index. +/// This contract above should be upheld by any manual implementors. +/// +/// Due to the [type-erasing] nature of the reflection API as a whole, +/// this trait does not make any guarantees that the implementor's elements +/// are homogenous (i.e. all the same type). +/// +/// # Example +/// +/// ``` +/// use bevy_reflect::{Reflect, List}; +/// +/// let foo: &mut dyn List = &mut vec![123_u32, 456_u32, 789_u32]; +/// assert_eq!(foo.len(), 3); +/// +/// let last_field: Box = foo.pop().unwrap(); +/// assert_eq!(last_field.downcast_ref::(), Some(&789)); +/// ``` +/// +/// [list-like]: https://doc.rust-lang.org/book/ch08-01-vectors.html +/// [reflection]: crate +/// [`Vec`]: std::vec::Vec +/// [type-erasing]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html pub trait List: Reflect { /// Returns a reference to the element at `index`, or `None` if out of bounds. fn get(&self, index: usize) -> Option<&dyn Reflect>; diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index f5e4a8695f2a2..8dcd28386a2e5 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -7,16 +7,38 @@ use bevy_utils::{Entry, HashMap}; use crate::utility::NonGenericTypeInfoCell; use crate::{DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed}; -/// An ordered mapping between [`Reflect`] values. +/// A trait used to power [map-like] operations via [reflection]. /// -/// Because the values are reflected, the underlying types of keys and values -/// may differ between entries. +/// Maps contain zero or more entries of a key and its associated value, +/// and correspond to types like [`HashMap`]. +/// The order of these entries is not guaranteed by this trait. /// -///`ReflectValue` `Keys` are assumed to return a non-`None` hash. The ordering -/// of `Map` entries is not guaranteed to be stable across runs or between -/// instances. +/// # Hashing /// -/// This trait corresponds to types like [`std::collections::HashMap`]. +/// All keys are expected to return a valid hash value from [`Reflect::reflect_hash`]. +/// If using the [`#[derive(Reflect)]`](derive@crate::Reflect) macro, this can be done by adding `#[reflect(Hash)]` +/// to the entire struct or enum. +/// This is true even for manual implementors who do not use the hashed value, +/// as it is still relied on by [`DynamicMap`]. +/// +/// # Example +/// +/// ``` +/// use bevy_reflect::{Reflect, Map}; +/// use bevy_utils::HashMap; +/// +/// +/// let foo: &mut dyn Map = &mut HashMap::::new(); +/// foo.insert_boxed(Box::new(123_u32), Box::new(true)); +/// assert_eq!(foo.len(), 1); +/// +/// let field: &dyn Reflect = foo.get(&123_u32).unwrap(); +/// assert_eq!(field.downcast_ref::(), Some(&true)); +/// ``` +/// +/// [map-like]: https://doc.rust-lang.org/book/ch08-03-hash-maps.html +/// [reflection]: crate +/// [`HashMap`]: bevy_utils::HashMap pub trait Map: Reflect { /// Returns a reference to the value associated with the given key. /// diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 90c57f7d5bbd6..8abfeef742fbd 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -61,13 +61,17 @@ pub enum ReflectOwned { Value(Box), } -/// A reflected Rust type. +/// The core trait of [`bevy_reflect`], used for accessing and modifying data dynamically. /// -/// Methods for working with particular kinds of Rust type are available using the [`Array`], [`List`], -/// [`Map`], [`Tuple`], [`TupleStruct`], [`Struct`], and [`Enum`] subtraits. +/// It's recommended to use the [derive macro] rather than manually implementing this trait. +/// Doing so will automatically implement many other useful traits for reflection, +/// including one of the appropriate subtraits: [`Struct`], [`TupleStruct`] or [`Enum`]. /// -/// When using `#[derive(Reflect)]` on a struct, tuple struct or enum, the suitable subtrait for that -/// type (`Struct`, `TupleStruct` or `Enum`) is derived automatically. +/// See the [crate-level documentation] to see how this trait and its subtraits can be used. +/// +/// [`bevy_reflect`]: crate +/// [derive macro]: bevy_reflect_derive::Reflect +/// [crate-level documentation]: crate pub trait Reflect: Any + Send + Sync { /// Returns the [type name][std::any::type_name] of the underlying type. fn type_name(&self) -> &str; diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 4b8485cbb5b3e..ab146d1b36a43 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -10,13 +10,14 @@ use std::{ slice::Iter, }; -/// A reflected Rust regular struct type. +/// A trait used to power [struct-like] operations via [reflection]. /// -/// Implementors of this trait allow their fields to be addressed by name as -/// well as by index. +/// This trait uses the [`Reflect`] trait to allow implementors to have their fields +/// be dynamically addressed by both name and index. /// -/// This trait is automatically implemented for `struct` types with named fields -/// when using `#[derive(Reflect)]`. +/// When using [`#[derive(Reflect)]`](derive@crate::Reflect) on a standard struct, +/// this trait will be automatically implemented. +/// This goes for [unit structs] as well. /// /// # Example /// @@ -25,19 +26,22 @@ use std::{ /// /// #[derive(Reflect)] /// struct Foo { -/// bar: String, +/// bar: u32, /// } /// -/// # fn main() { -/// let foo = Foo { bar: "Hello, world!".to_string() }; +/// let foo = Foo { bar: 123 }; /// /// assert_eq!(foo.field_len(), 1); /// assert_eq!(foo.name_at(0), Some("bar")); /// -/// let bar = foo.field("bar").unwrap(); -/// assert_eq!(bar.downcast_ref::(), Some(&"Hello, world!".to_string())); -/// # } +/// let field: &dyn Reflect = foo.field("bar").unwrap(); +/// assert_eq!(field.downcast_ref::(), Some(&123)); /// ``` +/// +/// [struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html +/// [reflection]: crate + +/// [unit structs]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields pub trait Struct: Reflect { /// Returns a reference to the value of the field named `name` as a `&dyn /// Reflect`. @@ -68,7 +72,7 @@ pub trait Struct: Reflect { fn clone_dynamic(&self) -> DynamicStruct; } -/// A container for compile-time struct info. +/// A container for compile-time named struct info. #[derive(Clone, Debug)] pub struct StructInfo { name: &'static str, diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index cebabaf3ffc9d..f0e20aff6ba25 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -7,7 +7,10 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::slice::Iter; -/// A reflected Rust tuple. +/// A trait used to power [tuple-like] operations via [reflection]. +/// +/// This trait uses the [`Reflect`] trait to allow implementors to have their fields +/// be dynamically addressed by index. /// /// This trait is automatically implemented for arbitrary tuples of up to 12 /// elements, provided that each element implements [`Reflect`]. @@ -15,16 +18,17 @@ use std::slice::Iter; /// # Example /// /// ``` -/// use bevy_reflect::Tuple; +/// use bevy_reflect::{Reflect, Tuple}; /// -/// # fn main() { -/// let foo = ("blue".to_string(), 42_i32); +/// let foo = (123_u32, true); /// assert_eq!(foo.field_len(), 2); /// -/// let first = foo.field(0).unwrap(); -/// assert_eq!(first.downcast_ref::(), Some(&"blue".to_string())); -/// # } +/// let field: &dyn Reflect = foo.field(0).unwrap(); +/// assert_eq!(field.downcast_ref::(), Some(&123)); /// ``` +/// +/// [tuple-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type +/// [reflection]: crate pub trait Tuple: Reflect { /// Returns a reference to the value of the field with index `index` as a /// `&dyn Reflect`. diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index e8c52bdadddbd..33edd7bb172e3 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -6,29 +6,32 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::slice::Iter; -/// A reflected Rust tuple struct. +/// A trait used to power [tuple struct-like] operations via [reflection]. /// -/// Implementors of this trait allow their tuple fields to be addressed by -/// index. +/// This trait uses the [`Reflect`] trait to allow implementors to have their fields +/// be dynamically addressed by index. /// -/// This trait is automatically implemented for tuple struct types when using -/// `#[derive(Reflect)]`. +/// When using [`#[derive(Reflect)]`](derive@crate::Reflect) on a tuple struct, +/// this trait will be automatically implemented. +/// +/// # Example /// /// ``` /// use bevy_reflect::{Reflect, TupleStruct}; /// /// #[derive(Reflect)] -/// struct Foo(String); +/// struct Foo(u32); /// -/// # fn main() { -/// let foo = Foo("Hello, world!".to_string()); +/// let foo = Foo(123); /// /// assert_eq!(foo.field_len(), 1); /// -/// let first = foo.field(0).unwrap(); -/// assert_eq!(first.downcast_ref::(), Some(&"Hello, world!".to_string())); -/// # } +/// let field: &dyn Reflect = foo.field(0).unwrap(); +/// assert_eq!(field.downcast_ref::(), Some(&123)); /// ``` +/// +/// [tuple struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types +/// [reflection]: crate pub trait TupleStruct: Reflect { /// Returns a reference to the value of the field with index `index` as a /// `&dyn Reflect`. diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 42e011c14915f..27df34ea767e3 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -5,7 +5,7 @@ use std::any::{Any, TypeId}; /// A static accessor to compile-time type information. /// -/// This trait is automatically implemented by the `#[derive(Reflect)]` macro +/// This trait is automatically implemented by the [`#[derive(Reflect)]`](derive@crate::Reflect) macro /// and allows type information to be processed without an instance of that type. /// /// # Implementing diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index 2a6fc6f8168be..c19ce9bd831af 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -6,7 +6,18 @@ use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use serde::Deserialize; use std::{any::TypeId, fmt::Debug, sync::Arc}; -/// A registry of reflected types. +/// A registry of [reflected] types. +/// +/// This struct is used as the central store for type information. +/// [Registering] a type will generate a new [`TypeRegistration`] entry in this store +/// using a type's [`GetTypeRegistration`] implementation +/// (which is automatically implemented when using [`#[derive(Reflect)]`](derive@crate::Reflect)). +/// +/// See the [crate-level documentation] for more information. +/// +/// [reflected]: crate +/// [Registering]: TypeRegistry::register +/// [crate-level documentation]: crate pub struct TypeRegistry { registrations: HashMap, short_name_to_id: HashMap, @@ -28,9 +39,15 @@ impl Debug for TypeRegistryArc { } } -/// A trait which allows a type to generate its [`TypeRegistration`]. +/// A trait which allows a type to generate its [`TypeRegistration`] +/// for registration into the [`TypeRegistry`]. +/// +/// This trait is automatically implemented for items using [`#[derive(Reflect)]`](derive@crate::Reflect). +/// The macro also allows [`TypeData`] to be more easily registered. +/// +/// See the [crate-level documentation] for more information on type registration. /// -/// This trait is automatically implemented for types which derive [`Reflect`]. +/// [crate-level documentation]: crate pub trait GetTypeRegistration { fn get_type_registration() -> TypeRegistration; } @@ -257,19 +274,32 @@ impl TypeRegistryArc { } } -/// A record of data about a type. +/// Runtime storage for type metadata, registered into the [`TypeRegistry`]. /// -/// This contains the [`TypeInfo`] of the type, as well as its [short name]. +/// An instance of `TypeRegistration` can be created using the [`TypeRegistration::of`] method, +/// but is more often automatically generated using [`#[derive(Reflect)]`](derive@crate::Reflect) which itself generates +/// an implementation of the [`GetTypeRegistration`] trait. /// -/// For each trait specified by the [`#[reflect(_)]`][0] attribute of -/// [`#[derive(Reflect)]`][1] on the registered type, this record also contains -/// a [`TypeData`] which can be used to downcast [`Reflect`] trait objects of -/// this type to trait objects of the relevant trait. +/// Along with the type's [`TypeInfo`] and [short name], +/// this struct also contains a type's registered [`TypeData`]. +/// +/// See the [crate-level documentation] for more information on type registration. +/// +/// # Example +/// +/// ``` +/// # use bevy_reflect::{TypeRegistration, std_traits::ReflectDefault, FromType}; +/// let mut registration = TypeRegistration::of::>(); +/// +/// assert_eq!("core::option::Option", registration.type_name()); +/// assert_eq!("Option", registration.short_name()); +/// +/// registration.insert::(FromType::>::from_type()); +/// assert!(registration.data::().is_some()) +/// ``` /// /// [short name]: bevy_utils::get_short_name -/// [`TypeInfo`]: crate::TypeInfo -/// [0]: crate::Reflect -/// [1]: crate::Reflect +/// [crate-level documentation]: crate pub struct TypeRegistration { short_name: String, data: HashMap>, @@ -365,9 +395,18 @@ impl Clone for TypeRegistration { } } } -/// A trait for types generated by the [`#[reflect_trait]`][0] attribute macro. + +/// A trait used to type-erase type metadata. +/// +/// Type data can be registered to the [`TypeRegistry`] and stored on a type's [`TypeRegistration`]. +/// +/// While type data is often generated using the [`#[reflect_trait]`](crate::reflect_trait) macro, +/// almost any type that implements [`Clone`] can be considered "type data". +/// This is because it has a blanket implementation over all `T` where `T: Clone + Send + Sync + 'static`. +/// +/// See the [crate-level documentation] for more information on type data and type registration. /// -/// [0]: crate::reflect_trait +/// [crate-level documentation]: crate pub trait TypeData: Downcast + Send + Sync { fn clone_type_data(&self) -> Box; }