lyra-engine/lyra-reflect/src/registry.rs

119 lines
No EOL
3 KiB
Rust

use std::{any::{TypeId, type_name}, collections::HashMap, ops::Deref};
/// Storage for
#[derive(Default, Clone)]
pub struct TypeRegistry {
inner: HashMap<TypeId, RegisteredType>,
}
impl TypeRegistry {
pub fn new() -> Self {
Self::default()
}
/// Get registered type from the registry.
pub fn get_type(&self, type_id: TypeId) -> Option<&RegisteredType> {
self.inner.get(&type_id)
}
/// Get a mutable borrow of a registered type from the registry.
pub fn get_type_mut(&mut self, type_id: TypeId) -> Option<&mut RegisteredType> {
self.inner.get_mut(&type_id)
}
/// Get a registered type, or register a new type and return it.
pub fn get_type_or_default(&mut self, type_id: TypeId) -> &mut RegisteredType {
self.inner.entry(type_id)
.or_insert(RegisteredType::default())
}
pub fn register_type<T>(&mut self)
where
T: AsRegisteredType + 'static
{
self.inner.insert(TypeId::of::<T>(), T::as_registered_type());
}
/// Check if the registry has a type.
pub fn has_type(&self, type_id: TypeId) -> bool {
self.inner.contains_key(&type_id)
}
pub fn add_registered_type(&mut self, type_id: TypeId, registered: RegisteredType) {
self.inner.insert(type_id, registered);
}
}
pub trait TypeData: std::any::Any {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
fn boxed_clone(&self) -> Box<dyn TypeData>;
}
impl<T: Clone + 'static> TypeData for T {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn boxed_clone(&self) -> Box<dyn TypeData> {
Box::new(self.clone())
}
}
#[derive(Default)]
pub struct RegisteredType {
data: HashMap<TypeId, Box<dyn TypeData>>,
pub(crate) data_names: HashMap<TypeId, String>,
}
impl Clone for RegisteredType {
fn clone(&self) -> Self {
let cloned_data = self.data.iter()
.map(|(k, v)| (k.clone(), v.deref().boxed_clone()))
.collect();
Self {
data: cloned_data,
data_names: self.data_names.clone(),
}
}
}
impl RegisteredType {
pub fn new() -> Self {
Self::default()
}
pub fn get_data<D>(&self) -> Option<&D>
where
D: TypeData
{
self.data.get(&TypeId::of::<D>())
.and_then(|b| b.as_ref().as_any().downcast_ref())
}
pub fn get_data_mut<D>(&mut self) -> Option<&mut D>
where
D: TypeData
{
self.data.get_mut(&TypeId::of::<D>())
.and_then(|b| b.as_mut().as_any_mut().downcast_mut())
}
pub fn add_data<D>(&mut self, data: D)
where
D: TypeData
{
self.data.insert(TypeId::of::<D>(), Box::new(data));
self.data_names.insert(TypeId::of::<D>(), type_name::<D>().to_string());
}
}
pub trait AsRegisteredType {
fn as_registered_type() -> RegisteredType;
}