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 ®istration,
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 ®istration,
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}