Skip to main content

bevy_reflect/info/
typed.rs

1use crate::{
2    array::DynamicArray, enums::DynamicEnum, list::DynamicList, map::DynamicMap, set::DynamicSet,
3    structs::DynamicStruct, tuple::DynamicTuple, tuple_struct::DynamicTupleStruct, PartialReflect,
4    Reflect, TypeInfo, TypePath,
5};
6
7/// A static accessor to compile-time type information.
8///
9/// This trait is automatically implemented by the [`#[derive(Reflect)]`](derive@crate::Reflect) macro
10/// and allows type information to be processed without an instance of that type.
11///
12/// If you need to use this trait as a generic bound along with other reflection traits,
13/// for your convenience, consider using [`Reflectable`] instead.
14///
15/// # Implementing
16///
17/// While it is recommended to leave implementing this trait to the `#[derive(Reflect)]` macro,
18/// it is possible to implement this trait manually. If a manual implementation is needed,
19/// you _must_ ensure that the information you provide is correct, otherwise various systems that
20/// rely on this trait may fail in unexpected ways.
21///
22/// Implementors may have difficulty in generating a reference to [`TypeInfo`] with a static
23/// lifetime. Luckily, this crate comes with some [utility] structs, to make generating these
24/// statics much simpler.
25///
26/// # Example
27///
28/// ```
29/// # use core::any::Any;
30/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, structs::StructInfo, TypeInfo, TypePath, OpaqueInfo, ApplyError};
31/// # use bevy_reflect::utility::NonGenericTypeInfoCell;
32/// use bevy_reflect::Typed;
33///
34/// struct MyStruct {
35///   foo: usize,
36///   bar: (f32, f32)
37/// }
38///
39/// impl Typed for MyStruct {
40///   fn type_info() -> &'static TypeInfo {
41///     static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
42///     CELL.get_or_set(|| {
43///       let fields = [
44///         NamedField::new::<usize >("foo"),
45///         NamedField::new::<(f32, f32) >("bar"),
46///       ];
47///       let info = StructInfo::new::<Self>(&fields);
48///       TypeInfo::Struct(info)
49///     })
50///   }
51/// }
52///
53/// # impl TypePath for MyStruct {
54/// #     fn type_path() -> &'static str { todo!() }
55/// #     fn short_type_path() -> &'static str { todo!() }
56/// # }
57/// # impl PartialReflect for MyStruct {
58/// #     fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
59/// #     fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> { todo!() }
60/// #     fn as_partial_reflect(&self) -> &dyn PartialReflect { todo!() }
61/// #     fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { todo!() }
62/// #     fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> { todo!() }
63/// #     fn try_as_reflect(&self) -> Option<&dyn Reflect> { todo!() }
64/// #     fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { todo!() }
65/// #     fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { todo!() }
66/// #     fn reflect_ref(&self) -> ReflectRef<'_> { todo!() }
67/// #     fn reflect_mut(&mut self) -> ReflectMut<'_> { todo!() }
68/// #     fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
69/// # }
70/// # impl Reflect for MyStruct {
71/// #     fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
72/// #     fn as_any(&self) -> &dyn Any { todo!() }
73/// #     fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
74/// #     fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
75/// #     fn as_reflect(&self) -> &dyn Reflect { todo!() }
76/// #     fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
77/// #     fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
78/// # }
79/// ```
80///
81/// [`Reflectable`]: crate::Reflectable
82/// [utility]: crate::utility
83#[diagnostic::on_unimplemented(
84    message = "`{Self}` does not implement `Typed` so cannot provide static type information",
85    note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
86)]
87pub trait Typed: Reflect + TypePath {
88    /// Returns the compile-time [info] for the underlying type.
89    ///
90    /// [info]: TypeInfo
91    fn type_info() -> &'static TypeInfo;
92}
93
94/// Dynamic dispatch for [`Typed`].
95///
96/// Since this is a supertrait of [`Reflect`] its methods can be called on a `dyn Reflect`.
97///
98/// [`Reflect`]: crate::Reflect
99#[diagnostic::on_unimplemented(
100    message = "`{Self}` can not provide dynamic type information through reflection",
101    note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
102)]
103pub trait DynamicTyped {
104    /// See [`Typed::type_info`].
105    fn reflect_type_info(&self) -> &'static TypeInfo;
106}
107
108impl<T: Typed> DynamicTyped for T {
109    #[inline]
110    fn reflect_type_info(&self) -> &'static TypeInfo {
111        Self::type_info()
112    }
113}
114
115/// A wrapper trait around [`Typed`].
116///
117/// This trait is used to provide a way to get compile-time type information for types that
118/// do implement `Typed` while also allowing for types that do not implement `Typed` to be used.
119/// It's used instead of `Typed` directly to avoid making dynamic types also
120/// implement `Typed` in order to be used as active fields.
121///
122/// This trait has a blanket implementation for all types that implement `Typed`
123/// and manual implementations for all dynamic types (which simply return `None`).
124#[doc(hidden)]
125#[diagnostic::on_unimplemented(
126    message = "`{Self}` does not implement `Typed` so cannot provide static type information",
127    note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
128)]
129pub trait MaybeTyped: PartialReflect {
130    /// Returns the compile-time [info] for the underlying type, if it exists.
131    ///
132    /// [info]: TypeInfo
133    fn maybe_type_info() -> Option<&'static TypeInfo> {
134        None
135    }
136}
137
138impl<T: Typed> MaybeTyped for T {
139    fn maybe_type_info() -> Option<&'static TypeInfo> {
140        Some(T::type_info())
141    }
142}
143
144impl MaybeTyped for DynamicEnum {}
145
146impl MaybeTyped for DynamicTupleStruct {}
147
148impl MaybeTyped for DynamicStruct {}
149
150impl MaybeTyped for DynamicMap {}
151
152impl MaybeTyped for DynamicSet {}
153
154impl MaybeTyped for DynamicList {}
155
156impl MaybeTyped for DynamicArray {}
157
158impl MaybeTyped for DynamicTuple {}