use crate::{serde::Serializable, Reflect, TypeInfo, TypePath, Typed};
use bevy_ptr::{Ptr, PtrMut};
use bevy_utils::{HashMap, HashSet, TypeIdMap};
use downcast_rs::{impl_downcast, Downcast};
use serde::Deserialize;
use std::{
any::TypeId,
fmt::Debug,
sync::{Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
pub struct TypeRegistry {
registrations: TypeIdMap<TypeRegistration>,
short_path_to_id: HashMap<&'static str, TypeId>,
type_path_to_id: HashMap<&'static str, TypeId>,
ambiguous_names: HashSet<&'static str>,
}
#[derive(Clone, Default)]
pub struct TypeRegistryArc {
pub internal: Arc<RwLock<TypeRegistry>>,
}
impl Debug for TypeRegistryArc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.internal
.read()
.unwrap_or_else(PoisonError::into_inner)
.type_path_to_id
.keys()
.fmt(f)
}
}
pub trait GetTypeRegistration {
fn get_type_registration() -> TypeRegistration;
}
impl Default for TypeRegistry {
fn default() -> Self {
Self::new()
}
}
impl TypeRegistry {
pub fn empty() -> Self {
Self {
registrations: Default::default(),
short_path_to_id: Default::default(),
type_path_to_id: Default::default(),
ambiguous_names: Default::default(),
}
}
pub fn new() -> Self {
let mut registry = Self::empty();
registry.register::<bool>();
registry.register::<char>();
registry.register::<u8>();
registry.register::<u16>();
registry.register::<u32>();
registry.register::<u64>();
registry.register::<u128>();
registry.register::<usize>();
registry.register::<i8>();
registry.register::<i16>();
registry.register::<i32>();
registry.register::<i64>();
registry.register::<i128>();
registry.register::<isize>();
registry.register::<f32>();
registry.register::<f64>();
registry.register::<String>();
registry
}
pub fn register<T>(&mut self)
where
T: GetTypeRegistration,
{
self.add_registration(T::get_type_registration());
}
pub fn add_registration(&mut self, registration: TypeRegistration) {
if self.registrations.contains_key(®istration.type_id()) {
return;
}
let short_name = registration.type_info().type_path_table().short_path();
if self.short_path_to_id.contains_key(short_name)
|| self.ambiguous_names.contains(short_name)
{
self.short_path_to_id.remove(short_name);
self.ambiguous_names.insert(short_name);
} else {
self.short_path_to_id
.insert(short_name, registration.type_id());
}
self.type_path_to_id
.insert(registration.type_info().type_path(), registration.type_id());
self.registrations
.insert(registration.type_id(), registration);
}
pub fn register_type_data<T: Reflect + TypePath, D: TypeData + FromType<T>>(&mut self) {
let data = self.get_mut(TypeId::of::<T>()).unwrap_or_else(|| {
panic!(
"attempted to call `TypeRegistry::register_type_data` for type `{T}` with data `{D}` without registering `{T}` first",
T = T::type_path(),
D = std::any::type_name::<D>(),
)
});
data.insert(D::from_type());
}
pub fn get(&self, type_id: TypeId) -> Option<&TypeRegistration> {
self.registrations.get(&type_id)
}
pub fn get_mut(&mut self, type_id: TypeId) -> Option<&mut TypeRegistration> {
self.registrations.get_mut(&type_id)
}
pub fn get_with_type_path(&self, type_path: &str) -> Option<&TypeRegistration> {
self.type_path_to_id
.get(type_path)
.and_then(|id| self.get(*id))
}
pub fn get_with_type_path_mut(&mut self, type_path: &str) -> Option<&mut TypeRegistration> {
self.type_path_to_id
.get(type_path)
.cloned()
.and_then(move |id| self.get_mut(id))
}
pub fn get_with_short_type_path(&self, short_type_path: &str) -> Option<&TypeRegistration> {
self.short_path_to_id
.get(short_type_path)
.and_then(|id| self.registrations.get(id))
}
pub fn get_with_short_type_path_mut(
&mut self,
short_type_path: &str,
) -> Option<&mut TypeRegistration> {
self.short_path_to_id
.get(short_type_path)
.and_then(|id| self.registrations.get_mut(id))
}
pub fn get_type_data<T: TypeData>(&self, type_id: TypeId) -> Option<&T> {
self.get(type_id)
.and_then(|registration| registration.data::<T>())
}
pub fn get_type_data_mut<T: TypeData>(&mut self, type_id: TypeId) -> Option<&mut T> {
self.get_mut(type_id)
.and_then(|registration| registration.data_mut::<T>())
}
pub fn get_type_info(&self, type_id: TypeId) -> Option<&'static TypeInfo> {
self.get(type_id)
.map(|registration| registration.type_info())
}
pub fn iter(&self) -> impl Iterator<Item = &TypeRegistration> {
self.registrations.values()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut TypeRegistration> {
self.registrations.values_mut()
}
}
impl TypeRegistryArc {
pub fn read(&self) -> RwLockReadGuard<'_, TypeRegistry> {
self.internal.read().unwrap_or_else(PoisonError::into_inner)
}
pub fn write(&self) -> RwLockWriteGuard<'_, TypeRegistry> {
self.internal
.write()
.unwrap_or_else(PoisonError::into_inner)
}
}
pub struct TypeRegistration {
data: TypeIdMap<Box<dyn TypeData>>,
type_info: &'static TypeInfo,
}
impl Debug for TypeRegistration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TypeRegistration")
.field("type_info", &self.type_info)
.finish()
}
}
impl TypeRegistration {
#[inline]
pub fn type_id(&self) -> TypeId {
self.type_info.type_id()
}
pub fn data<T: TypeData>(&self) -> Option<&T> {
self.data
.get(&TypeId::of::<T>())
.and_then(|value| value.downcast_ref())
}
pub fn data_mut<T: TypeData>(&mut self) -> Option<&mut T> {
self.data
.get_mut(&TypeId::of::<T>())
.and_then(|value| value.downcast_mut())
}
pub fn type_info(&self) -> &'static TypeInfo {
self.type_info
}
pub fn insert<T: TypeData>(&mut self, data: T) {
self.data.insert(TypeId::of::<T>(), Box::new(data));
}
pub fn of<T: Reflect + Typed + TypePath>() -> Self {
Self {
data: Default::default(),
type_info: T::type_info(),
}
}
}
impl Clone for TypeRegistration {
fn clone(&self) -> Self {
let mut data = TypeIdMap::default();
for (id, type_data) in &self.data {
data.insert(*id, (*type_data).clone_type_data());
}
TypeRegistration {
data,
type_info: self.type_info,
}
}
}
pub trait TypeData: Downcast + Send + Sync {
fn clone_type_data(&self) -> Box<dyn TypeData>;
}
impl_downcast!(TypeData);
impl<T: 'static + Send + Sync> TypeData for T
where
T: Clone,
{
fn clone_type_data(&self) -> Box<dyn TypeData> {
Box::new(self.clone())
}
}
pub trait FromType<T> {
fn from_type() -> Self;
}
#[derive(Clone)]
pub struct ReflectSerialize {
get_serializable: for<'a> fn(value: &'a dyn Reflect) -> Serializable,
}
impl<T: Reflect + erased_serde::Serialize> FromType<T> for ReflectSerialize {
fn from_type() -> Self {
ReflectSerialize {
get_serializable: |value| {
let value = value.downcast_ref::<T>().unwrap_or_else(|| {
panic!("ReflectSerialize::get_serialize called with type `{}`, even though it was created for `{}`", value.reflect_type_path(), std::any::type_name::<T>())
});
Serializable::Borrowed(value)
},
}
}
}
impl ReflectSerialize {
pub fn get_serializable<'a>(&self, value: &'a dyn Reflect) -> Serializable<'a> {
(self.get_serializable)(value)
}
}
#[derive(Clone)]
pub struct ReflectDeserialize {
pub func: fn(
deserializer: &mut dyn erased_serde::Deserializer,
) -> Result<Box<dyn Reflect>, erased_serde::Error>,
}
impl ReflectDeserialize {
pub fn deserialize<'de, D>(&self, deserializer: D) -> Result<Box<dyn Reflect>, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut erased = <dyn erased_serde::Deserializer>::erase(deserializer);
(self.func)(&mut erased)
.map_err(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)
}
}
impl<T: for<'a> Deserialize<'a> + Reflect> FromType<T> for ReflectDeserialize {
fn from_type() -> Self {
ReflectDeserialize {
func: |deserializer| Ok(Box::new(T::deserialize(deserializer)?)),
}
}
}
#[derive(Clone)]
pub struct ReflectFromPtr {
type_id: TypeId,
from_ptr: unsafe fn(Ptr) -> &dyn Reflect,
from_ptr_mut: unsafe fn(PtrMut) -> &mut dyn Reflect,
}
impl ReflectFromPtr {
pub fn type_id(&self) -> TypeId {
self.type_id
}
pub unsafe fn as_reflect<'a>(&self, val: Ptr<'a>) -> &'a dyn Reflect {
unsafe { (self.from_ptr)(val) }
}
pub unsafe fn as_reflect_mut<'a>(&self, val: PtrMut<'a>) -> &'a mut dyn Reflect {
unsafe { (self.from_ptr_mut)(val) }
}
pub fn from_ptr(&self) -> unsafe fn(Ptr) -> &dyn Reflect {
self.from_ptr
}
pub fn from_ptr_mut(&self) -> unsafe fn(PtrMut) -> &mut dyn Reflect {
self.from_ptr_mut
}
}
impl<T: Reflect> FromType<T> for ReflectFromPtr {
fn from_type() -> Self {
ReflectFromPtr {
type_id: TypeId::of::<T>(),
from_ptr: |ptr| {
unsafe { ptr.deref::<T>() as &dyn Reflect }
},
from_ptr_mut: |ptr| {
unsafe { ptr.deref_mut::<T>() as &mut dyn Reflect }
},
}
}
}
#[cfg(test)]
mod test {
use crate::{GetTypeRegistration, ReflectFromPtr};
use bevy_ptr::{Ptr, PtrMut};
use crate as bevy_reflect;
use crate::Reflect;
#[test]
fn test_reflect_from_ptr() {
#[derive(Reflect)]
struct Foo {
a: f32,
}
let foo_registration = <Foo as GetTypeRegistration>::get_type_registration();
let reflect_from_ptr = foo_registration.data::<ReflectFromPtr>().unwrap();
assert_eq!(reflect_from_ptr.type_id(), std::any::TypeId::of::<Foo>());
let mut value = Foo { a: 1.0 };
{
let value = PtrMut::from(&mut value);
let dyn_reflect = unsafe { reflect_from_ptr.as_reflect_mut(value) };
match dyn_reflect.reflect_mut() {
bevy_reflect::ReflectMut::Struct(strukt) => {
strukt.field_mut("a").unwrap().apply(&2.0f32);
}
_ => panic!("invalid reflection"),
}
}
{
let dyn_reflect = unsafe { reflect_from_ptr.as_reflect(Ptr::from(&value)) };
match dyn_reflect.reflect_ref() {
bevy_reflect::ReflectRef::Struct(strukt) => {
let a = strukt.field("a").unwrap().downcast_ref::<f32>().unwrap();
assert_eq!(*a, 2.0);
}
_ => panic!("invalid reflection"),
}
}
}
}