189 lines
5.3 KiB
Rust
189 lines
5.3 KiB
Rust
use crate::Properties;
|
|
use std::any::Any;
|
|
|
|
pub trait Property: erased_serde::Serialize + Send + Sync + Any + 'static {
|
|
fn type_name(&self) -> &str;
|
|
fn any(&self) -> &dyn Any;
|
|
fn any_mut(&mut self) -> &mut dyn Any;
|
|
fn clone_prop(&self) -> Box<dyn Property>;
|
|
fn set(&mut self, value: &dyn Property);
|
|
fn apply(&mut self, value: &dyn Property);
|
|
fn as_properties(&self) -> Option<&dyn Properties> {
|
|
None
|
|
}
|
|
fn is_sequence(&self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
erased_serde::serialize_trait_object!(Property);
|
|
|
|
pub trait PropertyVal {
|
|
fn val<T: 'static>(&self) -> Option<&T>;
|
|
fn set_val<T: 'static>(&mut self, value: T);
|
|
}
|
|
|
|
impl PropertyVal for dyn Property {
|
|
#[inline]
|
|
fn val<T: 'static>(&self) -> Option<&T> {
|
|
self.any().downcast_ref::<T>()
|
|
}
|
|
|
|
#[inline]
|
|
fn set_val<T: 'static>(&mut self, value: T) {
|
|
if let Some(prop) = self.any_mut().downcast_mut::<T>() {
|
|
*prop = value;
|
|
} else {
|
|
panic!("prop value is not {}", std::any::type_name::<T>());
|
|
}
|
|
}
|
|
}
|
|
|
|
// used by impl_property
|
|
#[allow(unused_macros)]
|
|
macro_rules! as_item {
|
|
($i:item) => {
|
|
$i
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! impl_property {
|
|
($ty:ident) => {
|
|
impl Property for $ty {
|
|
#[inline]
|
|
fn type_name(&self) -> &str {
|
|
std::any::type_name::<Self>()
|
|
}
|
|
|
|
#[inline]
|
|
fn any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
#[inline]
|
|
fn any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
#[inline]
|
|
fn clone_prop(&self) -> Box<dyn Property> {
|
|
Box::new(self.clone())
|
|
}
|
|
|
|
#[inline]
|
|
fn apply(&mut self, value: &dyn Property) {
|
|
self.set(value);
|
|
}
|
|
|
|
fn set(&mut self, value: &dyn Property) {
|
|
let value = value.any();
|
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
|
*self = prop.clone();
|
|
} else {
|
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
|
}
|
|
}
|
|
}
|
|
};
|
|
(SEQUENCE, @$trait_:ident [$($args:ident,)*] where [$($preds:tt)+]) => {
|
|
impl_property! {
|
|
@as_item
|
|
impl<$($args),*> Property for $trait_<$($args),*> where $($args: ::std::any::Any + 'static,)*
|
|
$($preds)* {
|
|
#[inline]
|
|
fn type_name(&self) -> &str {
|
|
std::any::type_name::<Self>()
|
|
}
|
|
|
|
#[inline]
|
|
fn any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
#[inline]
|
|
fn any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
#[inline]
|
|
fn clone_prop(&self) -> Box<dyn Property> {
|
|
Box::new(self.clone())
|
|
}
|
|
|
|
#[inline]
|
|
fn apply(&mut self, value: &dyn Property) {
|
|
self.set(value);
|
|
}
|
|
|
|
fn set(&mut self, value: &dyn Property) {
|
|
let value = value.any();
|
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
|
*self = prop.clone();
|
|
} else {
|
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
|
}
|
|
}
|
|
|
|
fn is_sequence(&self) -> bool {
|
|
true
|
|
}
|
|
}
|
|
}
|
|
};
|
|
(@$trait_:ident [$($args:ident,)*] where [$($preds:tt)+]) => {
|
|
impl_property! {
|
|
@as_item
|
|
impl<$($args),*> Property for $trait_<$($args),*> where $($args: ::std::any::Any + 'static,)*
|
|
$($preds)* {
|
|
#[inline]
|
|
fn type_name(&self) -> &str {
|
|
std::any::type_name::<Self>()
|
|
}
|
|
|
|
#[inline]
|
|
fn any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
#[inline]
|
|
fn any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
#[inline]
|
|
fn clone_prop(&self) -> Box<dyn Property> {
|
|
Box::new(self.clone())
|
|
}
|
|
|
|
#[inline]
|
|
fn apply(&mut self, value: &dyn Property) {
|
|
self.set(value);
|
|
}
|
|
|
|
fn set(&mut self, value: &dyn Property) {
|
|
let value = value.any();
|
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
|
*self = prop.clone();
|
|
} else {
|
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
(@as_item $i:item) => { $i };
|
|
|
|
(
|
|
SEQUENCE, $trait_:ident < $($args:ident),* $(,)* >
|
|
where $($preds:tt)+
|
|
) => {
|
|
impl_property! {SEQUENCE, @$trait_ [$($args,)*] where [$($preds)*] }
|
|
};
|
|
(
|
|
$trait_:ident < $($args:ident),* $(,)* >
|
|
where $($preds:tt)+
|
|
) => {
|
|
impl_property! { @$trait_ [$($args,)*] where [$($preds)*] }
|
|
};
|
|
} |