diff --git a/lyra-reflect/lyra-reflect-derive/src/enum_derive.rs b/lyra-reflect/lyra-reflect-derive/src/enum_derive.rs index 6e41c4c..306de32 100644 --- a/lyra-reflect/lyra-reflect-derive/src/enum_derive.rs +++ b/lyra-reflect/lyra-reflect-derive/src/enum_derive.rs @@ -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) -> Box { + self + } fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) { let val = val.as_any().downcast_ref::() diff --git a/lyra-reflect/lyra-reflect-derive/src/lib.rs b/lyra-reflect/lyra-reflect-derive/src/lib.rs index e340ade..e512611 100644 --- a/lyra-reflect/lyra-reflect-derive/src/lib.rs +++ b/lyra-reflect/lyra-reflect-derive/src/lib.rs @@ -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::()?; + /* let f: Punctuated = 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) -> Box { + self + } fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) { let val = val.as_any().downcast_ref::() diff --git a/lyra-reflect/lyra-reflect-derive/src/struct_derive.rs b/lyra-reflect/lyra-reflect-derive/src/struct_derive.rs index 1f54547..6bea7a8 100644 --- a/lyra-reflect/lyra-reflect-derive/src/struct_derive.rs +++ b/lyra-reflect/lyra-reflect-derive/src/struct_derive.rs @@ -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) -> Box { + self + } fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) { let val = val.as_any().downcast_ref::() diff --git a/lyra-reflect/lyra-reflect-derive/src/struct_macro.rs b/lyra-reflect/lyra-reflect-derive/src/struct_macro.rs index d4971f8..a7e24cb 100644 --- a/lyra-reflect/lyra-reflect-derive/src/struct_macro.rs +++ b/lyra-reflect/lyra-reflect-derive/src/struct_macro.rs @@ -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) -> Box { + self + } fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) { let val = val.as_any().downcast_ref::() diff --git a/lyra-reflect/src/dynamic_tuple.rs b/lyra-reflect/src/dynamic_tuple.rs index b5237bd..8e5faae 100644 --- a/lyra-reflect/src/dynamic_tuple.rs +++ b/lyra-reflect/src/dynamic_tuple.rs @@ -43,6 +43,10 @@ impl Reflect for DynamicTupleRef { self } + fn as_boxed_any(self: Box) -> Box { + 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"); diff --git a/lyra-reflect/src/impls/impl_std.rs b/lyra-reflect/src/impls/impl_std.rs index 9c135e0..4d68c05 100644 --- a/lyra-reflect/src/impls/impl_std.rs +++ b/lyra-reflect/src/impls/impl_std.rs @@ -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); impl_reflect_trait_value!(::core::result::Result); +impl_reflect_trait_value!(::core::marker::PhantomData); + +impl_reflect_trait_value!(::std::sync::Arc); +//impl_reflect_trait_value!(::std::sync::Arc>); +//impl_reflect_trait_value!(::std::sync::RwLock); + impl_reflect_trait_value!(::core::ptr::NonNull); impl Reflect for [T; N] { @@ -50,6 +62,10 @@ impl Reflect for [T; N] { self } + fn as_boxed_any(self: Box) -> Box { + 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 Reflect for Vec { self } + fn as_boxed_any(self: Box) -> Box { + 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 Reflect for Vec { fn reflect_val_mut(&mut self) -> &mut dyn Reflect { self } -} \ No newline at end of file +} + +impl Reflect for Arc> { + fn name(&self) -> String { + let t = self.read().unwrap(); + format!("Arc>", t.name()) + } + + fn type_id(&self) -> std::any::TypeId { + TypeId::of::() + } + + 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) -> Box { + self + } + + fn apply(&mut self, val: &dyn Reflect) { + let val = val.as_any().downcast_ref::() + .expect(&format!("Cannot reflect assign {} to {}", self.name(), val.name())); + *self = val.clone(); + } + + fn clone_inner(&self) -> Box { + 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!() + } +} diff --git a/lyra-reflect/src/lib.rs b/lyra-reflect/src/lib.rs index 4d0a7cb..8823aa7 100644 --- a/lyra-reflect/src/lib.rs +++ b/lyra-reflect/src/lib.rs @@ -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) -> Box; /// 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. fn apply(&mut self, val: &dyn Reflect); /// Clone self into a [`Box`] @@ -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), } } diff --git a/lyra-reflect/src/reflected_hashmap.rs b/lyra-reflect/src/reflected_hashmap.rs new file mode 100644 index 0000000..a5e841e --- /dev/null +++ b/lyra-reflect/src/reflected_hashmap.rs @@ -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, val: Box) -> Option>; + + /// 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 Reflect for HashMap { + fn name(&self) -> String { + format!("HashMap") // TODO: get types of the generics + } + + fn type_id(&self) -> std::any::TypeId { + TypeId::of::() + } + + 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) -> Box { + self + } + + fn apply(&mut self, val: &dyn Reflect) { + let val = val.as_any().downcast_ref::() + .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 { + 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 ReflectedMap for HashMap { + fn reflect_get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { + let key = key.as_any().downcast_ref::() + .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, val: Box) -> Option> { + let key = key.as_boxed_any(); + let key = *key.downcast::().expect("The provided key is not the same type as the HashMap's key"); + + let val = val.as_boxed_any(); + let val = *val.downcast::().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) + } + + fn reflect_contains_key(&self, key: &dyn Reflect) -> bool { + let key = key.as_any().downcast_ref::() + .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() + } +} \ No newline at end of file diff --git a/lyra-reflect/src/reflected_tuple.rs b/lyra-reflect/src/reflected_tuple.rs index 51f0849..6f22f0f 100644 --- a/lyra-reflect/src/reflected_tuple.rs +++ b/lyra-reflect/src/reflected_tuple.rs @@ -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) -> Box { + self + } fn apply(&mut self, val: &dyn Reflect) { let val = val.as_any().downcast_ref::()