bevy_reflect/
reflect.rs

1use crate::{
2    array_debug, enum_debug, list_debug, map_debug, serde::Serializable, set_debug, struct_debug,
3    tuple_debug, tuple_struct_debug, DynamicTypePath, DynamicTyped, OpaqueInfo, ReflectKind,
4    ReflectKindMismatchError, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, Typed,
5};
6use core::{
7    any::{Any, TypeId},
8    fmt::Debug,
9};
10
11use derive_more::derive::{Display, Error};
12
13use crate::utility::NonGenericTypeInfoCell;
14
15/// A enumeration of all error outcomes that might happen when running [`try_apply`](PartialReflect::try_apply).
16#[derive(Error, Display, Debug)]
17pub enum ApplyError {
18    #[display("attempted to apply `{from_kind}` to `{to_kind}`")]
19    /// Attempted to apply the wrong [kind](ReflectKind) to a type, e.g. a struct to a enum.
20    MismatchedKinds {
21        from_kind: ReflectKind,
22        to_kind: ReflectKind,
23    },
24
25    #[display("enum variant `{variant_name}` doesn't have a field named `{field_name}`")]
26    /// Enum variant that we tried to apply to was missing a field.
27    MissingEnumField {
28        variant_name: Box<str>,
29        field_name: Box<str>,
30    },
31
32    #[display("`{from_type}` is not `{to_type}`")]
33    /// Tried to apply incompatible types.
34    MismatchedTypes {
35        from_type: Box<str>,
36        to_type: Box<str>,
37    },
38
39    #[display("attempted to apply type with {from_size} size to a type with {to_size} size")]
40    /// Attempted to apply to types with mismatched sizez, e.g. a [u8; 4] to [u8; 3].
41    DifferentSize { from_size: usize, to_size: usize },
42
43    #[display("variant with name `{variant_name}` does not exist on enum `{enum_name}`")]
44    /// The enum we tried to apply to didn't contain a variant with the give name.
45    UnknownVariant {
46        enum_name: Box<str>,
47        variant_name: Box<str>,
48    },
49}
50
51impl From<ReflectKindMismatchError> for ApplyError {
52    fn from(value: ReflectKindMismatchError) -> Self {
53        Self::MismatchedKinds {
54            from_kind: value.received,
55            to_kind: value.expected,
56        }
57    }
58}
59
60/// The foundational trait of [`bevy_reflect`], used for accessing and modifying data dynamically.
61///
62/// This is a supertrait of [`Reflect`],
63/// meaning any type which implements `Reflect` implements `PartialReflect` by definition.
64///
65/// It's recommended to use [the derive macro for `Reflect`] rather than manually implementing this trait.
66/// Doing so will automatically implement this trait as well as many other useful traits for reflection,
67/// including one of the appropriate subtraits: [`Struct`], [`TupleStruct`] or [`Enum`].
68///
69/// See the [crate-level documentation] to see how this trait and its subtraits can be used.
70///
71/// [`bevy_reflect`]: crate
72/// [the derive macro for `Reflect`]: bevy_reflect_derive::Reflect
73/// [`Struct`]: crate::Struct
74/// [`TupleStruct`]: crate::TupleStruct
75/// [`Enum`]: crate::Enum
76/// [crate-level documentation]: crate
77#[diagnostic::on_unimplemented(
78    message = "`{Self}` does not implement `PartialReflect` so cannot be introspected",
79    note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
80)]
81pub trait PartialReflect: DynamicTypePath + Send + Sync
82where
83    // NB: we don't use `Self: Any` since for downcasting, `Reflect` should be used.
84    Self: 'static,
85{
86    /// Returns the [`TypeInfo`] of the type _represented_ by this value.
87    ///
88    /// For most types, this will simply return their own `TypeInfo`.
89    /// However, for dynamic types, such as [`DynamicStruct`] or [`DynamicList`],
90    /// this will return the type they represent
91    /// (or `None` if they don't represent any particular type).
92    ///
93    /// This method is great if you have an instance of a type or a `dyn Reflect`,
94    /// and want to access its [`TypeInfo`]. However, if this method is to be called
95    /// frequently, consider using [`TypeRegistry::get_type_info`] as it can be more
96    /// performant for such use cases.
97    ///
98    /// [`DynamicStruct`]: crate::DynamicStruct
99    /// [`DynamicList`]: crate::DynamicList
100    /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info
101    fn get_represented_type_info(&self) -> Option<&'static TypeInfo>;
102
103    /// Casts this type to a boxed, reflected value.
104    ///
105    /// This is useful for coercing trait objects.
106    fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect>;
107
108    /// Casts this type to a reflected value.
109    ///
110    /// This is useful for coercing trait objects.
111    fn as_partial_reflect(&self) -> &dyn PartialReflect;
112
113    /// Casts this type to a mutable, reflected value.
114    ///
115    /// This is useful for coercing trait objects.
116    fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect;
117
118    /// Attempts to cast this type to a boxed, [fully-reflected] value.
119    ///
120    /// [fully-reflected]: Reflect
121    fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>;
122
123    /// Attempts to cast this type to a [fully-reflected] value.
124    ///
125    /// [fully-reflected]: Reflect
126    fn try_as_reflect(&self) -> Option<&dyn Reflect>;
127
128    /// Attempts to cast this type to a mutable, [fully-reflected] value.
129    ///
130    /// [fully-reflected]: Reflect
131    fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect>;
132
133    /// Applies a reflected value to this value.
134    ///
135    /// If a type implements an [introspection subtrait], then the semantics of this
136    /// method are as follows:
137    /// - If `T` is a [`Struct`], then the value of each named field of `value` is
138    ///   applied to the corresponding named field of `self`. Fields which are
139    ///   not present in both structs are ignored.
140    /// - If `T` is a [`TupleStruct`] or [`Tuple`], then the value of each
141    ///   numbered field is applied to the corresponding numbered field of
142    ///   `self.` Fields which are not present in both values are ignored.
143    /// - If `T` is an [`Enum`], then the variant of `self` is `updated` to match
144    ///   the variant of `value`. The corresponding fields of that variant are
145    ///   applied from `value` onto `self`. Fields which are not present in both
146    ///   values are ignored.
147    /// - If `T` is a [`List`] or [`Array`], then each element of `value` is applied
148    ///   to the corresponding element of `self`. Up to `self.len()` items are applied,
149    ///   and excess elements in `value` are appended to `self`.
150    /// - If `T` is a [`Map`], then for each key in `value`, the associated
151    ///   value is applied to the value associated with the same key in `self`.
152    ///   Keys which are not present in `self` are inserted.
153    /// - If `T` is none of these, then `value` is downcast to `T`, cloned, and
154    ///   assigned to `self`.
155    ///
156    /// Note that `Reflect` must be implemented manually for [`List`]s and
157    /// [`Map`]s in order to achieve the correct semantics, as derived
158    /// implementations will have the semantics for [`Struct`], [`TupleStruct`], [`Enum`]
159    /// or none of the above depending on the kind of type. For lists and maps, use the
160    /// [`list_apply`] and [`map_apply`] helper functions when implementing this method.
161    ///
162    /// [introspection subtrait]: crate#the-introspection-subtraits
163    /// [`Struct`]: crate::Struct
164    /// [`TupleStruct`]: crate::TupleStruct
165    /// [`Tuple`]: crate::Tuple
166    /// [`Enum`]: crate::Enum
167    /// [`List`]: crate::List
168    /// [`Array`]: crate::Array
169    /// [`Map`]: crate::Map
170    /// [`list_apply`]: crate::list_apply
171    /// [`map_apply`]: crate::map_apply
172    ///
173    /// # Panics
174    ///
175    /// Derived implementations of this method will panic:
176    /// - If the type of `value` is not of the same kind as `T` (e.g. if `T` is
177    ///   a `List`, while `value` is a `Struct`).
178    /// - If `T` is any complex type and the corresponding fields or elements of
179    ///   `self` and `value` are not of the same type.
180    /// - If `T` is an opaque type and `self` cannot be downcast to `T`
181    fn apply(&mut self, value: &dyn PartialReflect) {
182        PartialReflect::try_apply(self, value).unwrap();
183    }
184
185    /// Tries to [`apply`](PartialReflect::apply) a reflected value to this value.
186    ///
187    /// Functions the same as the [`apply`](PartialReflect::apply) function but returns an error instead of
188    /// panicking.
189    ///
190    /// # Handling Errors
191    ///
192    /// This function may leave `self` in a partially mutated state if a error was encountered on the way.
193    /// consider maintaining a cloned instance of this data you can switch to if a error is encountered.
194    fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError>;
195
196    /// Returns a zero-sized enumeration of "kinds" of type.
197    ///
198    /// See [`ReflectKind`].
199    fn reflect_kind(&self) -> ReflectKind {
200        self.reflect_ref().kind()
201    }
202
203    /// Returns an immutable enumeration of "kinds" of type.
204    ///
205    /// See [`ReflectRef`].
206    fn reflect_ref(&self) -> ReflectRef;
207
208    /// Returns a mutable enumeration of "kinds" of type.
209    ///
210    /// See [`ReflectMut`].
211    fn reflect_mut(&mut self) -> ReflectMut;
212
213    /// Returns an owned enumeration of "kinds" of type.
214    ///
215    /// See [`ReflectOwned`].
216    fn reflect_owned(self: Box<Self>) -> ReflectOwned;
217
218    /// Clones the value as a `Reflect` trait object.
219    ///
220    /// When deriving `Reflect` for a struct, tuple struct or enum, the value is
221    /// cloned via [`Struct::clone_dynamic`], [`TupleStruct::clone_dynamic`],
222    /// or [`Enum::clone_dynamic`], respectively.
223    /// Implementors of other `Reflect` subtraits (e.g. [`List`], [`Map`]) should
224    /// use those subtraits' respective `clone_dynamic` methods.
225    ///
226    /// [`Struct::clone_dynamic`]: crate::Struct::clone_dynamic
227    /// [`TupleStruct::clone_dynamic`]: crate::TupleStruct::clone_dynamic
228    /// [`Enum::clone_dynamic`]: crate::Enum::clone_dynamic
229    /// [`List`]: crate::List
230    /// [`Map`]: crate::Map
231    fn clone_value(&self) -> Box<dyn PartialReflect>;
232
233    /// Returns a hash of the value (which includes the type).
234    ///
235    /// If the underlying type does not support hashing, returns `None`.
236    fn reflect_hash(&self) -> Option<u64> {
237        None
238    }
239
240    /// Returns a "partial equality" comparison result.
241    ///
242    /// If the underlying type does not support equality testing, returns `None`.
243    fn reflect_partial_eq(&self, _value: &dyn PartialReflect) -> Option<bool> {
244        None
245    }
246
247    /// Debug formatter for the value.
248    ///
249    /// Any value that is not an implementor of other `Reflect` subtraits
250    /// (e.g. [`List`], [`Map`]), will default to the format: `"Reflect(type_path)"`,
251    /// where `type_path` is the [type path] of the underlying type.
252    ///
253    /// [`List`]: crate::List
254    /// [`Map`]: crate::Map
255    /// [type path]: TypePath::type_path
256    fn debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
257        match self.reflect_ref() {
258            ReflectRef::Struct(dyn_struct) => struct_debug(dyn_struct, f),
259            ReflectRef::TupleStruct(dyn_tuple_struct) => tuple_struct_debug(dyn_tuple_struct, f),
260            ReflectRef::Tuple(dyn_tuple) => tuple_debug(dyn_tuple, f),
261            ReflectRef::List(dyn_list) => list_debug(dyn_list, f),
262            ReflectRef::Array(dyn_array) => array_debug(dyn_array, f),
263            ReflectRef::Map(dyn_map) => map_debug(dyn_map, f),
264            ReflectRef::Set(dyn_set) => set_debug(dyn_set, f),
265            ReflectRef::Enum(dyn_enum) => enum_debug(dyn_enum, f),
266            #[cfg(feature = "functions")]
267            ReflectRef::Function(dyn_function) => dyn_function.fmt(f),
268            ReflectRef::Opaque(_) => write!(f, "Reflect({})", self.reflect_type_path()),
269        }
270    }
271
272    /// Returns a serializable version of the value.
273    ///
274    /// If the underlying type does not support serialization, returns `None`.
275    fn serializable(&self) -> Option<Serializable> {
276        None
277    }
278
279    /// Indicates whether or not this type is a _dynamic_ type.
280    ///
281    /// Dynamic types include the ones built-in to this [crate],
282    /// such as [`DynamicStruct`], [`DynamicList`], and [`DynamicTuple`].
283    /// However, they may be custom types used as proxies for other types
284    /// or to facilitate scripting capabilities.
285    ///
286    /// By default, this method will return `false`.
287    ///
288    /// [`DynamicStruct`]: crate::DynamicStruct
289    /// [`DynamicList`]: crate::DynamicList
290    /// [`DynamicTuple`]: crate::DynamicTuple
291    fn is_dynamic(&self) -> bool {
292        false
293    }
294}
295
296/// A core trait of [`bevy_reflect`], used for downcasting to concrete types.
297///
298/// This is a subtrait of [`PartialReflect`],
299/// meaning any type which implements `Reflect` implements `PartialReflect` by definition.
300///
301/// It's recommended to use [the derive macro] rather than manually implementing this trait.
302/// Doing so will automatically implement this trait, [`PartialReflect`], and many other useful traits for reflection,
303/// including one of the appropriate subtraits: [`Struct`], [`TupleStruct`] or [`Enum`].
304///
305/// If you need to use this trait as a generic bound along with other reflection traits,
306/// for your convenience, consider using [`Reflectable`] instead.
307///
308/// See the [crate-level documentation] to see how this trait can be used.
309///
310/// [`bevy_reflect`]: crate
311/// [the derive macro]: bevy_reflect_derive::Reflect
312/// [`Struct`]: crate::Struct
313/// [`TupleStruct`]: crate::TupleStruct
314/// [`Enum`]: crate::Enum
315/// [`Reflectable`]: crate::Reflectable
316/// [crate-level documentation]: crate
317#[diagnostic::on_unimplemented(
318    message = "`{Self}` does not implement `Reflect` so cannot be fully reflected",
319    note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
320)]
321pub trait Reflect: PartialReflect + DynamicTyped + Any {
322    /// Returns the value as a [`Box<dyn Any>`][std::any::Any].
323    ///
324    /// For remote wrapper types, this will return the remote type instead.
325    fn into_any(self: Box<Self>) -> Box<dyn Any>;
326
327    /// Returns the value as a [`&dyn Any`][std::any::Any].
328    ///
329    /// For remote wrapper types, this will return the remote type instead.
330    fn as_any(&self) -> &dyn Any;
331
332    /// Returns the value as a [`&mut dyn Any`][std::any::Any].
333    ///
334    /// For remote wrapper types, this will return the remote type instead.
335    fn as_any_mut(&mut self) -> &mut dyn Any;
336
337    /// Casts this type to a boxed, fully-reflected value.
338    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect>;
339
340    /// Casts this type to a fully-reflected value.
341    fn as_reflect(&self) -> &dyn Reflect;
342
343    /// Casts this type to a mutable, fully-reflected value.
344    fn as_reflect_mut(&mut self) -> &mut dyn Reflect;
345
346    /// Performs a type-checked assignment of a reflected value to this value.
347    ///
348    /// If `value` does not contain a value of type `T`, returns an `Err`
349    /// containing the trait object.
350    fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>;
351}
352
353impl dyn PartialReflect {
354    /// Returns `true` if the underlying value represents a value of type `T`, or `false`
355    /// otherwise.
356    ///
357    /// Read `is` for more information on underlying values and represented types.
358    #[inline]
359    pub fn represents<T: Reflect + TypePath>(&self) -> bool {
360        self.get_represented_type_info()
361            .map(|t| t.type_path() == T::type_path())
362            .unwrap_or(false)
363    }
364
365    /// Downcasts the value to type `T`, consuming the trait object.
366    ///
367    /// If the underlying value does not implement [`Reflect`]
368    /// or is not of type `T`, returns `Err(self)`.
369    ///
370    /// For remote types, `T` should be the type itself rather than the wrapper type.
371    pub fn try_downcast<T: Any>(
372        self: Box<dyn PartialReflect>,
373    ) -> Result<Box<T>, Box<dyn PartialReflect>> {
374        self.try_into_reflect()?
375            .downcast()
376            .map_err(PartialReflect::into_partial_reflect)
377    }
378
379    /// Downcasts the value to type `T`, unboxing and consuming the trait object.
380    ///
381    /// If the underlying value does not implement [`Reflect`]
382    /// or is not of type `T`, returns `Err(self)`.
383    ///
384    /// For remote types, `T` should be the type itself rather than the wrapper type.
385    pub fn try_take<T: Any>(self: Box<dyn PartialReflect>) -> Result<T, Box<dyn PartialReflect>> {
386        self.try_downcast().map(|value| *value)
387    }
388
389    /// Downcasts the value to type `T` by reference.
390    ///
391    /// If the underlying value does not implement [`Reflect`]
392    /// or is not of type `T`, returns [`None`].
393    ///
394    /// For remote types, `T` should be the type itself rather than the wrapper type.
395    pub fn try_downcast_ref<T: Any>(&self) -> Option<&T> {
396        self.try_as_reflect()?.downcast_ref()
397    }
398
399    /// Downcasts the value to type `T` by mutable reference.
400    ///
401    /// If the underlying value does not implement [`Reflect`]
402    /// or is not of type `T`, returns [`None`].
403    ///
404    /// For remote types, `T` should be the type itself rather than the wrapper type.
405    pub fn try_downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
406        self.try_as_reflect_mut()?.downcast_mut()
407    }
408}
409
410impl Debug for dyn PartialReflect {
411    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
412        self.debug(f)
413    }
414}
415
416// The following implementation never actually shadows the concrete TypePath implementation.
417// See the comment on `dyn Reflect`'s `TypePath` implementation.
418impl TypePath for dyn PartialReflect {
419    fn type_path() -> &'static str {
420        "dyn bevy_reflect::PartialReflect"
421    }
422
423    fn short_type_path() -> &'static str {
424        "dyn PartialReflect"
425    }
426}
427
428#[deny(rustdoc::broken_intra_doc_links)]
429impl dyn Reflect {
430    /// Downcasts the value to type `T`, consuming the trait object.
431    ///
432    /// If the underlying value is not of type `T`, returns `Err(self)`.
433    ///
434    /// For remote types, `T` should be the type itself rather than the wrapper type.
435    pub fn downcast<T: Any>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
436        if self.is::<T>() {
437            Ok(self.into_any().downcast().unwrap())
438        } else {
439            Err(self)
440        }
441    }
442
443    /// Downcasts the value to type `T`, unboxing and consuming the trait object.
444    ///
445    /// If the underlying value is not of type `T`, returns `Err(self)`.
446    ///
447    /// For remote types, `T` should be the type itself rather than the wrapper type.
448    pub fn take<T: Any>(self: Box<dyn Reflect>) -> Result<T, Box<dyn Reflect>> {
449        self.downcast::<T>().map(|value| *value)
450    }
451
452    /// Returns `true` if the underlying value is of type `T`, or `false`
453    /// otherwise.
454    ///
455    /// The underlying value is the concrete type that is stored in this `dyn` object;
456    /// it can be downcasted to. In the case that this underlying value "represents"
457    /// a different type, like the Dynamic\*\*\* types do, you can call `represents`
458    /// to determine what type they represent. Represented types cannot be downcasted
459    /// to, but you can use [`FromReflect`] to create a value of the represented type from them.
460    ///
461    /// For remote types, `T` should be the type itself rather than the wrapper type.
462    ///
463    /// [`FromReflect`]: crate::FromReflect
464    #[inline]
465    pub fn is<T: Any>(&self) -> bool {
466        self.as_any().type_id() == TypeId::of::<T>()
467    }
468
469    /// Downcasts the value to type `T` by reference.
470    ///
471    /// If the underlying value is not of type `T`, returns `None`.
472    ///
473    /// For remote types, `T` should be the type itself rather than the wrapper type.
474    #[inline]
475    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
476        self.as_any().downcast_ref::<T>()
477    }
478
479    /// Downcasts the value to type `T` by mutable reference.
480    ///
481    /// If the underlying value is not of type `T`, returns `None`.
482    ///
483    /// For remote types, `T` should be the type itself rather than the wrapper type.
484    #[inline]
485    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
486        self.as_any_mut().downcast_mut::<T>()
487    }
488}
489
490impl Debug for dyn Reflect {
491    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
492        self.debug(f)
493    }
494}
495
496impl Typed for dyn Reflect {
497    fn type_info() -> &'static TypeInfo {
498        static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
499        CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::<Self>()))
500    }
501}
502
503// The following implementation never actually shadows the concrete `TypePath` implementation.
504// See this playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=589064053f27bc100d90da89c6a860aa).
505impl TypePath for dyn Reflect {
506    fn type_path() -> &'static str {
507        "dyn bevy_reflect::Reflect"
508    }
509
510    fn short_type_path() -> &'static str {
511        "dyn Reflect"
512    }
513}
514
515macro_rules! impl_full_reflect {
516    ($(<$($id:ident),* $(,)?>)? for $ty:ty $(where $($tt:tt)*)?) => {
517        impl $(<$($id),*>)? $crate::Reflect for $ty $(where $($tt)*)? {
518            fn into_any(self: Box<Self>) -> Box<dyn ::core::any::Any> {
519                self
520            }
521
522            fn as_any(&self) -> &dyn ::core::any::Any {
523                self
524            }
525
526            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
527                self
528            }
529
530            fn into_reflect(self: Box<Self>) -> Box<dyn $crate::Reflect> {
531                self
532            }
533
534            fn as_reflect(&self) -> &dyn $crate::Reflect {
535                self
536            }
537
538            fn as_reflect_mut(&mut self) -> &mut dyn $crate::Reflect {
539                self
540            }
541
542            fn set(
543                &mut self,
544                value: Box<dyn $crate::Reflect>,
545            ) -> Result<(), Box<dyn $crate::Reflect>> {
546                *self = <dyn $crate::Reflect>::take(value)?;
547                Ok(())
548            }
549        }
550    };
551}
552
553pub(crate) use impl_full_reflect;