Path: blob/main/crates/bevy_reflect/src/from_reflect.rs
6598 views
use crate::{FromType, PartialReflect, Reflect};1use alloc::boxed::Box;23/// A trait that enables types to be dynamically constructed from reflected data.4///5/// It's recommended to use the [derive macro] rather than manually implementing this trait.6///7/// `FromReflect` allows dynamic proxy types, like [`DynamicStruct`], to be used to generate8/// their concrete counterparts.9/// It can also be used to partially or fully clone a type (depending on whether it has10/// ignored fields or not).11///12/// In some cases, this trait may even be required.13/// Deriving [`Reflect`] on an enum requires all its fields to implement `FromReflect`.14/// Additionally, some complex types like `Vec<T>` require that their element types15/// implement this trait.16/// The reason for such requirements is that some operations require new data to be constructed,17/// such as swapping to a new variant or pushing data to a homogeneous list.18///19/// See the [crate-level documentation] to see how this trait can be used.20///21/// [derive macro]: bevy_reflect_derive::FromReflect22/// [`DynamicStruct`]: crate::DynamicStruct23/// [crate-level documentation]: crate24#[diagnostic::on_unimplemented(25message = "`{Self}` does not implement `FromReflect` so cannot be created through reflection",26note = "consider annotating `{Self}` with `#[derive(Reflect)]`"27)]28pub trait FromReflect: Reflect + Sized {29/// Constructs a concrete instance of `Self` from a reflected value.30fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self>;3132/// Attempts to downcast the given value to `Self` using,33/// constructing the value using [`from_reflect`] if that fails.34///35/// This method is more efficient than using [`from_reflect`] for cases where36/// the given value is likely a boxed instance of `Self` (i.e. `Box<Self>`)37/// rather than a boxed dynamic type (e.g. [`DynamicStruct`], [`DynamicList`], etc.).38///39/// [`from_reflect`]: Self::from_reflect40/// [`DynamicStruct`]: crate::DynamicStruct41/// [`DynamicList`]: crate::DynamicList42fn take_from_reflect(43reflect: Box<dyn PartialReflect>,44) -> Result<Self, Box<dyn PartialReflect>> {45match reflect.try_take::<Self>() {46Ok(value) => Ok(value),47Err(value) => match Self::from_reflect(value.as_ref()) {48None => Err(value),49Some(value) => Ok(value),50},51}52}53}5455/// Type data that represents the [`FromReflect`] trait and allows it to be used dynamically.56///57/// `FromReflect` allows dynamic types (e.g. [`DynamicStruct`], [`DynamicEnum`], etc.) to be converted58/// to their full, concrete types. This is most important when it comes to deserialization where it isn't59/// guaranteed that every field exists when trying to construct the final output.60///61/// However, to do this, you normally need to specify the exact concrete type:62///63/// ```64/// # use bevy_reflect::{DynamicTupleStruct, FromReflect, Reflect};65/// #[derive(Reflect, PartialEq, Eq, Debug)]66/// struct Foo(#[reflect(default = "default_value")] usize);67///68/// fn default_value() -> usize { 123 }69///70/// let reflected = DynamicTupleStruct::default();71///72/// let concrete: Foo = <Foo as FromReflect>::from_reflect(&reflected).unwrap();73///74/// assert_eq!(Foo(123), concrete);75/// ```76///77/// In a dynamic context where the type might not be known at compile-time, this is nearly impossible to do.78/// That is why this type data struct exists— it allows us to construct the full type without knowing79/// what the actual type is.80///81/// # Example82///83/// ```84/// # use bevy_reflect::{DynamicTupleStruct, Reflect, ReflectFromReflect, Typed, TypeRegistry, TypePath};85/// # #[derive(Reflect, PartialEq, Eq, Debug)]86/// # struct Foo(#[reflect(default = "default_value")] usize);87/// # fn default_value() -> usize { 123 }88/// # let mut registry = TypeRegistry::new();89/// # registry.register::<Foo>();90///91/// let mut reflected = DynamicTupleStruct::default();92/// reflected.set_represented_type(Some(<Foo as Typed>::type_info()));93///94/// let registration = registry.get_with_type_path(<Foo as TypePath>::type_path()).unwrap();95/// let rfr = registration.data::<ReflectFromReflect>().unwrap();96///97/// let concrete: Box<dyn Reflect> = rfr.from_reflect(&reflected).unwrap();98///99/// assert_eq!(Foo(123), concrete.take::<Foo>().unwrap());100/// ```101///102/// [`DynamicStruct`]: crate::DynamicStruct103/// [`DynamicEnum`]: crate::DynamicEnum104#[derive(Clone)]105pub struct ReflectFromReflect {106from_reflect: fn(&dyn PartialReflect) -> Option<Box<dyn Reflect>>,107}108109impl ReflectFromReflect {110/// Perform a [`FromReflect::from_reflect`] conversion on the given reflection object.111///112/// This will convert the object to a concrete type if it wasn't already, and return113/// the value as `Box<dyn Reflect>`.114pub fn from_reflect(&self, reflect_value: &dyn PartialReflect) -> Option<Box<dyn Reflect>> {115(self.from_reflect)(reflect_value)116}117}118119impl<T: FromReflect> FromType<T> for ReflectFromReflect {120fn from_type() -> Self {121Self {122from_reflect: |reflect_value| {123T::from_reflect(reflect_value).map(|value| Box::new(value) as Box<dyn Reflect>)124},125}126}127}128129130