@@ -3,7 +3,7 @@ use bevy_utils::{HashMap, HashSet};
3
3
use downcast_rs:: { impl_downcast, Downcast } ;
4
4
use parking_lot:: { RwLock , RwLockReadGuard , RwLockWriteGuard } ;
5
5
use serde:: Deserialize ;
6
- use std:: { any:: TypeId , fmt:: Debug , sync:: Arc } ;
6
+ use std:: { any:: TypeId , fmt:: Debug , marker :: PhantomData , sync:: Arc } ;
7
7
8
8
/// A registry of reflected types.
9
9
#[ derive( Default ) ]
@@ -350,11 +350,103 @@ impl<T: for<'a> Deserialize<'a> + Reflect> FromType<T> for ReflectDeserialize {
350
350
}
351
351
}
352
352
353
+ #[ derive( Clone ) ]
354
+ pub struct ReflectFromPtr {
355
+ type_id : TypeId ,
356
+ to_reflect : for <' a > unsafe fn ( * const ( ) , lt : PhantomData < & ' a ( ) > ) -> & ' a dyn Reflect ,
357
+ to_reflect_mut : for <' a > unsafe fn ( * mut ( ) , lt : PhantomData < & ' a ( ) > ) -> & ' a mut dyn Reflect ,
358
+ }
359
+
360
+ impl ReflectFromPtr {
361
+ /// # Safety:
362
+ /// - `val` must be a pointer to a value of the type that the [`ReflectFromPtr`] was constructed for
363
+ /// - the lifetime `'a` of the return type can be arbitrarily chosen by the caller, who must ensure that during
364
+ /// that lifetime, `val` is valid
365
+ pub unsafe fn to_reflect_ptr < ' a > ( & self , val : * const ( ) ) -> & ' a dyn Reflect {
366
+ ( self . to_reflect ) ( val, PhantomData )
367
+ }
368
+
369
+ /// # Safety:
370
+ /// - `val` must be a pointer to a value of the type that the [`ReflectFromPtr`] was constructed for
371
+ /// - the lifetime `'a` of the return type can be arbitrarily chosen by the caller, who must ensure that during
372
+ /// that lifetime, `val` is valid and not aliased
373
+ pub unsafe fn to_reflect_ptr_mut < ' a > ( & self , val : * mut ( ) ) -> & ' a mut dyn Reflect {
374
+ ( self . to_reflect_mut ) ( val, PhantomData )
375
+ }
376
+
377
+ pub fn to_reflect < ' a , T : ' static > ( & self , val : & ' a T ) -> & ' a dyn Reflect {
378
+ assert_eq ! ( self . type_id, std:: any:: TypeId :: of:: <T >( ) ) ;
379
+ // SAFE: the lifetime of `val` is the same as the lifetime of the return value
380
+ // and the type of `val` has been checked to be the same correct one
381
+ unsafe { self . to_reflect_ptr ( val as * const _ as * const ( ) ) }
382
+ }
383
+
384
+ pub fn to_reflect_mut < ' a , T : ' static > ( & self , val : & ' a mut T ) -> & ' a mut dyn Reflect {
385
+ assert_eq ! ( self . type_id, std:: any:: TypeId :: of:: <T >( ) ) ;
386
+ // SAFE: the lifetime of `val` is the same as the lifetime of the return value
387
+ // and the type of `val` has been checked to be the same correct one
388
+ unsafe { self . to_reflect_ptr_mut ( val as * mut _ as * mut ( ) ) }
389
+ }
390
+ }
391
+
392
+ impl < T : Reflect + ' static > FromType < T > for ReflectFromPtr {
393
+ fn from_type ( ) -> Self {
394
+ ReflectFromPtr {
395
+ type_id : std:: any:: TypeId :: of :: < T > ( ) ,
396
+ to_reflect : |ptr, _lt| {
397
+ // SAFE: can only be called by `to_reflect_ptr` where the caller promises the safety requirements
398
+ // or `to_reflect` which is typed and checks that the correct type is used.
399
+ let val: & T = unsafe { & * ptr. cast :: < T > ( ) } ;
400
+ val as & dyn Reflect
401
+ } ,
402
+ to_reflect_mut : |ptr, _lt| {
403
+ // SAFE: can only be called by `to_reflect_ptr_mut` where the caller promises the safety requirements
404
+ // or `to_reflect_mut` which is typed and checks that the correct type is used.
405
+ let val: & mut T = unsafe { & mut * ptr. cast :: < T > ( ) } ;
406
+ val as & mut dyn Reflect
407
+ } ,
408
+ }
409
+ }
410
+ }
411
+
353
412
#[ cfg( test) ]
354
413
mod test {
355
- use crate :: TypeRegistration ;
414
+ use crate :: { GetTypeRegistration , ReflectFromPtr , TypeRegistration } ;
356
415
use bevy_utils:: HashMap ;
357
416
417
+ use crate as bevy_reflect;
418
+ use crate :: Reflect ;
419
+
420
+ #[ test]
421
+ fn test_reflect_from_ptr ( ) {
422
+ #[ derive( Reflect ) ]
423
+ struct Foo {
424
+ a : f32 ,
425
+ }
426
+
427
+ let foo_registration = <Foo as GetTypeRegistration >:: get_type_registration ( ) ;
428
+ let reflect_from_ptr = foo_registration. data :: < ReflectFromPtr > ( ) . unwrap ( ) ;
429
+
430
+ let mut value = Foo { a : 1.0 } ;
431
+
432
+ let dyn_reflect = reflect_from_ptr. to_reflect_mut ( & mut value) ;
433
+ match dyn_reflect. reflect_mut ( ) {
434
+ bevy_reflect:: ReflectMut :: Struct ( strukt) => {
435
+ strukt. field_mut ( "a" ) . unwrap ( ) . apply ( & 2.0f32 )
436
+ }
437
+ _ => panic ! ( "invalid reflection" ) ,
438
+ }
439
+
440
+ let dyn_reflect = reflect_from_ptr. to_reflect ( & value) ;
441
+ match dyn_reflect. reflect_ref ( ) {
442
+ bevy_reflect:: ReflectRef :: Struct ( strukt) => {
443
+ let a = strukt. field ( "a" ) . unwrap ( ) . downcast_ref :: < f32 > ( ) . unwrap ( ) ;
444
+ assert_eq ! ( * a, 2.0 ) ;
445
+ }
446
+ _ => panic ! ( "invalid reflection" ) ,
447
+ }
448
+ }
449
+
358
450
#[ test]
359
451
fn test_get_short_name ( ) {
360
452
assert_eq ! (
0 commit comments