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

295 lines
7.9 KiB
Rust

#![feature(trait_upcasting)]
use std::{any::TypeId, any::Any};
use lyra_ecs::{AtomicRef, AtomicRefMut, World};
extern crate self as lyra_reflect;
pub use lyra_reflect_derive::*;
#[allow(unused_imports)]
pub(crate) mod lyra_engine {
pub(crate) mod reflect {
pub use super::super::*;
}
}
pub mod reflected_struct;
pub use reflected_struct::*;
pub mod reflected_enum;
pub use reflected_enum::*;
pub mod reflected_tuple;
pub use reflected_tuple::*;
pub mod reflected_array;
pub use reflected_array::*;
pub mod reflected_list;
pub use reflected_list::*;
pub mod dynamic_tuple;
pub use dynamic_tuple::*;
pub mod reflected_hashmap;
pub use reflected_hashmap::*;
pub mod component;
pub use component::*;
pub mod resource;
pub use resource::*;
pub mod util;
pub mod field;
pub use field::*;
pub mod method;
pub use method::*;
pub mod registry;
pub use registry::*;
pub mod impls;
pub trait Reflect: Any {
fn name(&self) -> String;
fn type_id(&self) -> TypeId;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn as_boxed_any(self: Box<Self>) -> Box<dyn Any>;
/// Apply a value to this object.
///
/// # Panics
///
/// The method panics if
/// * the type of `val` is not the same type as `self`
// TODO: instead of taking as reference, it would make more sense to take a Box<dyn Reflect>.
fn apply(&mut self, val: &dyn Reflect);
/// Clone self into a [`Box<dyn Reflect>`]
fn clone_inner(&self) -> Box<dyn Reflect>;
/// Returns a reflected reference of the value of `self`
fn reflect_ref(&self) -> ReflectRef;
/// Returns a reflected mutable reference of the value of `self`
fn reflect_mut(&mut self) -> ReflectMut;
fn reflect_val(&self) -> &dyn Reflect;
fn reflect_val_mut(&mut self) -> &mut dyn Reflect;
/// Returns a boolean indicating if this reflected object is `other_typeid`
///
/// I can't use a generic here because this trait needs to be object safe
fn is(&self, other_typeid: TypeId) -> bool {
TypeId::of::<Self>() == other_typeid
}
}
pub enum ReflectRef<'a> {
Struct(&'a dyn Struct),
Enum(&'a dyn Enum),
Tuple(&'a dyn Tuple),
Array(&'a dyn Array),
List(&'a dyn List),
Value(&'a dyn Reflect),
Map(&'a dyn ReflectedMap),
}
impl<'a> ReflectRef<'a> {
/// Gets the reflected reference as a struct.
///
/// # Safety
/// * If `self` is not a `Struct` variant, this will panic
pub fn as_struct(&self) -> &dyn Struct {
match self {
ReflectRef::Struct(s) => *s,
_ => panic!("`self` is not a struct variant!"),
}
}
}
pub enum ReflectMut<'a> {
Struct(&'a mut dyn Struct),
Enum(&'a mut dyn Enum),
Tuple(&'a mut dyn Tuple),
Array(&'a mut dyn Array),
List(&'a mut dyn List),
Value(&'a mut dyn Reflect),
Map(&'a dyn ReflectedMap),
}
impl<'a> ReflectMut<'a> {
/// Retrieves self as a [`ReflectRef`].
pub fn as_ref(&self) -> ReflectRef {
match self {
ReflectMut::Struct(v) => ReflectRef::Struct(*v),
ReflectMut::Enum(v) => ReflectRef::Enum(*v),
ReflectMut::Tuple(v) => ReflectRef::Tuple(*v),
ReflectMut::Array(v) => ReflectRef::Array(*v),
ReflectMut::List(v) => ReflectRef::List(*v),
ReflectMut::Value(v) => ReflectRef::Value(*v),
ReflectMut::Map(v) => ReflectRef::Map(*v),
}
}
/// Gets the reflected reference as a struct.
///
/// # Safety
/// * If `self` is not a `Struct` variant, this will panic
pub fn as_struct(&self) -> &dyn Struct {
match self {
ReflectMut::Struct(s) => *s,
_ => panic!("`self` is not a struct variant!"),
}
}
/// Gets the reflected reference mutable as a struct.
///
/// # Safety
/// * If `self` is not a `Struct` variant, this will panic
pub fn as_struct_mut(&mut self) -> &mut dyn Struct {
match self {
ReflectMut::Struct(s) => *s,
_ => panic!("`self` is not a struct variant!"),
}
}
}
pub enum ReflectEither<'a> {
Ref(ReflectRef<'a>),
Mut(ReflectMut<'a>),
}
impl<'a> ReflectEither<'a> {
/// Converts `self` into a [`ReflectRef`]. Both variants can be retrieved as a reference.
/* pub fn into_ref(self) -> ReflectRef<'a> {
match self {
Self::Ref(v) => v,
Self::Mut(v) => v.as_ref()
}
} */
/// Attempts to get `self` as a [`ReflectMut`].
///
/// If `self` is a `Ref`, `None` will be returned
pub fn try_into_mut(self) -> Option<ReflectMut<'a>> {
match self {
Self::Mut(v) => Some(v),
Self::Ref(_) => None
}
}
/* pub fn as_ref(&self) -> &ReflectRef<'a> {
match self {
Self::Ref(v) => v,
Self::Mut(v) => &v.as_ref()
}
} */
pub fn is_mut(&self) -> bool {
match self {
ReflectEither::Ref(_) => false,
ReflectEither::Mut(_) => true,
}
}
}
#[allow(dead_code)]
pub struct Value {
inner: Box<dyn Reflect>,
type_id: TypeId,
ref_type_id: TypeId,
}
impl Value {
pub fn new<T: Reflect>(val: T) -> Self {
Self {
inner: Box::new(val),
type_id: TypeId::of::<T>(),
ref_type_id: TypeId::of::<&T>(),
}
}
/// Remove the stored object from Value
pub fn take<T: Reflect>(self) -> Option<T> {
(self.inner as Box<dyn Any>).downcast::<T>().ok().map(|v| *v)
}
pub fn get<T: Reflect>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
pub fn get_mut<T: Reflect>(&mut self) -> Option<&mut T> {
self.inner.as_any_mut().downcast_mut::<T>()
}
}
pub trait IntoValue {
fn into_value(self) -> Value;
fn type_id() -> TypeId;
}
impl<T: Reflect> IntoValue for T {
fn into_value(self) -> Value {
Value::new(self)
}
fn type_id() -> TypeId {
TypeId::of::<T>()
}
}
pub trait FromType<T> {
fn from_type() -> Self;
}
pub trait ReflectWorldExt {
/// Retrieves the type registry from the world.
fn get_type_registry(&self) -> AtomicRef<TypeRegistry>;
/// Retrieves the type registry mutably from the world.
fn get_type_registry_mut(&self) -> AtomicRefMut<TypeRegistry>;
/// Get a registered type from the type registry. Returns `None` if the type is not registered
fn get_type<T>(&self, type_id: TypeId) -> Option<AtomicRef<RegisteredType>>;
/// Get a mutable registered type from the type registry in the world. returns `None` if the type is not registered.
fn get_type_mut<T>(&self, type_id: TypeId) -> Option<AtomicRefMut<RegisteredType>>;
/// Get a registered type, or register a new type and return it.
fn get_type_or_default<T>(&self, type_id: TypeId) -> AtomicRefMut<RegisteredType>;
}
impl ReflectWorldExt for World {
fn get_type_registry(&self) -> AtomicRef<TypeRegistry> {
self.get_resource::<TypeRegistry>()
}
fn get_type_registry_mut(&self) -> AtomicRefMut<TypeRegistry> {
self.get_resource_mut::<TypeRegistry>()
}
fn get_type<T>(&self, type_id: TypeId) -> Option<AtomicRef<RegisteredType>> {
let r = self.get_resource::<TypeRegistry>();
if r.has_type(type_id) {
Some(AtomicRef::map(r, |tr| tr.get_type(type_id).unwrap()))
} else {
None
}
}
fn get_type_mut<T>(&self, type_id: TypeId) -> Option<AtomicRefMut<RegisteredType>> {
let r = self.get_resource_mut::<TypeRegistry>();
if r.has_type(type_id) {
Some(AtomicRefMut::map(r, |tr| tr.get_type_mut(type_id).unwrap()))
} else {
None
}
}
fn get_type_or_default<T>(&self, type_id: TypeId) -> AtomicRefMut<RegisteredType> {
let r = self.get_resource_mut::<TypeRegistry>();
AtomicRefMut::map(r, |tr| tr.get_type_or_default(type_id))
}
}