use std::{any::Any, collections::HashMap, str::FromStr, sync::Arc}; use futures_util::{future::LocalBoxFuture, FutureExt}; use giterated_models::{ object::GiteratedObject, operation::GiteratedOperation, settings::Setting, value::{GetValueTyped, GiteratedObjectValue}, }; use serde_json::Value; use tracing::trace; use crate::{ AnyFailure, AnyObject, AnyOperation, AnySetting, AnySuccess, AnyValue, GiteratedStack, ObjectOperationPair, ObjectSettingPair, ObjectValuePair, StackOperationState, }; /// Stores runtime metadata for all in-use Giterated protocol types. #[derive(Default)] pub struct RuntimeMetadata { pub objects: HashMap, pub operations: HashMap, OperationMeta>, pub values: HashMap, ValueMeta>, pub settings: HashMap, SettingMeta>, } impl RuntimeMetadata { pub fn register_object(&mut self) { let object_name = O::object_name().to_string(); let object_meta = ObjectMeta::new::(); if self.objects.insert(object_name, object_meta).is_some() { trace!( "Registration of object {} overwrote previous registration.", O::object_name() ); } else { trace!("Registration of object {}.", O::object_name()) } } pub fn register_operation + 'static>( &mut self, ) { let _object_name = O::object_name().to_string(); let _operation_name = D::operation_name().to_string(); if self .operations .insert( ObjectOperationPair::from_types::(), OperationMeta::new::(), ) .is_some() { trace!( "Registration of object operation {}<{}> overwrote previous registration.", D::operation_name(), O::object_name() ); } else { trace!( "Registration of object operation {}<{}>.", D::operation_name(), O::object_name() ) } } pub fn register_value< O: GiteratedObject + 'static, V: GiteratedObjectValue + 'static, >( &mut self, ) { let _object_name = O::object_name().to_string(); let _value_name = V::value_name().to_string(); if self .values .insert(ObjectValuePair::from_types::(), ValueMeta::new::()) .is_some() { trace!( "Registration of value <{}>::{} overwrote previous registration.", O::object_name(), V::value_name() ); } else { trace!( "Registration of value <{}>::{}.", O::object_name(), V::value_name() ); } } pub fn register_setting(&mut self) { if self .settings .insert( ObjectSettingPair::from_types::(), SettingMeta::new::(), ) .is_some() { trace!( "Registration of setting {} overwrote previous registration.", S::name() ); } else { trace!("Registration of setting {}.", S::name()); } } pub fn append(&mut self, other: Self) { self.objects.extend(other.objects); self.operations.extend(other.operations); self.values.extend(other.values); self.settings.extend(other.settings); } } pub struct ValueMeta { pub name: String, pub deserialize: fn(&[u8]) -> Result, pub serialize: fn(AnyValue) -> Result, serde_json::Error>, pub typed_get: fn() -> Box, pub is_get_value_typed: fn(AnyOperation) -> bool, } pub trait IntoValueMeta { fn name() -> String; fn deserialize(buffer: &[u8]) -> Result; fn serialize(value: AnyValue) -> Result, serde_json::Error>; fn typed_get() -> Box; fn is_get_value_typed(typed_get_value: AnyOperation) -> bool; } impl + 'static> IntoValueMeta for V { fn name() -> String { V::value_name().to_string() } fn deserialize(buffer: &[u8]) -> Result { Ok(AnyValue(Arc::new(serde_json::from_slice(buffer)?))) } fn serialize(value: AnyValue) -> Result, serde_json::Error> { let value = value.0.downcast_ref::().unwrap(); serde_json::to_vec(&*value) } fn typed_get() -> Box { Box::new(GetValueTyped:: { ty: Default::default(), }) } fn is_get_value_typed(typed_get_value: AnyOperation) -> bool { typed_get_value.0.is::>() } } impl ValueMeta { pub fn new() -> Self { Self { name: I::name(), deserialize: I::deserialize, serialize: I::serialize, typed_get: I::typed_get, is_get_value_typed: I::is_get_value_typed, } } } pub struct OperationMeta { pub name: String, pub object_kind: String, pub deserialize: fn(&[u8]) -> Result, pub any_is_same: fn(&dyn Any) -> bool, pub serialize_success: fn(AnySuccess) -> Result, serde_json::Error>, pub serialize_error: fn(AnyFailure) -> Result, serde_json::Error>, } pub trait IntoOperationMeta { fn name() -> String; fn deserialize(buffer: &[u8]) -> Result; fn serialize_success(success: AnySuccess) -> Result, serde_json::Error>; fn serialize_failure(failure: AnyFailure) -> Result, serde_json::Error>; fn any_is_same(other: &dyn Any) -> bool; } impl IntoOperationMeta for D where D::Failure: 'static, D::Success: 'static, O: GiteratedObject, D: GiteratedOperation + 'static, { fn name() -> String { D::operation_name().to_string() } fn deserialize(buffer: &[u8]) -> Result { Ok(AnyOperation( Arc::new(serde_json::from_slice::(buffer)?) as Arc )) } fn serialize_success(success: AnySuccess) -> Result, serde_json::Error> { let to_serialize = success.0.downcast_ref::().unwrap(); serde_json::to_vec(&to_serialize) } fn serialize_failure(failure: AnyFailure) -> Result, serde_json::Error> { let to_serialize = failure.0.downcast_ref::().unwrap(); serde_json::to_vec(&to_serialize) } fn any_is_same(other: &dyn Any) -> bool { other.is::() } } impl OperationMeta { pub fn new + 'static>() -> Self { Self { name: I::name(), deserialize: I::deserialize, serialize_success: I::serialize_success, serialize_error: I::serialize_failure, object_kind: O::object_name().to_string(), any_is_same: I::any_is_same, } } } pub struct ObjectMeta { pub name: String, pub from_str: Box Result + Send + Sync>, pub any_is_same: fn(&dyn Any) -> bool, } pub trait IntoObjectMeta: FromStr { fn name() -> String; fn any_is_same(other: &dyn Any) -> bool; } impl IntoObjectMeta for O { fn name() -> String { O::object_name().to_string() } fn any_is_same(other: &dyn Any) -> bool { other.is::() } } impl ObjectMeta { pub fn new() -> Self { Self { name: I::name(), from_str: Box::new(|source| { let object = I::from_str(source).map_err(|_| ())?; Ok(AnyObject(Arc::new(object) as Arc)) }), any_is_same: I::any_is_same, } } } pub struct SettingMeta { pub name: String, pub deserialize: fn(Value) -> Result, pub serialize: fn(AnySetting) -> Result, pub setting_updated: for<'fut> fn( AnyObject, AnySetting, Arc, &StackOperationState, ) -> LocalBoxFuture<'_, ()>, } pub trait IntoSettingMeta { fn name() -> String; fn deserialize(value: Value) -> Result; fn serialize(setting: AnySetting) -> Result; fn setting_updated( object: AnyObject, setting: AnySetting, stack: Arc, operation_state: &StackOperationState, ) -> LocalBoxFuture<'_, ()>; } impl IntoSettingMeta for S { fn name() -> String { S::name().to_string() } fn deserialize(value: Value) -> Result { Ok(AnySetting(Arc::new(serde_json::from_value::(value)?))) } fn serialize(setting: AnySetting) -> Result { serde_json::to_value(setting.0.downcast_ref::().unwrap()) } fn setting_updated( object: AnyObject, setting: AnySetting, stack: Arc, operation_state: &StackOperationState, ) -> LocalBoxFuture<'_, ()> { async move { stack .setting_update( object.0.downcast_ref::().unwrap().clone(), setting.0.downcast_ref::().unwrap().clone(), operation_state, ) .await } .boxed_local() } } impl SettingMeta { pub fn new + 'static>() -> Self { Self { name: I::name(), deserialize: I::deserialize, serialize: I::serialize, setting_updated: I::setting_updated, } } }