2021-01-08 03:50:09 +00:00
|
|
|
use crate::{serde::Serializable, List, Map, Struct, Tuple, TupleStruct};
|
2020-11-28 00:39:59 +00:00
|
|
|
use std::{any::Any, fmt::Debug};
|
|
|
|
|
|
|
|
pub use bevy_utils::AHasher as ReflectHasher;
|
|
|
|
|
2022-01-14 19:09:44 +00:00
|
|
|
/// An immutable enumeration of "kinds" of reflected type.
|
|
|
|
///
|
|
|
|
/// Each variant contains a trait object with methods specific to a kind of
|
|
|
|
/// type.
|
|
|
|
///
|
|
|
|
/// A `ReflectRef` is obtained via [`Reflect::reflect_ref`].
|
2020-11-28 00:39:59 +00:00
|
|
|
pub enum ReflectRef<'a> {
|
|
|
|
Struct(&'a dyn Struct),
|
|
|
|
TupleStruct(&'a dyn TupleStruct),
|
2021-01-08 03:50:09 +00:00
|
|
|
Tuple(&'a dyn Tuple),
|
2020-11-28 00:39:59 +00:00
|
|
|
List(&'a dyn List),
|
|
|
|
Map(&'a dyn Map),
|
|
|
|
Value(&'a dyn Reflect),
|
|
|
|
}
|
|
|
|
|
2022-01-14 19:09:44 +00:00
|
|
|
/// A mutable enumeration of "kinds" of reflected type.
|
|
|
|
///
|
|
|
|
/// Each variant contains a trait object with methods specific to a kind of
|
|
|
|
/// type.
|
|
|
|
///
|
|
|
|
/// A `ReflectMut` is obtained via [`Reflect::reflect_mut`].
|
2020-11-28 00:39:59 +00:00
|
|
|
pub enum ReflectMut<'a> {
|
|
|
|
Struct(&'a mut dyn Struct),
|
|
|
|
TupleStruct(&'a mut dyn TupleStruct),
|
2021-01-09 02:29:03 +00:00
|
|
|
Tuple(&'a mut dyn Tuple),
|
2020-11-28 00:39:59 +00:00
|
|
|
List(&'a mut dyn List),
|
|
|
|
Map(&'a mut dyn Map),
|
|
|
|
Value(&'a mut dyn Reflect),
|
|
|
|
}
|
|
|
|
|
2022-01-08 20:45:24 +00:00
|
|
|
/// A reflected Rust type.
|
|
|
|
///
|
|
|
|
/// Methods for working with particular kinds of Rust type are available using the [`List`], [`Map`],
|
|
|
|
/// [`Struct`], [`TupleStruct`], and [`Tuple`] subtraits.
|
|
|
|
///
|
|
|
|
/// When using `#[derive(Reflect)]` with a struct or tuple struct, the suitable subtrait for that
|
|
|
|
/// type (`Struct` or `TupleStruct`) is derived automatically.
|
2021-03-17 22:46:46 +00:00
|
|
|
///
|
|
|
|
/// # Safety
|
2021-04-25 17:24:09 +00:00
|
|
|
/// Implementors _must_ ensure that [`Reflect::any`] and [`Reflect::any_mut`] both return the `self`
|
2022-01-08 20:45:24 +00:00
|
|
|
/// value passed in. If this is not done, [`Reflect::downcast`](trait.Reflect.html#method.downcast)
|
2021-04-25 17:24:09 +00:00
|
|
|
/// will be UB (and also just logically broken).
|
2021-03-17 22:46:46 +00:00
|
|
|
pub unsafe trait Reflect: Any + Send + Sync {
|
2022-01-14 19:09:44 +00:00
|
|
|
/// Returns the [type name] of the underlying type.
|
|
|
|
///
|
|
|
|
/// [type name]: std::any::type_name
|
2020-11-28 00:39:59 +00:00
|
|
|
fn type_name(&self) -> &str;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Returns the value as a [`&dyn Any`][std::any::Any].
|
2020-11-28 00:39:59 +00:00
|
|
|
fn any(&self) -> &dyn Any;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Returns the value as a [`&mut dyn Any`][std::any::Any].
|
2020-11-28 00:39:59 +00:00
|
|
|
fn any_mut(&mut self) -> &mut dyn Any;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Applies a reflected value to this value.
|
|
|
|
///
|
|
|
|
/// If a type implements a subtrait of `Reflect`, then the semantics of this
|
|
|
|
/// method are as follows:
|
|
|
|
/// - If `T` is a [`Struct`], then the value of each named field of `value` is
|
|
|
|
/// applied to the corresponding named field of `self`. Fields which are
|
|
|
|
/// not present in both structs are ignored.
|
|
|
|
/// - If `T` is a [`TupleStruct`] or [`Tuple`], then the value of each
|
|
|
|
/// numbered field is applied to the corresponding numbered field of
|
|
|
|
/// `self.` Fields which are not present in both values are ignored.
|
|
|
|
/// - If `T` is a [`List`], then each element of `value` is applied to the
|
|
|
|
/// corresponding element of `self`. Up to `self.len()` items are applied,
|
|
|
|
/// and excess elements in `value` are appended to `self`.
|
|
|
|
/// - If `T` is a [`Map`], then for each key in `value`, the associated
|
|
|
|
/// value is applied to the value associated with the same key in `self`.
|
|
|
|
/// Keys which are not present in both maps are ignored.
|
|
|
|
/// - If `T` is none of these, then `value` is downcast to `T`, cloned, and
|
|
|
|
/// assigned to `self`.
|
|
|
|
///
|
|
|
|
/// Note that `Reflect` must be implemented manually for [`List`]s and
|
|
|
|
/// [`Map`]s in order to achieve the correct semantics, as derived
|
|
|
|
/// implementations will have the semantics for [`Struct`], [`TupleStruct`]
|
|
|
|
/// or none of the above depending on the kind of type. For lists, use the
|
|
|
|
/// [`list_apply`] helper function when implementing this method.
|
|
|
|
///
|
|
|
|
/// [`list_apply`]: crate::list_apply
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Derived implementations of this method will panic:
|
|
|
|
/// - If the type of `value` is not of the same kind as `T` (e.g. if `T` is
|
|
|
|
/// a `List`, while `value` is a `Struct`).
|
|
|
|
/// - If `T` is any complex type and the corresponding fields or elements of
|
|
|
|
/// `self` and `value` are not of the same type.
|
|
|
|
/// - If `T` is a value type and `self` cannot be downcast to `T`
|
2020-11-28 00:39:59 +00:00
|
|
|
fn apply(&mut self, value: &dyn Reflect);
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Performs a type-checked assignment of a reflected value to this value.
|
|
|
|
///
|
|
|
|
/// If `value` does not contain a value of type `T`, returns an `Err`
|
|
|
|
/// containing the trait object.
|
2020-11-28 00:39:59 +00:00
|
|
|
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Returns an enumeration of "kinds" of type.
|
|
|
|
///
|
|
|
|
/// See [`ReflectRef`].
|
2020-11-28 00:39:59 +00:00
|
|
|
fn reflect_ref(&self) -> ReflectRef;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Returns a mutable enumeration of "kinds" of type.
|
|
|
|
///
|
|
|
|
/// See [`ReflectMut`].
|
2020-11-28 00:39:59 +00:00
|
|
|
fn reflect_mut(&mut self) -> ReflectMut;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Clones the value as a `Reflect` trait object.
|
|
|
|
///
|
|
|
|
/// When deriving `Reflect` for a struct or struct tuple, the value is
|
|
|
|
/// cloned via [`Struct::clone_dynamic`] (resp.
|
|
|
|
/// [`TupleStruct::clone_dynamic`]). Implementors of other `Reflect`
|
|
|
|
/// subtraits (e.g. [`List`], [`Map`]) should use those subtraits'
|
|
|
|
/// respective `clone_dynamic` methods.
|
2020-11-28 00:39:59 +00:00
|
|
|
fn clone_value(&self) -> Box<dyn Reflect>;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Returns a hash of the value (which includes the type).
|
|
|
|
///
|
|
|
|
/// If the underlying type does not support hashing, returns `None`.
|
2020-12-01 19:15:07 +00:00
|
|
|
fn reflect_hash(&self) -> Option<u64>;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Returns a "partial equality" comparison result.
|
|
|
|
///
|
|
|
|
/// If the underlying type does not support equality testing, returns `None`.
|
2020-12-01 19:15:07 +00:00
|
|
|
fn reflect_partial_eq(&self, _value: &dyn Reflect) -> Option<bool>;
|
2022-01-14 19:09:44 +00:00
|
|
|
|
|
|
|
/// Returns a serializable version of the value.
|
|
|
|
///
|
|
|
|
/// If the underlying type does not support serialization, returns `None`.
|
2020-11-28 00:39:59 +00:00
|
|
|
fn serializable(&self) -> Option<Serializable>;
|
|
|
|
}
|
|
|
|
|
2022-01-14 19:09:44 +00:00
|
|
|
/// A trait for types which can be constructed from a reflected type.
|
|
|
|
///
|
|
|
|
/// This trait can be derived on types which implement [`Reflect`]. Some complex
|
|
|
|
/// types (such as `Vec<T>`) may only be reflected if their element types
|
|
|
|
/// implement this trait.
|
|
|
|
///
|
|
|
|
/// 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.
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
pub trait FromReflect: Reflect + Sized {
|
2022-01-14 19:09:44 +00:00
|
|
|
/// Constructs a concrete instance of `Self` from a reflected value.
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
2020-11-28 00:39:59 +00:00
|
|
|
impl Debug for dyn Reflect {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
Avoid some format! into immediate format! (#2913)
# Objective
- Avoid usages of `format!` that ~immediately get passed to another `format!`. This avoids a temporary allocation and is just generally cleaner.
## Solution
- `bevy_derive::shader_defs` does a `format!("{}", val.to_string())`, which is better written as just `format!("{}", val)`
- `bevy_diagnostic::log_diagnostics_plugin` does a `format!("{:>}", format!(...))`, which is better written as `format!("{:>}", format_args!(...))`
- `bevy_ecs::schedule` does `tracing::info!(..., name = &*format!("{:?}", val))`, which is better written with the tracing shorthand `tracing::info!(..., name = ?val)`
- `bevy_reflect::reflect` does `f.write_str(&format!(...))`, which is better written as `write!(f, ...)` (this could also be written using `f.debug_tuple`, but I opted to maintain alt debug behavior)
- `bevy_reflect::serde::{ser, de}` do `serde::Error::custom(format!(...))`, which is better written as `Error::custom(format_args!(...))`, as `Error::custom` takes `impl Display` and just immediately calls `format!` again
2021-10-06 18:34:33 +00:00
|
|
|
write!(f, "Reflect({})", self.type_name())
|
2020-11-28 00:39:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl dyn Reflect {
|
2022-01-14 19:09:44 +00:00
|
|
|
/// Downcasts the value to type `T`, consuming the trait object.
|
|
|
|
///
|
|
|
|
/// If the underlying value is not of type `T`, returns `Err(self)`.
|
2020-11-28 00:39:59 +00:00
|
|
|
pub fn downcast<T: Reflect>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
|
2021-03-11 00:27:30 +00:00
|
|
|
// SAFE?: Same approach used by std::any::Box::downcast. ReflectValue is always Any and type
|
|
|
|
// has been checked.
|
2020-11-28 00:39:59 +00:00
|
|
|
if self.is::<T>() {
|
|
|
|
unsafe {
|
|
|
|
let raw: *mut dyn Reflect = Box::into_raw(self);
|
|
|
|
Ok(Box::from_raw(raw as *mut T))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-14 19:09:44 +00:00
|
|
|
/// Downcasts the value to type `T`, unboxing and consuming the trait object.
|
|
|
|
///
|
|
|
|
/// If the underlying value is not of type `T`, returns `Err(self)`.
|
2020-11-28 00:39:59 +00:00
|
|
|
pub fn take<T: Reflect>(self: Box<dyn Reflect>) -> Result<T, Box<dyn Reflect>> {
|
|
|
|
self.downcast::<T>().map(|value| *value)
|
|
|
|
}
|
|
|
|
|
2022-01-14 19:09:44 +00:00
|
|
|
/// Returns `true` if the underlying value is of type `T`, or `false`
|
|
|
|
/// otherwise.
|
2020-11-28 00:39:59 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn is<T: Reflect>(&self) -> bool {
|
|
|
|
self.any().is::<T>()
|
|
|
|
}
|
|
|
|
|
2022-01-14 19:09:44 +00:00
|
|
|
/// Downcasts the value to type `T` by reference.
|
|
|
|
///
|
|
|
|
/// If the underlying value is not of type `T`, returns `None`.
|
2020-11-28 00:39:59 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn downcast_ref<T: Reflect>(&self) -> Option<&T> {
|
|
|
|
self.any().downcast_ref::<T>()
|
|
|
|
}
|
|
|
|
|
2022-01-14 19:09:44 +00:00
|
|
|
/// Downcasts the value to type `T` by mutable reference.
|
|
|
|
///
|
|
|
|
/// If the underlying value is not of type `T`, returns `None`.
|
2020-11-28 00:39:59 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn downcast_mut<T: Reflect>(&mut self) -> Option<&mut T> {
|
|
|
|
self.any_mut().downcast_mut::<T>()
|
|
|
|
}
|
|
|
|
}
|