reflect: create ReflectedMap

This commit is contained in:
SeanOMik 2024-03-10 00:17:09 -05:00
parent aa3a4a17d7
commit f345f065c1
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
9 changed files with 234 additions and 2 deletions

View File

@ -495,6 +495,10 @@ pub fn derive_reflect_enum(input: &DeriveInput, data_enum: &DataEnum) -> proc_ma
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) {
let val = val.as_any().downcast_ref::<Self>()

View File

@ -1,7 +1,7 @@
use proc_macro::TokenStream;
use proc_macro2::Ident;
use quote::quote;
use syn::{Generics, Path, Attribute, GenericParam, parse_macro_input, DeriveInput, TypeParamBound};
use syn::{parse_macro_input, Attribute, DeriveInput, GenericParam, Generics, Path, TypeParamBound};
mod enum_derive;
#[allow(unused_imports)]
@ -71,6 +71,8 @@ impl syn::parse::Parse for ReflectDef {
let type_path = Path::parse_mod_style(input)?;
//let ident = type_path. //type_path.require_ident()?;
let mut generics = input.parse::<Generics>()?;
/* let f: Punctuated<GenericParam, Token![,]> = input.parse_terminated(GenericParam::parse, Token![,])?;
generics.params = f; */
generics.where_clause = input.parse()?;
Ok(Self {
@ -134,6 +136,10 @@ pub fn impl_reflect_trait_value(input: TokenStream) -> TokenStream {
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) {
let val = val.as_any().downcast_ref::<Self>()

View File

@ -403,6 +403,10 @@ pub fn derive_reflect_struct(input: &DeriveInput, data_struct: &DataStruct) -> p
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) {
let val = val.as_any().downcast_ref::<Self>()

View File

@ -177,6 +177,10 @@ pub(crate) fn impl_reflect_simple_struct(input: proc_macro::TokenStream) -> proc
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) {
let val = val.as_any().downcast_ref::<Self>()

View File

@ -43,6 +43,10 @@ impl Reflect for DynamicTupleRef {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn Reflect) {
if let ReflectRef::Tuple(t) = val.reflect_ref() {
assert_eq!(t.items_len(), self.items.len(), "The Tuple lengths do not match");

View File

@ -1,9 +1,14 @@
use std::any::TypeId;
use std::sync::Arc;
use std::sync::RwLock;
use lyra_reflect_derive::impl_reflect_trait_value;
use crate::List;
use crate::lyra_engine;
use crate::Struct;
use crate::{Reflect, ReflectRef, ReflectMut, util};
impl_reflect_trait_value!(bool);
@ -26,11 +31,18 @@ impl_reflect_trait_value!(isize);
impl_reflect_trait_value!(f32);
impl_reflect_trait_value!(f64);
impl_reflect_trait_value!(TypeId);
impl_reflect_trait_value!(String);
impl_reflect_trait_value!(::core::option::Option<T: Clone + Reflect>);
impl_reflect_trait_value!(::core::result::Result<T: Clone + Reflect, E: Clone + Reflect>);
impl_reflect_trait_value!(::core::marker::PhantomData<T: 'static>);
impl_reflect_trait_value!(::std::sync::Arc<T: Reflect>);
//impl_reflect_trait_value!(::std::sync::Arc<std::sync::Mutex<T: Reflect>>);
//impl_reflect_trait_value!(::std::sync::RwLock<T: Reflect>);
impl_reflect_trait_value!(::core::ptr::NonNull<T: Reflect>);
impl<T: Clone + Reflect, const N: usize> Reflect for [T; N] {
@ -50,6 +62,10 @@ impl<T: Clone + Reflect, const N: usize> Reflect for [T; N] {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn Reflect) {
if let ReflectRef::Array(arr) = val.reflect_ref() {
util::apply_array(self, arr);
@ -96,6 +112,10 @@ impl<T: Clone + Reflect> Reflect for Vec<T> {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn Reflect) {
if let ReflectRef::List(list) = val.reflect_ref() {
self.apply_list(list);
@ -127,4 +147,53 @@ impl<T: Clone + Reflect> Reflect for Vec<T> {
fn reflect_val_mut(&mut self) -> &mut dyn Reflect {
self
}
}
}
impl<T: Reflect + Struct> Reflect for Arc<RwLock<T>> {
fn name(&self) -> String {
let t = self.read().unwrap();
format!("Arc<RwLock<{}>>", t.name())
}
fn type_id(&self) -> std::any::TypeId {
TypeId::of::<Self>()
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn Reflect) {
let val = val.as_any().downcast_ref::<Self>()
.expect(&format!("Cannot reflect assign {} to {}", self.name(), val.name()));
*self = val.clone();
}
fn clone_inner(&self) -> Box<dyn Reflect> {
todo!()
}
fn reflect_ref(&self) -> ReflectRef {
todo!()
}
fn reflect_mut(&mut self) -> ReflectMut {
todo!()
}
fn reflect_val(&self) -> &dyn Reflect {
todo!()
}
fn reflect_val_mut(&mut self) -> &mut dyn Reflect {
todo!()
}
}

View File

@ -33,6 +33,9 @@ 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::*;
@ -55,6 +58,7 @@ pub trait Reflect: Any {
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.
///
@ -62,6 +66,7 @@ pub trait Reflect: Any {
///
/// 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>`]
@ -92,6 +97,7 @@ pub enum ReflectRef<'a> {
Array(&'a dyn Array),
List(&'a dyn List),
Value(&'a dyn Reflect),
Map(&'a dyn ReflectedMap),
}
impl<'a> ReflectRef<'a> {
@ -114,6 +120,7 @@ pub enum ReflectMut<'a> {
Array(&'a mut dyn Array),
List(&'a mut dyn List),
Value(&'a mut dyn Reflect),
Map(&'a dyn ReflectedMap),
}
impl<'a> ReflectMut<'a> {
@ -126,6 +133,7 @@ impl<'a> ReflectMut<'a> {
ReflectMut::Array(v) => ReflectRef::Array(*v),
ReflectMut::List(v) => ReflectRef::List(*v),
ReflectMut::Value(v) => ReflectRef::Value(*v),
ReflectMut::Map(v) => ReflectRef::Map(*v),
}
}

View File

@ -0,0 +1,129 @@
use std::{any::TypeId, collections::HashMap, hash::Hash};
use crate::Reflect;
pub trait ReflectedMap: Reflect {
/// Get the value at the provided `key` in the map.
///
/// `key` must be the same type as the key in the map.
fn reflect_get(&self, key: &dyn Reflect) -> Option<&dyn Reflect>;
/// Get the nth value in the map.
fn reflect_get_nth_value(&self, n: usize) -> Option<&dyn Reflect>;
/// Get a mutable borrow to the nth value in the map.
fn reflect_get_nth_value_mut(&mut self, n: usize) -> Option<&mut dyn Reflect>;
/// Insert a value at the provided `key` in the map.
///
/// If there is already a value at `key`, the old value will be returned.
fn reflect_insert(&mut self, key: Box<dyn Reflect>, val: Box<dyn Reflect>) -> Option<Box<dyn Reflect>>;
/// Returns a boolean indicating if the map contains a key as `key`.
///
/// `key` must be the same type as the key in the map.
fn reflect_contains_key(&self, key: &dyn Reflect) -> bool;
/// Returns the length of the map
fn reflect_len(&self) -> usize;
fn reflect_capacity(&self) -> usize;
}
impl<K: PartialEq + Eq + Hash + Clone + Reflect, V: Clone + Reflect> Reflect for HashMap<K, V> {
fn name(&self) -> String {
format!("HashMap<?, ?>") // TODO: get types of the generics
}
fn type_id(&self) -> std::any::TypeId {
TypeId::of::<Self>()
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn Reflect) {
let val = val.as_any().downcast_ref::<Self>()
.expect("The provided value is not the same type the HashMap");
for (k, v) in val.iter() {
let (k, v) = (k.clone(), v.clone());
self.insert(k, v);
}
}
fn clone_inner(&self) -> Box<dyn Reflect> {
Box::new(self.clone())
}
fn reflect_ref(&self) -> crate::ReflectRef {
crate::ReflectRef::Map(self)
}
fn reflect_mut(&mut self) -> crate::ReflectMut {
crate::ReflectMut::Map(self)
}
fn reflect_val(&self) -> &dyn Reflect {
self
}
fn reflect_val_mut(&mut self) -> &mut dyn Reflect {
self
}
}
impl<K: PartialEq + Eq + Hash + Clone + Reflect, V: Clone + Reflect> ReflectedMap for HashMap<K, V> {
fn reflect_get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> {
let key = key.as_any().downcast_ref::<K>()
.expect("The provided key is not the same type as the HashMap's key");
self.get(key)
.map(|v| v.reflect_val())
}
fn reflect_get_nth_value(&self, n: usize) -> Option<&dyn Reflect> {
self.values().nth(n)
.map(|v| v.reflect_val())
}
fn reflect_get_nth_value_mut(&mut self, n: usize) -> Option<&mut dyn Reflect> {
self.values_mut().nth(n)
.map(|v| v.reflect_val_mut())
}
fn reflect_insert(&mut self, key: Box<dyn Reflect>, val: Box<dyn Reflect>) -> Option<Box<dyn Reflect>> {
let key = key.as_boxed_any();
let key = *key.downcast::<K>().expect("The provided key is not the same type as the HashMap's key");
let val = val.as_boxed_any();
let val = *val.downcast::<V>().expect("The provided value is not the same type as the HashMap's value");
self.insert(key, val)
.map(|v| Box::new(v) as Box<dyn Reflect>)
}
fn reflect_contains_key(&self, key: &dyn Reflect) -> bool {
let key = key.as_any().downcast_ref::<K>()
.expect("The provided key is not the same type as the HashMap's key");
self.contains_key(key)
}
fn reflect_len(&self) -> usize {
self.len()
}
fn reflect_capacity(&self) -> usize {
self.capacity()
}
}

View File

@ -24,6 +24,10 @@ macro_rules! impl_reflect_tuple {
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_boxed_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn apply(&mut self, val: &dyn Reflect) {
let val = val.as_any().downcast_ref::<Self>()