bevy_reflect/
type_registry.rs

1use crate::{serde::Serializable, FromReflect, Reflect, TypeInfo, TypePath, Typed};
2use bevy_ptr::{Ptr, PtrMut};
3use bevy_utils::{HashMap, HashSet, TypeIdMap};
4use downcast_rs::{impl_downcast, Downcast};
5use serde::Deserialize;
6use std::{
7    any::TypeId,
8    fmt::Debug,
9    sync::{Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard},
10};
11
12/// A registry of [reflected] types.
13///
14/// This struct is used as the central store for type information.
15/// [Registering] a type will generate a new [`TypeRegistration`] entry in this store
16/// using a type's [`GetTypeRegistration`] implementation
17/// (which is automatically implemented when using [`#[derive(Reflect)]`](derive@crate::Reflect)).
18///
19/// See the [crate-level documentation] for more information.
20///
21/// [reflected]: crate
22/// [Registering]: TypeRegistry::register
23/// [crate-level documentation]: crate
24pub struct TypeRegistry {
25    registrations: TypeIdMap<TypeRegistration>,
26    short_path_to_id: HashMap<&'static str, TypeId>,
27    type_path_to_id: HashMap<&'static str, TypeId>,
28    ambiguous_names: HashSet<&'static str>,
29}
30
31// TODO:  remove this wrapper once we migrate to Atelier Assets and the Scene AssetLoader doesn't
32// need a TypeRegistry ref
33/// A synchronized wrapper around a [`TypeRegistry`].
34#[derive(Clone, Default)]
35pub struct TypeRegistryArc {
36    pub internal: Arc<RwLock<TypeRegistry>>,
37}
38
39impl Debug for TypeRegistryArc {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        self.internal
42            .read()
43            .unwrap_or_else(PoisonError::into_inner)
44            .type_path_to_id
45            .keys()
46            .fmt(f)
47    }
48}
49
50/// A trait which allows a type to generate its [`TypeRegistration`]
51/// for registration into the [`TypeRegistry`].
52///
53/// This trait is automatically implemented for items using [`#[derive(Reflect)]`](derive@crate::Reflect).
54/// The macro also allows [`TypeData`] to be more easily registered.
55///
56/// See the [crate-level documentation] for more information on type registration.
57///
58/// [crate-level documentation]: crate
59#[diagnostic::on_unimplemented(
60    message = "`{Self}` does not provide type registration information",
61    note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
62)]
63pub trait GetTypeRegistration: 'static {
64    /// Returns the default [`TypeRegistration`] for this type.
65    fn get_type_registration() -> TypeRegistration;
66    /// Registers other types needed by this type.
67    ///
68    /// This method is called by [`TypeRegistry::register`] to register any other required types.
69    /// Often, this is done for fields of structs and enum variants to ensure all types are properly registered.
70    #[allow(unused_variables)]
71    fn register_type_dependencies(registry: &mut TypeRegistry) {}
72}
73
74impl Default for TypeRegistry {
75    fn default() -> Self {
76        Self::new()
77    }
78}
79
80impl TypeRegistry {
81    /// Create a type registry with *no* registered types.
82    pub fn empty() -> Self {
83        Self {
84            registrations: Default::default(),
85            short_path_to_id: Default::default(),
86            type_path_to_id: Default::default(),
87            ambiguous_names: Default::default(),
88        }
89    }
90
91    /// Create a type registry with default registrations for primitive types.
92    pub fn new() -> Self {
93        let mut registry = Self::empty();
94        registry.register::<bool>();
95        registry.register::<char>();
96        registry.register::<u8>();
97        registry.register::<u16>();
98        registry.register::<u32>();
99        registry.register::<u64>();
100        registry.register::<u128>();
101        registry.register::<usize>();
102        registry.register::<i8>();
103        registry.register::<i16>();
104        registry.register::<i32>();
105        registry.register::<i64>();
106        registry.register::<i128>();
107        registry.register::<isize>();
108        registry.register::<f32>();
109        registry.register::<f64>();
110        registry.register::<String>();
111        registry
112    }
113
114    /// Attempts to register the type `T` if it has not yet been registered already.
115    ///
116    /// This will also recursively register any type dependencies as specified by [`GetTypeRegistration::register_type_dependencies`].
117    /// When deriving `Reflect`, this will generally be all the fields of the struct or enum variant.
118    /// As with any type registration, these type dependencies will not be registered more than once.
119    ///
120    /// If the registration for type `T` already exists, it will not be registered again and neither will its type dependencies.
121    /// To register the type, overwriting any existing registration, use [register](Self::overwrite_registration) instead.
122    ///
123    /// Additionally, this will add any reflect [type data](TypeData) as specified in the [`Reflect`] derive.
124    ///
125    /// # Example
126    ///
127    /// ```
128    /// # use std::any::TypeId;
129    /// # use bevy_reflect::{Reflect, TypeRegistry, std_traits::ReflectDefault};
130    /// #[derive(Reflect, Default)]
131    /// #[reflect(Default)]
132    /// struct Foo {
133    ///   name: Option<String>,
134    ///   value: i32
135    /// }
136    ///
137    /// let mut type_registry = TypeRegistry::default();
138    ///
139    /// type_registry.register::<Foo>();
140    ///
141    /// // The main type
142    /// assert!(type_registry.contains(TypeId::of::<Foo>()));
143    ///
144    /// // Its type dependencies
145    /// assert!(type_registry.contains(TypeId::of::<Option<String>>()));
146    /// assert!(type_registry.contains(TypeId::of::<i32>()));
147    ///
148    /// // Its type data
149    /// assert!(type_registry.get_type_data::<ReflectDefault>(TypeId::of::<Foo>()).is_some());
150    /// ```
151    pub fn register<T>(&mut self)
152    where
153        T: GetTypeRegistration,
154    {
155        if self.register_internal(TypeId::of::<T>(), T::get_type_registration) {
156            T::register_type_dependencies(self);
157        }
158    }
159
160    /// Attempts to register the type described by `registration`.
161    ///
162    /// If the registration for the type already exists, it will not be registered again.
163    ///
164    /// To forcibly register the type, overwriting any existing registration, use the
165    /// [`overwrite_registration`](Self::overwrite_registration) method instead.
166    ///
167    /// This method will _not_ register type dependencies.
168    /// Use [`register`](Self::register) to register a type with its dependencies.
169    ///
170    /// Returns `true` if the registration was added and `false` if it already exists.
171    pub fn add_registration(&mut self, registration: TypeRegistration) -> bool {
172        let type_id = registration.type_id();
173        self.register_internal(type_id, || registration)
174    }
175
176    /// Registers the type described by `registration`.
177    ///
178    /// If the registration for the type already exists, it will be overwritten.
179    ///
180    /// To avoid overwriting existing registrations, it's recommended to use the
181    /// [`register`](Self::register) or [`add_registration`](Self::add_registration) methods instead.
182    ///
183    /// This method will _not_ register type dependencies.
184    /// Use [`register`](Self::register) to register a type with its dependencies.
185    pub fn overwrite_registration(&mut self, registration: TypeRegistration) {
186        Self::update_registration_indices(
187            &registration,
188            &mut self.short_path_to_id,
189            &mut self.type_path_to_id,
190            &mut self.ambiguous_names,
191        );
192        self.registrations
193            .insert(registration.type_id(), registration);
194    }
195
196    /// Internal method to register a type with a given [`TypeId`] and [`TypeRegistration`].
197    ///
198    /// By using this method, we are able to reduce the number of `TypeId` hashes and lookups needed
199    /// to register a type.
200    ///
201    /// This method is internal to prevent users from accidentally registering a type with a `TypeId`
202    /// that does not match the type in the `TypeRegistration`.
203    fn register_internal(
204        &mut self,
205        type_id: TypeId,
206        get_registration: impl FnOnce() -> TypeRegistration,
207    ) -> bool {
208        match self.registrations.entry(type_id) {
209            bevy_utils::Entry::Occupied(_) => false,
210            bevy_utils::Entry::Vacant(entry) => {
211                let registration = get_registration();
212                Self::update_registration_indices(
213                    &registration,
214                    &mut self.short_path_to_id,
215                    &mut self.type_path_to_id,
216                    &mut self.ambiguous_names,
217                );
218                entry.insert(registration);
219                true
220            }
221        }
222    }
223
224    /// Internal method to register additional lookups for a given [`TypeRegistration`].
225    fn update_registration_indices(
226        registration: &TypeRegistration,
227        short_path_to_id: &mut HashMap<&'static str, TypeId>,
228        type_path_to_id: &mut HashMap<&'static str, TypeId>,
229        ambiguous_names: &mut HashSet<&'static str>,
230    ) {
231        let short_name = registration.type_info().type_path_table().short_path();
232        if short_path_to_id.contains_key(short_name) || ambiguous_names.contains(short_name) {
233            // name is ambiguous. fall back to long names for all ambiguous types
234            short_path_to_id.remove(short_name);
235            ambiguous_names.insert(short_name);
236        } else {
237            short_path_to_id.insert(short_name, registration.type_id());
238        }
239        type_path_to_id.insert(registration.type_info().type_path(), registration.type_id());
240    }
241
242    /// Registers the type data `D` for type `T`.
243    ///
244    /// Most of the time [`TypeRegistry::register`] can be used instead to register a type you derived [`Reflect`] for.
245    /// However, in cases where you want to add a piece of type data that was not included in the list of `#[reflect(...)]` type data in the derive,
246    /// or where the type is generic and cannot register e.g. [`ReflectSerialize`] unconditionally without knowing the specific type parameters,
247    /// this method can be used to insert additional type data.
248    ///
249    /// # Example
250    /// ```
251    /// use bevy_reflect::{TypeRegistry, ReflectSerialize, ReflectDeserialize};
252    ///
253    /// let mut type_registry = TypeRegistry::default();
254    /// type_registry.register::<Option<String>>();
255    /// type_registry.register_type_data::<Option<String>, ReflectSerialize>();
256    /// type_registry.register_type_data::<Option<String>, ReflectDeserialize>();
257    /// ```
258    pub fn register_type_data<T: Reflect + TypePath, D: TypeData + FromType<T>>(&mut self) {
259        let data = self.get_mut(TypeId::of::<T>()).unwrap_or_else(|| {
260            panic!(
261                "attempted to call `TypeRegistry::register_type_data` for type `{T}` with data `{D}` without registering `{T}` first",
262                T = T::type_path(),
263                D = std::any::type_name::<D>(),
264            )
265        });
266        data.insert(D::from_type());
267    }
268
269    pub fn contains(&self, type_id: TypeId) -> bool {
270        self.registrations.contains_key(&type_id)
271    }
272
273    /// Returns a reference to the [`TypeRegistration`] of the type with the
274    /// given [`TypeId`].
275    ///
276    /// If the specified type has not been registered, returns `None`.
277    ///
278    pub fn get(&self, type_id: TypeId) -> Option<&TypeRegistration> {
279        self.registrations.get(&type_id)
280    }
281
282    /// Returns a mutable reference to the [`TypeRegistration`] of the type with
283    /// the given [`TypeId`].
284    ///
285    /// If the specified type has not been registered, returns `None`.
286    ///
287    pub fn get_mut(&mut self, type_id: TypeId) -> Option<&mut TypeRegistration> {
288        self.registrations.get_mut(&type_id)
289    }
290
291    /// Returns a reference to the [`TypeRegistration`] of the type with the
292    /// given [type path].
293    ///
294    /// If no type with the given path has been registered, returns `None`.
295    ///
296    /// [type path]: TypePath::type_path
297    pub fn get_with_type_path(&self, type_path: &str) -> Option<&TypeRegistration> {
298        self.type_path_to_id
299            .get(type_path)
300            .and_then(|id| self.get(*id))
301    }
302
303    /// Returns a mutable reference to the [`TypeRegistration`] of the type with
304    /// the given [type path].
305    ///
306    /// If no type with the given type path has been registered, returns `None`.
307    ///
308    /// [type path]: TypePath::type_path
309    pub fn get_with_type_path_mut(&mut self, type_path: &str) -> Option<&mut TypeRegistration> {
310        self.type_path_to_id
311            .get(type_path)
312            .cloned()
313            .and_then(move |id| self.get_mut(id))
314    }
315
316    /// Returns a reference to the [`TypeRegistration`] of the type with
317    /// the given [short type path].
318    ///
319    /// If the short type path is ambiguous, or if no type with the given path
320    /// has been registered, returns `None`.
321    ///
322    /// [short type path]: TypePath::short_type_path
323    pub fn get_with_short_type_path(&self, short_type_path: &str) -> Option<&TypeRegistration> {
324        self.short_path_to_id
325            .get(short_type_path)
326            .and_then(|id| self.registrations.get(id))
327    }
328
329    /// Returns a mutable reference to the [`TypeRegistration`] of the type with
330    /// the given [short type path].
331    ///
332    /// If the short type path is ambiguous, or if no type with the given path
333    /// has been registered, returns `None`.
334    ///
335    /// [short type path]: TypePath::short_type_path
336    pub fn get_with_short_type_path_mut(
337        &mut self,
338        short_type_path: &str,
339    ) -> Option<&mut TypeRegistration> {
340        self.short_path_to_id
341            .get(short_type_path)
342            .and_then(|id| self.registrations.get_mut(id))
343    }
344
345    /// Returns `true` if the given [short type path] is ambiguous, that is, it matches multiple registered types.
346    ///
347    /// # Example
348    /// ```
349    /// # use bevy_reflect::TypeRegistry;
350    /// # mod foo {
351    /// #     use bevy_reflect::Reflect;
352    /// #     #[derive(Reflect)]
353    /// #     pub struct MyType;
354    /// # }
355    /// # mod bar {
356    /// #     use bevy_reflect::Reflect;
357    /// #     #[derive(Reflect)]
358    /// #     pub struct MyType;
359    /// # }
360    /// let mut type_registry = TypeRegistry::default();
361    /// type_registry.register::<foo::MyType>();
362    /// type_registry.register::<bar::MyType>();
363    /// assert_eq!(type_registry.is_ambiguous("MyType"), true);
364    /// ```
365    ///
366    /// [short type path]: TypePath::short_type_path
367    pub fn is_ambiguous(&self, short_type_path: &str) -> bool {
368        self.ambiguous_names.contains(short_type_path)
369    }
370
371    /// Returns a reference to the [`TypeData`] of type `T` associated with the given [`TypeId`].
372    ///
373    /// The returned value may be used to downcast [`Reflect`] trait objects to
374    /// trait objects of the trait used to generate `T`, provided that the
375    /// underlying reflected type has the proper `#[reflect(DoThing)]`
376    /// attribute.
377    ///
378    /// If the specified type has not been registered, or if `T` is not present
379    /// in its type registration, returns `None`.
380    pub fn get_type_data<T: TypeData>(&self, type_id: TypeId) -> Option<&T> {
381        self.get(type_id)
382            .and_then(|registration| registration.data::<T>())
383    }
384
385    /// Returns a mutable reference to the [`TypeData`] of type `T` associated with the given [`TypeId`].
386    ///
387    /// If the specified type has not been registered, or if `T` is not present
388    /// in its type registration, returns `None`.
389    pub fn get_type_data_mut<T: TypeData>(&mut self, type_id: TypeId) -> Option<&mut T> {
390        self.get_mut(type_id)
391            .and_then(|registration| registration.data_mut::<T>())
392    }
393
394    /// Returns the [`TypeInfo`] associated with the given [`TypeId`].
395    ///
396    /// If the specified type has not been registered, returns `None`.
397    pub fn get_type_info(&self, type_id: TypeId) -> Option<&'static TypeInfo> {
398        self.get(type_id)
399            .map(|registration| registration.type_info())
400    }
401
402    /// Returns an iterator over the [`TypeRegistration`]s of the registered
403    /// types.
404    pub fn iter(&self) -> impl Iterator<Item = &TypeRegistration> {
405        self.registrations.values()
406    }
407
408    /// Returns a mutable iterator over the [`TypeRegistration`]s of the registered
409    /// types.
410    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut TypeRegistration> {
411        self.registrations.values_mut()
412    }
413
414    /// Checks to see if the [`TypeData`] of type `T` is associated with each registered type,
415    /// returning a ([`TypeRegistration`], [`TypeData`]) iterator for all entries where data of that type was found.
416    pub fn iter_with_data<T: TypeData>(&self) -> impl Iterator<Item = (&TypeRegistration, &T)> {
417        self.registrations.values().filter_map(|item| {
418            let type_data = item.data::<T>();
419            type_data.map(|data| (item, data))
420        })
421    }
422}
423
424impl TypeRegistryArc {
425    /// Takes a read lock on the underlying [`TypeRegistry`].
426    pub fn read(&self) -> RwLockReadGuard<'_, TypeRegistry> {
427        self.internal.read().unwrap_or_else(PoisonError::into_inner)
428    }
429
430    /// Takes a write lock on the underlying [`TypeRegistry`].
431    pub fn write(&self) -> RwLockWriteGuard<'_, TypeRegistry> {
432        self.internal
433            .write()
434            .unwrap_or_else(PoisonError::into_inner)
435    }
436}
437
438/// Runtime storage for type metadata, registered into the [`TypeRegistry`].
439///
440/// An instance of `TypeRegistration` can be created using the [`TypeRegistration::of`] method,
441/// but is more often automatically generated using [`#[derive(Reflect)]`](derive@crate::Reflect) which itself generates
442/// an implementation of the [`GetTypeRegistration`] trait.
443///
444/// Along with the type's [`TypeInfo`],
445/// this struct also contains a type's registered [`TypeData`].
446///
447/// See the [crate-level documentation] for more information on type registration.
448///
449/// # Example
450///
451/// ```
452/// # use bevy_reflect::{TypeRegistration, std_traits::ReflectDefault, FromType};
453/// let mut registration = TypeRegistration::of::<Option<String>>();
454///
455/// assert_eq!("core::option::Option<alloc::string::String>", registration.type_info().type_path());
456/// assert_eq!("Option<String>", registration.type_info().type_path_table().short_path());
457///
458/// registration.insert::<ReflectDefault>(FromType::<Option<String>>::from_type());
459/// assert!(registration.data::<ReflectDefault>().is_some())
460/// ```
461///
462/// [crate-level documentation]: crate
463pub struct TypeRegistration {
464    data: TypeIdMap<Box<dyn TypeData>>,
465    type_info: &'static TypeInfo,
466}
467
468impl Debug for TypeRegistration {
469    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
470        f.debug_struct("TypeRegistration")
471            .field("type_info", &self.type_info)
472            .finish()
473    }
474}
475
476impl TypeRegistration {
477    /// Returns the [`TypeId`] of the type.
478    ///
479    #[inline]
480    pub fn type_id(&self) -> TypeId {
481        self.type_info.type_id()
482    }
483
484    /// Returns a reference to the value of type `T` in this registration's type
485    /// data.
486    ///
487    /// Returns `None` if no such value exists.
488    pub fn data<T: TypeData>(&self) -> Option<&T> {
489        self.data
490            .get(&TypeId::of::<T>())
491            .and_then(|value| value.downcast_ref())
492    }
493
494    /// Returns a mutable reference to the value of type `T` in this
495    /// registration's type data.
496    ///
497    /// Returns `None` if no such value exists.
498    pub fn data_mut<T: TypeData>(&mut self) -> Option<&mut T> {
499        self.data
500            .get_mut(&TypeId::of::<T>())
501            .and_then(|value| value.downcast_mut())
502    }
503
504    /// Returns a reference to the registration's [`TypeInfo`]
505    pub fn type_info(&self) -> &'static TypeInfo {
506        self.type_info
507    }
508
509    /// Inserts an instance of `T` into this registration's type data.
510    ///
511    /// If another instance of `T` was previously inserted, it is replaced.
512    pub fn insert<T: TypeData>(&mut self, data: T) {
513        self.data.insert(TypeId::of::<T>(), Box::new(data));
514    }
515
516    /// Creates type registration information for `T`.
517    pub fn of<T: Reflect + Typed + TypePath>() -> Self {
518        Self {
519            data: Default::default(),
520            type_info: T::type_info(),
521        }
522    }
523}
524
525impl Clone for TypeRegistration {
526    fn clone(&self) -> Self {
527        let mut data = TypeIdMap::default();
528        for (id, type_data) in &self.data {
529            data.insert(*id, (*type_data).clone_type_data());
530        }
531
532        TypeRegistration {
533            data,
534            type_info: self.type_info,
535        }
536    }
537}
538
539/// A trait used to type-erase type metadata.
540///
541/// Type data can be registered to the [`TypeRegistry`] and stored on a type's [`TypeRegistration`].
542///
543/// While type data is often generated using the [`#[reflect_trait]`](crate::reflect_trait) macro,
544/// almost any type that implements [`Clone`] can be considered "type data".
545/// This is because it has a blanket implementation over all `T` where `T: Clone + Send + Sync + 'static`.
546///
547/// See the [crate-level documentation] for more information on type data and type registration.
548///
549/// [crate-level documentation]: crate
550pub trait TypeData: Downcast + Send + Sync {
551    fn clone_type_data(&self) -> Box<dyn TypeData>;
552}
553impl_downcast!(TypeData);
554
555impl<T: 'static + Send + Sync> TypeData for T
556where
557    T: Clone,
558{
559    fn clone_type_data(&self) -> Box<dyn TypeData> {
560        Box::new(self.clone())
561    }
562}
563
564/// Trait used to generate [`TypeData`] for trait reflection.
565///
566/// This is used by the `#[derive(Reflect)]` macro to generate an implementation
567/// of [`TypeData`] to pass to [`TypeRegistration::insert`].
568pub trait FromType<T> {
569    fn from_type() -> Self;
570}
571
572/// A struct used to serialize reflected instances of a type.
573///
574/// A `ReflectSerialize` for type `T` can be obtained via
575/// [`FromType::from_type`].
576#[derive(Clone)]
577pub struct ReflectSerialize {
578    get_serializable: for<'a> fn(value: &'a dyn Reflect) -> Serializable,
579}
580
581impl<T: TypePath + FromReflect + erased_serde::Serialize> FromType<T> for ReflectSerialize {
582    fn from_type() -> Self {
583        ReflectSerialize {
584            get_serializable: |value| {
585                value
586                    .downcast_ref::<T>()
587                    .map(|value| Serializable::Borrowed(value))
588                    .or_else(|| T::from_reflect(value).map(|value| Serializable::Owned(Box::new(value))))
589                    .unwrap_or_else(|| {
590                        panic!(
591                            "FromReflect::from_reflect failed when called on type `{}` with this value: {value:?}",
592                            T::type_path(),
593                        );
594                    })
595            },
596        }
597    }
598}
599
600impl ReflectSerialize {
601    /// Turn the value into a serializable representation
602    pub fn get_serializable<'a>(&self, value: &'a dyn Reflect) -> Serializable<'a> {
603        (self.get_serializable)(value)
604    }
605}
606
607/// A struct used to deserialize reflected instances of a type.
608///
609/// A `ReflectDeserialize` for type `T` can be obtained via
610/// [`FromType::from_type`].
611#[derive(Clone)]
612pub struct ReflectDeserialize {
613    pub func: fn(
614        deserializer: &mut dyn erased_serde::Deserializer,
615    ) -> Result<Box<dyn Reflect>, erased_serde::Error>,
616}
617
618impl ReflectDeserialize {
619    /// Deserializes a reflected value.
620    ///
621    /// The underlying type of the reflected value, and thus the expected
622    /// structure of the serialized data, is determined by the type used to
623    /// construct this `ReflectDeserialize` value.
624    pub fn deserialize<'de, D>(&self, deserializer: D) -> Result<Box<dyn Reflect>, D::Error>
625    where
626        D: serde::Deserializer<'de>,
627    {
628        let mut erased = <dyn erased_serde::Deserializer>::erase(deserializer);
629        (self.func)(&mut erased)
630            .map_err(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)
631    }
632}
633
634impl<T: for<'a> Deserialize<'a> + Reflect> FromType<T> for ReflectDeserialize {
635    fn from_type() -> Self {
636        ReflectDeserialize {
637            func: |deserializer| Ok(Box::new(T::deserialize(deserializer)?)),
638        }
639    }
640}
641
642/// [`Reflect`] values are commonly used in situations where the actual types of values
643/// are not known at runtime. In such situations you might have access to a `*const ()` pointer
644/// that you know implements [`Reflect`], but have no way of turning it into a `&dyn Reflect`.
645///
646/// This is where [`ReflectFromPtr`] comes in, when creating a [`ReflectFromPtr`] for a given type `T: Reflect`.
647/// Internally, this saves a concrete function `*const T -> const dyn Reflect` which lets you create a trait object of [`Reflect`]
648/// from a pointer.
649///
650/// # Example
651/// ```
652/// use bevy_reflect::{TypeRegistry, Reflect, ReflectFromPtr};
653/// use bevy_ptr::Ptr;
654/// use std::ptr::NonNull;
655///
656/// #[derive(Reflect)]
657/// struct Reflected(String);
658///
659/// let mut type_registry = TypeRegistry::default();
660/// type_registry.register::<Reflected>();
661///
662/// let mut value = Reflected("Hello world!".to_string());
663/// let value = Ptr::from(&value);
664///
665/// let reflect_data = type_registry.get(std::any::TypeId::of::<Reflected>()).unwrap();
666/// let reflect_from_ptr = reflect_data.data::<ReflectFromPtr>().unwrap();
667/// // SAFE: `value` is of type `Reflected`, which the `ReflectFromPtr` was created for
668/// let value = unsafe { reflect_from_ptr.as_reflect(value) };
669///
670/// assert_eq!(value.downcast_ref::<Reflected>().unwrap().0, "Hello world!");
671/// ```
672#[derive(Clone)]
673pub struct ReflectFromPtr {
674    type_id: TypeId,
675    from_ptr: unsafe fn(Ptr) -> &dyn Reflect,
676    from_ptr_mut: unsafe fn(PtrMut) -> &mut dyn Reflect,
677}
678
679#[allow(unsafe_code)]
680impl ReflectFromPtr {
681    /// Returns the [`TypeId`] that the [`ReflectFromPtr`] was constructed for.
682    pub fn type_id(&self) -> TypeId {
683        self.type_id
684    }
685
686    /// Convert `Ptr` into `&dyn Reflect`.
687    ///
688    /// # Safety
689    ///
690    /// `val` must be a pointer to value of the type that the [`ReflectFromPtr`] was constructed for.
691    /// This can be verified by checking that the type id returned by [`ReflectFromPtr::type_id`] is the expected one.
692    pub unsafe fn as_reflect<'a>(&self, val: Ptr<'a>) -> &'a dyn Reflect {
693        // SAFETY: contract uphold by the caller.
694        unsafe { (self.from_ptr)(val) }
695    }
696
697    /// Convert `PtrMut` into `&mut dyn Reflect`.
698    ///
699    /// # Safety
700    ///
701    /// `val` must be a pointer to a value of the type that the [`ReflectFromPtr`] was constructed for
702    /// This can be verified by checking that the type id returned by [`ReflectFromPtr::type_id`] is the expected one.
703    pub unsafe fn as_reflect_mut<'a>(&self, val: PtrMut<'a>) -> &'a mut dyn Reflect {
704        // SAFETY: contract uphold by the caller.
705        unsafe { (self.from_ptr_mut)(val) }
706    }
707    /// Get a function pointer to turn a `Ptr` into `&dyn Reflect` for
708    /// the type this [`ReflectFromPtr`] was constructed for.
709    ///
710    /// # Safety
711    ///
712    /// When calling the unsafe function returned by this method you must ensure that:
713    /// - The input `Ptr` points to the `Reflect` type this `ReflectFromPtr`
714    ///   was constructed for.
715    pub fn from_ptr(&self) -> unsafe fn(Ptr) -> &dyn Reflect {
716        self.from_ptr
717    }
718    /// Get a function pointer to turn a `PtrMut` into `&mut dyn Reflect` for
719    /// the type this [`ReflectFromPtr`] was constructed for.
720    ///
721    /// # Safety
722    ///
723    /// When calling the unsafe function returned by this method you must ensure that:
724    /// - The input `PtrMut` points to the `Reflect` type this `ReflectFromPtr`
725    ///   was constructed for.
726    pub fn from_ptr_mut(&self) -> unsafe fn(PtrMut) -> &mut dyn Reflect {
727        self.from_ptr_mut
728    }
729}
730
731#[allow(unsafe_code)]
732impl<T: Reflect> FromType<T> for ReflectFromPtr {
733    fn from_type() -> Self {
734        ReflectFromPtr {
735            type_id: TypeId::of::<T>(),
736            from_ptr: |ptr| {
737                // SAFETY: `from_ptr_mut` is either called in `ReflectFromPtr::as_reflect`
738                // or returned by `ReflectFromPtr::from_ptr`, both lay out the invariants
739                // required by `deref`
740                unsafe { ptr.deref::<T>() as &dyn Reflect }
741            },
742            from_ptr_mut: |ptr| {
743                // SAFETY: same as above, but for `as_reflect_mut`, `from_ptr_mut` and `deref_mut`.
744                unsafe { ptr.deref_mut::<T>() as &mut dyn Reflect }
745            },
746        }
747    }
748}
749
750#[cfg(test)]
751#[allow(unsafe_code)]
752mod test {
753    use crate::{GetTypeRegistration, ReflectFromPtr};
754    use bevy_ptr::{Ptr, PtrMut};
755
756    use crate as bevy_reflect;
757    use crate::Reflect;
758
759    #[test]
760    fn test_reflect_from_ptr() {
761        #[derive(Reflect)]
762        struct Foo {
763            a: f32,
764        }
765
766        let foo_registration = <Foo as GetTypeRegistration>::get_type_registration();
767        let reflect_from_ptr = foo_registration.data::<ReflectFromPtr>().unwrap();
768
769        // not required in this situation because we no nobody messed with the TypeRegistry,
770        // but in the general case somebody could have replaced the ReflectFromPtr with an
771        // instance for another type, so then we'd need to check that the type is the expected one
772        assert_eq!(reflect_from_ptr.type_id(), std::any::TypeId::of::<Foo>());
773
774        let mut value = Foo { a: 1.0 };
775        {
776            let value = PtrMut::from(&mut value);
777            // SAFETY: reflect_from_ptr was constructed for the correct type
778            let dyn_reflect = unsafe { reflect_from_ptr.as_reflect_mut(value) };
779            match dyn_reflect.reflect_mut() {
780                bevy_reflect::ReflectMut::Struct(strukt) => {
781                    strukt.field_mut("a").unwrap().apply(&2.0f32);
782                }
783                _ => panic!("invalid reflection"),
784            }
785        }
786
787        {
788            // SAFETY: reflect_from_ptr was constructed for the correct type
789            let dyn_reflect = unsafe { reflect_from_ptr.as_reflect(Ptr::from(&value)) };
790            match dyn_reflect.reflect_ref() {
791                bevy_reflect::ReflectRef::Struct(strukt) => {
792                    let a = strukt.field("a").unwrap().downcast_ref::<f32>().unwrap();
793                    assert_eq!(*a, 2.0);
794                }
795                _ => panic!("invalid reflection"),
796            }
797        }
798    }
799}