use std::{any::Any, collections::HashMap, str::FromStr, sync::Arc}; use futures_util::{future::LocalBoxFuture, FutureExt}; use giterated_models::{ object::GiteratedObject, operation::GiteratedOperation, settings::{SetSetting, Setting}, value::{GetValue, 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, ) { 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() ); } self.operations.insert( ObjectOperationPair::from_types::(), OperationMeta::new::(), ); } 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()); } self.operations.insert( ObjectOperationPair::from_types::(), OperationMeta::new::(), ); } 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::new(serde_json::from_slice::(buffer)?)) } fn serialize(value: AnyValue) -> Result, serde_json::Error> { let value = value.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.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 serialize: fn(AnyOperation) -> Result, serde_json::Error>, 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 deserialize_success: fn(Vec) -> Result, pub deserialize_failure: fn(Vec) -> Result, } 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 deserialize_success(success: Vec) -> Result; fn deserialize_failure(failure: Vec) -> Result; fn any_is_same(other: &dyn Any) -> bool; fn serialize(operation: AnyOperation) -> Result, serde_json::Error>; } impl IntoOperationMeta for D where D::Failure: 'static, D::Success: 'static, O: GiteratedObject + 'static, D: GiteratedOperation + 'static, { fn name() -> String { D::operation_name().to_string() } fn deserialize(buffer: &[u8]) -> Result { Ok(AnyOperation::new(serde_json::from_slice::(buffer)?)) } 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::() } fn serialize(operation: AnyOperation) -> Result, serde_json::Error> { let operation: &D = operation.downcast_ref().unwrap(); serde_json::to_vec(operation) } fn deserialize_success(success: Vec) -> Result { let success: D::Success = serde_json::from_slice(&success)?; Ok(AnySuccess(Arc::new(success))) } fn deserialize_failure(failure: Vec) -> Result { let failure: D::Failure = serde_json::from_slice(&failure)?; Ok(AnyFailure(Arc::new(failure))) } } 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, serialize: I::serialize, deserialize_success: I::deserialize_success, deserialize_failure: I::deserialize_failure, } } } pub struct ObjectMeta { pub name: String, pub to_str: Box String + Send + Sync>, pub from_str: Box Result + Send + Sync>, pub home_uri: fn(AnyObject) -> String, pub any_is_same: fn(&dyn Any) -> bool, } pub trait IntoObjectMeta: FromStr { fn name() -> String; fn any_is_same(other: &dyn Any) -> bool; fn home_uri(object: AnyObject) -> String; } impl IntoObjectMeta for O { fn name() -> String { O::object_name().to_string() } fn any_is_same(other: &dyn Any) -> bool { other.is::() } fn home_uri(object: AnyObject) -> String { let object: &O = object.downcast_ref().unwrap(); object.home_uri() } } 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::new(object)) }), to_str: Box::new(|source| { let object: &I = source.downcast_ref().unwrap(); object.to_string() }), any_is_same: I::any_is_same, home_uri: ::home_uri, } } } pub struct SettingMeta { pub name: String, pub deserialize: fn(Value) -> Result, pub serialize: fn(AnySetting) -> Result, pub setting_updated: for<'fut> fn( AnyObject, AnySetting, GiteratedStack, &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: GiteratedStack, operation_state: &StackOperationState, ) -> LocalBoxFuture<'_, ()>; } impl IntoSettingMeta for S { fn name() -> String { S::name().to_string() } fn deserialize(value: Value) -> Result { Ok(AnySetting::new::(serde_json::from_value::(value)?)) } fn serialize(setting: AnySetting) -> Result { serde_json::to_value(setting.downcast_ref::().unwrap()) } fn setting_updated( object: AnyObject, setting: AnySetting, stack: GiteratedStack, operation_state: &StackOperationState, ) -> LocalBoxFuture<'_, ()> { async move { stack .setting_update( object.downcast_ref::().unwrap().clone(), setting.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, } } }