|
1 |
| -use crate::serde::Serializable; |
2 |
| -use crate::{Reflect, TypeInfo, Typed}; |
| 1 | +use crate::{serde::Serializable, Reflect, TypeInfo, Typed}; |
| 2 | +use bevy_ptr::{Ptr, PtrMut}; |
3 | 3 | use bevy_utils::{HashMap, HashSet};
|
4 | 4 | use downcast_rs::{impl_downcast, Downcast};
|
5 | 5 | use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
@@ -411,11 +411,139 @@ impl<T: for<'a> Deserialize<'a> + Reflect> FromType<T> for ReflectDeserialize {
|
411 | 411 | }
|
412 | 412 | }
|
413 | 413 |
|
| 414 | +/// [`Reflect`] values are commonly used in situations where the actual types of values |
| 415 | +/// are not known at runtime. In such situations you might have access to a `*const ()` pointer |
| 416 | +/// that you know implements [`Reflect`], but have no way of turning it into a `&dyn Reflect`. |
| 417 | +/// |
| 418 | +/// This is where [`ReflectFromPtr`] comes in, when creating a [`ReflectFromPtr`] for a given type `T: Reflect`. |
| 419 | +/// Internally, this saves a concrete function `*const T -> const dyn Reflect` which lets you create a trait object of [`Reflect`] |
| 420 | +/// from a pointer. |
| 421 | +/// |
| 422 | +/// # Example |
| 423 | +/// ```rust |
| 424 | +/// use bevy_reflect::{TypeRegistry, Reflect, ReflectFromPtr}; |
| 425 | +/// use bevy_ptr::Ptr; |
| 426 | +/// use std::ptr::NonNull; |
| 427 | +/// |
| 428 | +/// #[derive(Reflect)] |
| 429 | +/// struct Reflected(String); |
| 430 | +/// |
| 431 | +/// let mut type_registry = TypeRegistry::default(); |
| 432 | +/// type_registry.register::<Reflected>(); |
| 433 | +/// |
| 434 | +/// let mut value = Reflected("Hello world!".to_string()); |
| 435 | +/// let value = unsafe { Ptr::new(NonNull::from(&mut value).cast()) }; |
| 436 | +/// |
| 437 | +/// let reflect_data = type_registry.get(std::any::TypeId::of::<Reflected>()).unwrap(); |
| 438 | +/// let reflect_from_ptr = reflect_data.data::<ReflectFromPtr>().unwrap(); |
| 439 | +/// // SAFE: `value` is of type `Reflected`, which the `ReflectFromPtr` was created for |
| 440 | +/// let value = unsafe { reflect_from_ptr.as_reflect_ptr(value) }; |
| 441 | +/// |
| 442 | +/// assert_eq!(value.downcast_ref::<Reflected>().unwrap().0, "Hello world!"); |
| 443 | +/// ``` |
| 444 | +#[derive(Clone)] |
| 445 | +pub struct ReflectFromPtr { |
| 446 | + type_id: TypeId, |
| 447 | + to_reflect: for<'a> unsafe fn(Ptr<'a>) -> &'a dyn Reflect, |
| 448 | + to_reflect_mut: for<'a> unsafe fn(PtrMut<'a>) -> &'a mut dyn Reflect, |
| 449 | +} |
| 450 | + |
| 451 | +impl ReflectFromPtr { |
| 452 | + /// Returns the [`TypeId`] that the [`ReflectFromPtr`] was constructed for |
| 453 | + pub fn type_id(&self) -> TypeId { |
| 454 | + self.type_id |
| 455 | + } |
| 456 | + |
| 457 | + /// # Safety |
| 458 | + /// |
| 459 | + /// `val` must be a pointer to value of the type that the [`ReflectFromPtr`] was constructed for. |
| 460 | + /// This can be verified by checking that the type id returned by [`ReflectFromPtr::type_id`] is the expected one. |
| 461 | + pub unsafe fn as_reflect_ptr<'a>(&self, val: Ptr<'a>) -> &'a dyn Reflect { |
| 462 | + (self.to_reflect)(val) |
| 463 | + } |
| 464 | + |
| 465 | + /// # Safety |
| 466 | + /// |
| 467 | + /// `val` must be a pointer to a value of the type that the [`ReflectFromPtr`] was constructed for |
| 468 | + /// This can be verified by checking that the type id returned by [`ReflectFromPtr::type_id`] is the expected one. |
| 469 | + pub unsafe fn as_reflect_ptr_mut<'a>(&self, val: PtrMut<'a>) -> &'a mut dyn Reflect { |
| 470 | + (self.to_reflect_mut)(val) |
| 471 | + } |
| 472 | +} |
| 473 | + |
| 474 | +impl<T: Reflect> FromType<T> for ReflectFromPtr { |
| 475 | + fn from_type() -> Self { |
| 476 | + ReflectFromPtr { |
| 477 | + type_id: std::any::TypeId::of::<T>(), |
| 478 | + to_reflect: |ptr| { |
| 479 | + // SAFE: only called from `as_reflect`, where the `ptr` is guaranteed to be of type `T`, |
| 480 | + // and `as_reflect_ptr`, where the caller promises to call it with type `T` |
| 481 | + unsafe { ptr.deref::<T>() as &dyn Reflect } |
| 482 | + }, |
| 483 | + to_reflect_mut: |ptr| { |
| 484 | + // SAFE: only called from `as_reflect_mut`, where the `ptr` is guaranteed to be of type `T`, |
| 485 | + // and `as_reflect_ptr_mut`, where the caller promises to call it with type `T` |
| 486 | + unsafe { ptr.deref_mut::<T>() as &mut dyn Reflect } |
| 487 | + }, |
| 488 | + } |
| 489 | + } |
| 490 | +} |
| 491 | + |
414 | 492 | #[cfg(test)]
|
415 | 493 | mod test {
|
416 |
| - use crate::TypeRegistration; |
| 494 | + use std::ptr::NonNull; |
| 495 | + |
| 496 | + use crate::{GetTypeRegistration, ReflectFromPtr, TypeRegistration}; |
| 497 | + use bevy_ptr::{Ptr, PtrMut}; |
417 | 498 | use bevy_utils::HashMap;
|
418 | 499 |
|
| 500 | + use crate as bevy_reflect; |
| 501 | + use crate::Reflect; |
| 502 | + |
| 503 | + #[test] |
| 504 | + fn test_reflect_from_ptr() { |
| 505 | + #[derive(Reflect)] |
| 506 | + struct Foo { |
| 507 | + a: f32, |
| 508 | + } |
| 509 | + |
| 510 | + let foo_registration = <Foo as GetTypeRegistration>::get_type_registration(); |
| 511 | + let reflect_from_ptr = foo_registration.data::<ReflectFromPtr>().unwrap(); |
| 512 | + |
| 513 | + // not required in this situation because we no nobody messed with the TypeRegistry, |
| 514 | + // but in the general case somebody could have replaced the ReflectFromPtr with an |
| 515 | + // instance for another type, so then we'd need to check that the type is the expected one |
| 516 | + assert_eq!(reflect_from_ptr.type_id(), std::any::TypeId::of::<Foo>()); |
| 517 | + |
| 518 | + let mut value = Foo { a: 1.0 }; |
| 519 | + { |
| 520 | + // SAFETY: lifetime doesn't outlive original value, access is unique |
| 521 | + let value = unsafe { PtrMut::new(NonNull::from(&mut value).cast()) }; |
| 522 | + // SAFETY: reflect_from_ptr was constructed for the correct type |
| 523 | + let dyn_reflect = unsafe { reflect_from_ptr.as_reflect_ptr_mut(value) }; |
| 524 | + match dyn_reflect.reflect_mut() { |
| 525 | + bevy_reflect::ReflectMut::Struct(strukt) => { |
| 526 | + strukt.field_mut("a").unwrap().apply(&2.0f32); |
| 527 | + } |
| 528 | + _ => panic!("invalid reflection"), |
| 529 | + } |
| 530 | + } |
| 531 | + |
| 532 | + { |
| 533 | + // SAFETY: lifetime doesn't outlive original value |
| 534 | + let value = unsafe { Ptr::new(NonNull::from(&mut value).cast()) }; |
| 535 | + // SAFETY: reflect_from_ptr was constructed for the correct type |
| 536 | + let dyn_reflect = unsafe { reflect_from_ptr.as_reflect_ptr(value) }; |
| 537 | + match dyn_reflect.reflect_ref() { |
| 538 | + bevy_reflect::ReflectRef::Struct(strukt) => { |
| 539 | + let a = strukt.field("a").unwrap().downcast_ref::<f32>().unwrap(); |
| 540 | + assert_eq!(*a, 2.0); |
| 541 | + } |
| 542 | + _ => panic!("invalid reflection"), |
| 543 | + } |
| 544 | + } |
| 545 | + } |
| 546 | + |
419 | 547 | #[test]
|
420 | 548 | fn test_property_type_registration() {
|
421 | 549 | assert_eq!(
|
|
0 commit comments