bevy_reflect/from_reflect.rs
1use crate::{FromType, PartialReflect, Reflect};
2
3/// 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 generate
8/// their concrete counterparts.
9/// It can also be used to partially or fully clone a type (depending on whether it has
10/// 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 types
15/// 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::FromReflect
22/// [`DynamicStruct`]: crate::DynamicStruct
23/// [crate-level documentation]: crate
24#[diagnostic::on_unimplemented(
25 message = "`{Self}` does not implement `FromReflect` so cannot be created through reflection",
26 note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
27)]
28pub trait FromReflect: Reflect + Sized {
29 /// Constructs a concrete instance of `Self` from a reflected value.
30 fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self>;
31
32 /// 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 where
36 /// 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_reflect
40 /// [`DynamicStruct`]: crate::DynamicStruct
41 /// [`DynamicList`]: crate::DynamicList
42 fn take_from_reflect(
43 reflect: Box<dyn PartialReflect>,
44 ) -> Result<Self, Box<dyn PartialReflect>> {
45 match reflect.try_take::<Self>() {
46 Ok(value) => Ok(value),
47 Err(value) => match Self::from_reflect(value.as_ref()) {
48 None => Err(value),
49 Some(value) => Ok(value),
50 },
51 }
52 }
53}
54
55/// 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 converted
58/// to their full, concrete types. This is most important when it comes to deserialization where it isn't
59/// 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 knowing
79/// what the actual type is.
80///
81/// # Example
82///
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::DynamicStruct
103/// [`DynamicEnum`]: crate::DynamicEnum
104#[derive(Clone)]
105pub struct ReflectFromReflect {
106 from_reflect: fn(&dyn PartialReflect) -> Option<Box<dyn Reflect>>,
107}
108
109impl 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 return
113 /// the value as `Box<dyn Reflect>`.
114 #[allow(clippy::wrong_self_convention)]
115 pub fn from_reflect(&self, reflect_value: &dyn PartialReflect) -> Option<Box<dyn Reflect>> {
116 (self.from_reflect)(reflect_value)
117 }
118}
119
120impl<T: FromReflect> FromType<T> for ReflectFromReflect {
121 fn from_type() -> Self {
122 Self {
123 from_reflect: |reflect_value| {
124 T::from_reflect(reflect_value).map(|value| Box::new(value) as Box<dyn Reflect>)
125 },
126 }
127 }
128}