use erased_serde::{Deserializer, Serialize, Serializer};
use serde::de::DeserializeOwned;
use std::any::{Any, TypeId};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use crate::core::ItemID;
pub trait EntityTrait: Send + Sync + Any {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn to_json_value(&self) -> Result<serde_json::Value, serde_json::Error>;
fn deserialize(
&mut self,
de: &mut dyn erased_serde::Deserializer,
) -> Result<(), erased_serde::Error>;
}
impl<T> EntityTrait for T
where
T: Send + Sync + Any + Serialize + DeserializeOwned,
{
fn as_any(&self) -> &dyn Any {
self as &dyn Any
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self as &mut dyn Any
}
fn deserialize(
&mut self,
de: &mut dyn erased_serde::Deserializer,
) -> Result<(), erased_serde::Error> {
*self = T::deserialize(de)?;
Ok(())
}
fn to_json_value(&self) -> Result<serde_json::Value, serde_json::Error> {
serde_json::to_value(self as &dyn erased_serde::Serialize)
}
}
pub struct Metadata {
pub name: &'static str,
pub type_id: TypeId,
pub v_default: Arc<dyn EntityTrait>,
pub v_min: Option<Box<dyn EntityTrait>>,
pub v_max: Option<Box<dyn EntityTrait>>,
pub v_one_of: Vec<Box<dyn EntityTrait>>,
pub props: MetadataProps,
pub fn_default: Box<dyn Fn() -> Box<dyn EntityTrait> + Send + Sync>,
pub fn_copy_to: fn(&dyn Any, &mut dyn Any),
pub fn_serialize_to: fn(&dyn Any, &mut dyn Serializer) -> Result<(), erased_serde::Error>,
pub fn_deserialize_from:
fn(&mut dyn Any, &mut dyn Deserializer) -> Result<(), erased_serde::Error>,
pub fn_validate: fn(&Metadata, &mut dyn Any) -> Option<bool>,
}
pub struct MetadataValInit<T> {
pub v_default: T,
pub v_min: Option<T>,
pub v_max: Option<T>,
pub v_one_of: Vec<T>,
pub fn_validate: fn(&Metadata, &mut dyn Any) -> Option<bool>,
}
#[derive(Debug)]
pub struct MetadataProps {
pub disable_export: bool,
pub disable_import: bool,
pub hidden: bool,
pub schema: Option<crate::Schema>,
pub varname: &'static str,
pub description: &'static str,
}
pub mod lookups {
pub trait HasSchema {
fn get_schema(&self) -> Option<crate::Schema>;
}
impl<T: schemars::JsonSchema> HasSchema for T {
fn get_schema(&self) -> Option<crate::Schema> {
Some(schemars::schema_for!(T))
}
}
pub trait NoSchema {
fn get_schema(&self) -> Option<crate::Schema> {
None
}
}
trait AnyType {}
impl<T> AnyType for T {}
impl<T: AnyType> NoSchema for &T {}
}
impl Metadata {
pub fn create_for_base_type<T>(
name: &'static str,
init: MetadataValInit<T>,
props: MetadataProps,
) -> Self
where
T: EntityTrait + Clone + serde::de::DeserializeOwned + serde::ser::Serialize,
{
let retrive_opt_minmax = |val| {
if let Some(v) = val {
Some(Box::new(v) as Box<dyn EntityTrait>)
} else {
None
}
};
let v_min = retrive_opt_minmax(init.v_min);
let v_max = retrive_opt_minmax(init.v_max);
let v_one_of: Vec<_> = init
.v_one_of
.iter()
.map(|v| Box::new(v.clone()) as Box<dyn EntityTrait>)
.collect();
Self {
name,
type_id: TypeId::of::<T>(),
v_default: Arc::new(init.v_default.clone()),
v_min,
v_max,
v_one_of,
props,
fn_default: Box::new(move || Box::new(init.v_default.clone())),
fn_copy_to: |from, to| {
let from: &T = from.downcast_ref().unwrap();
let to: &mut T = to.downcast_mut().unwrap();
*to = from.clone();
},
fn_serialize_to: |from, to| {
let from: &T = from.downcast_ref().unwrap();
from.erased_serialize(to)?;
Ok(())
},
fn_deserialize_from: |to, from| {
let to: &mut T = to.downcast_mut().unwrap();
*to = erased_serde::deserialize(from)?;
Ok(())
},
fn_validate: init.fn_validate,
}
}
}
pub mod gen_helper {
use std::any::Any;
use crate::entity::Metadata;
pub fn validate_min_max<T: 'static + Clone + Ord>(meta: &Metadata, val: &mut dyn Any) -> bool {
let to: &mut T = val.downcast_mut().unwrap();
let mut was_in_range = true;
if let Some(val) = &meta.v_min {
let from: &T = val.as_any().downcast_ref().unwrap();
if *to < *from {
was_in_range = false;
*to = from.clone();
}
}
if let Some(val) = &meta.v_max {
let from: &T = val.as_any().downcast_ref().unwrap();
if *from < *to {
was_in_range = false;
*to = from.clone();
}
}
was_in_range
}
pub fn verify_one_of<T: 'static + Eq>(meta: &Metadata, val: &dyn Any) -> bool {
if meta.v_one_of.is_empty() {
return true;
}
let to: &T = val.downcast_ref().unwrap();
meta.v_one_of
.iter()
.map(|v| v.as_any().downcast_ref::<T>().unwrap())
.any(|v| *v == *to)
}
}
pub struct EntityData {
id: ItemID,
meta: Arc<Metadata>,
fence: AtomicUsize,
value: Mutex<Arc<dyn EntityTrait>>,
hook: Arc<dyn EntityEventHook>,
}
impl EntityData {
pub(crate) fn new(meta: Arc<Metadata>, hook: Arc<dyn EntityEventHook>) -> Self {
Self {
id: ItemID::new_unique(),
fence: AtomicUsize::new(0), value: Mutex::new(meta.v_default.clone()),
meta,
hook,
}
}
pub fn get_id(&self) -> ItemID {
self.id
}
pub fn get_meta(&self) -> &Arc<Metadata> {
&self.meta
}
pub fn get_update_fence(&self) -> usize {
self.fence.load(Ordering::Relaxed)
}
pub fn get_value(&self) -> (&Arc<Metadata>, Arc<dyn EntityTrait>) {
(&self.meta, self.value.lock().unwrap().clone())
}
pub fn __apply_value(&self, value: Arc<dyn EntityTrait>) {
debug_assert!(self.meta.type_id == value.as_any().type_id());
{
let mut lock = self.value.lock().unwrap();
*lock = value;
self.fence.fetch_add(1, Ordering::Release);
}
}
pub fn update_value_from<'a, T>(&self, de: T) -> Result<bool, crate::core::Error>
where
T: serde::Deserializer<'a>,
{
let meta = &self.meta;
let mut erased = <dyn erased_serde::Deserializer>::erase(de);
let mut built = (meta.fn_default)();
match built.deserialize(&mut erased) {
Ok(_) => {
let clean = match (meta.fn_validate)(&*meta, built.as_any_mut()) {
Some(clean) => clean,
None => return Err(crate::core::Error::ValueValidationFailed),
};
let built: Arc<dyn EntityTrait> = built.into();
self.__apply_value(built);
Ok(clean)
}
Err(e) => {
log::error!(
"(Deserialization Failed) {}(var:{}) \n\nERROR: {e:#?}",
meta.name,
meta.props.varname,
);
Err(e.into())
}
}
}
pub fn __notify_value_change(&self, make_storage_dirty: bool) {
self.hook.on_value_changed(self, !make_storage_dirty);
}
}
pub(crate) trait EntityEventHook: Send + Sync {
fn on_value_changed(&self, data: &EntityData, silent: bool);
}