diff --git a/giterated-stack/src/handler.rs b/giterated-stack/src/handler.rs index 9e56b23..df1fa11 100644 --- a/giterated-stack/src/handler.rs +++ b/giterated-stack/src/handler.rs @@ -14,8 +14,8 @@ use giterated_models::{ settings::{GetSetting, GetSettingError, SetSetting, Setting}, value::{AnyValue, GetValue, GetValueTyped, GiteratedObjectValue}, }; -use serde_json::Value; -use tracing::{info, trace}; + +use tracing::trace; use crate::{ GiteratedOperationHandler, ObjectMeta, ObjectOperationPair, ObjectValuePair, OperationMeta, @@ -315,11 +315,7 @@ impl RuntimeMetadata { fn register_object(&mut self) { let object_name = O::object_name().to_string(); - let object_meta = ObjectMeta { - name: object_name.clone(), - from_str: Box::new(|str| Ok(Box::new(O::from_str(&str).map_err(|_| ())?))), - any_is_same: Box::new(|any| any.is::()), - }; + let object_meta = ObjectMeta::new::(); if self.objects.insert(object_name, object_meta).is_some() { trace!( @@ -344,23 +340,7 @@ impl RuntimeMetadata { object_name: object_name.clone(), operation_name: operation_name.clone(), }, - OperationMeta { - name: operation_name, - object_kind: object_name, - deserialize: Box::new(|bytes| { - Ok(Box::new(serde_json::from_slice::(bytes)?) - as Box) - }), - any_is_same: Box::new(|any_box| any_box.is::()), - serialize_success: Box::new(|any| { - let to_serialize = any.downcast::().unwrap(); - serde_json::to_vec(&to_serialize) - }), - serialize_error: Box::new(|any| { - let to_serialize = any.downcast::().unwrap(); - serde_json::to_vec(&to_serialize) - }), - }, + OperationMeta::new::(), ) .is_some() { @@ -386,7 +366,6 @@ impl RuntimeMetadata { ) { let object_name = O::object_name().to_string(); let value_name = V::value_name().to_string(); - let value_name_for_get = V::value_name().to_string(); if self .values @@ -395,22 +374,7 @@ impl RuntimeMetadata { object_kind: object_name.clone(), value_kind: value_name.clone(), }, - ValueMeta { - name: value_name.clone(), - deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(&bytes)?))), - serialize: Box::new(|value| { - let value = value.downcast::().unwrap(); - - Ok(serde_json::to_vec(&*value)?) - }), - typed_get: Box::new(move || { - Box::new(GetValueTyped:: { - value_name: value_name_for_get.clone(), - ty: Default::default(), - }) - }), - is_get_value_typed: Box::new(move |typed| typed.is::>()), - }, + ValueMeta::new::(), ) .is_some() { @@ -433,14 +397,7 @@ impl RuntimeMetadata { if self .settings - .insert( - setting_name.clone(), - SettingMeta { - name: setting_name, - deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(bytes)?))), - serialize: Box::new(|source| Ok(*source.downcast::().unwrap())), - }, - ) + .insert(setting_name.clone(), SettingMeta::new::()) .is_some() { trace!( @@ -499,20 +456,16 @@ impl GiteratedStack { .await; } else if message.operation == "get_setting" { let operation: GetSetting = serde_json::from_slice(&message.payload.0).unwrap(); - info!("1"); let setting_meta = self .metadata .settings .get(&operation.setting_name) .ok_or_else(|| OperationError::Unhandled)?; - info!("2"); let raw_result = self .get_setting(object, object_type.clone(), operation, operation_state) .await; - info!("3"); return match raw_result { Ok(success) => { - info!("3a"); // Success is the setting type, serialize it let serialized = (setting_meta.serialize)(success).unwrap(); @@ -520,7 +473,6 @@ impl GiteratedStack { } Err(err) => Err(match err { OperationError::Operation(failure) => { - info!("3b"); // We know how to resolve this type let failure: GetSettingError = *failure.downcast().unwrap(); @@ -703,23 +655,6 @@ impl ObjectBackend for Arc { let object = Box::new(in_object.clone()) as Box; let operation = Box::new(payload) as Box; - // We need to determine the type of the object, iterate through all known - // object types and check if the &dyn Any we have is the same type as the - // object type. - let object_type = { - let mut object_type = None; - - for (object_name, object_meta) in self.metadata.objects.iter() { - if (object_meta.any_is_same)(&in_object) { - object_type = Some(object_name.clone()); - break; - } - } - - object_type - } - .ok_or_else(|| OperationError::Unhandled)?; - // We need to hijack get_value, set_setting, and get_setting. if operation_name == "get_value" { let mut value_meta = None; @@ -734,10 +669,14 @@ impl ObjectBackend for Arc { let value_name = value_meta.name.clone(); - trace!("Handling get_value for {}::{}", object_type, value_name); + trace!( + "Handling get_value for {}::{}", + O::object_name(), + value_name + ); for (target, getter) in self.value_getters.iter() { - if target.object_kind != object_type { + if target.object_kind != O::object_name() { continue; } @@ -763,16 +702,14 @@ impl ObjectBackend for Arc { return Err(OperationError::Unhandled); } else if operation.is::() { let get_setting: Box = operation.downcast().unwrap(); - let _setting_name = get_setting.setting_name.clone(); - - let _setting_meta = self - .metadata - .settings - .get(&object_type) - .ok_or_else(|| OperationError::Unhandled)?; let raw_result = self - .get_setting(object, object_type.clone(), *get_setting, operation_state) + .get_setting( + object, + O::object_name().to_string(), + *get_setting, + operation_state, + ) .await; return match raw_result { @@ -804,7 +741,7 @@ impl ObjectBackend for Arc { for (target, operation_meta) in self.metadata.operations.iter() { // Skip elements that we know will not match - if target.object_name != object_type { + if target.object_name != O::object_name() { continue; } diff --git a/giterated-stack/src/lib.rs b/giterated-stack/src/lib.rs index 9240e93..2ba5444 100644 --- a/giterated-stack/src/lib.rs +++ b/giterated-stack/src/lib.rs @@ -1,7 +1,7 @@ mod handler; +mod meta; pub use handler::{GiteratedStack, GiteratedStackState, *}; -use serde_json::Value; - +pub use meta::*; pub mod state; pub mod update; @@ -30,40 +30,6 @@ struct ObjectOperationPair { pub operation_name: String, } -pub struct SettingMeta { - pub name: String, - pub deserialize: Box Result, serde_json::Error> + Send + Sync>, - pub serialize: - Box) -> Result + Send + Sync>, -} - -pub struct ValueMeta { - pub name: String, - pub deserialize: Box Result, serde_json::Error> + Send + Sync>, - pub serialize: - Box) -> Result, serde_json::Error> + Send + Sync>, - pub typed_get: Box Box + Send + Sync>, - pub is_get_value_typed: Box) -> bool + Send + Sync>, -} - -pub struct ObjectMeta { - pub name: String, - pub from_str: Box Result, ()> + Send + Sync>, - pub any_is_same: Box bool + Send + Sync>, -} - -pub struct OperationMeta { - pub name: String, - pub object_kind: String, - pub deserialize: - Box Result, serde_json::Error> + Send + Sync>, - pub any_is_same: Box bool + Send + Sync>, - pub serialize_success: - Box) -> Result, serde_json::Error> + Send + Sync>, - pub serialize_error: - Box) -> Result, serde_json::Error> + Send + Sync>, -} - #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct ObjectValuePair { pub object_kind: String, diff --git a/giterated-stack/src/meta/mod.rs b/giterated-stack/src/meta/mod.rs new file mode 100644 index 0000000..562e0ab --- /dev/null +++ b/giterated-stack/src/meta/mod.rs @@ -0,0 +1,200 @@ +use std::{any::Any, str::FromStr}; + +use giterated_models::{ + object::GiteratedObject, + operation::GiteratedOperation, + settings::Setting, + value::{GetValueTyped, GiteratedObjectValue}, +}; +use serde_json::Value; + +pub struct ValueMeta { + pub name: String, + pub deserialize: Box Result, serde_json::Error> + Send + Sync>, + pub serialize: + Box) -> Result, serde_json::Error> + Send + Sync>, + pub typed_get: Box Box + Send + Sync>, + pub is_get_value_typed: Box) -> bool + Send + Sync>, +} + +pub trait IntoValueMeta { + fn name() -> String; + fn deserialize(buffer: &[u8]) -> Result, serde_json::Error>; + fn serialize(value: Box) -> Result, serde_json::Error>; + fn typed_get() -> Box; + fn is_get_value_typed(typed_get_value: &Box) -> bool; +} + +impl + 'static> IntoValueMeta for V { + fn name() -> String { + V::value_name().to_string() + } + + fn deserialize(buffer: &[u8]) -> Result, serde_json::Error> { + Ok(Box::new(serde_json::from_slice(&buffer)?)) + } + + fn serialize(value: Box) -> Result, serde_json::Error> { + let value = value.downcast::().unwrap(); + + Ok(serde_json::to_vec(&*value)?) + } + + fn typed_get() -> Box { + Box::new(GetValueTyped:: { + value_name: V::value_name().to_string(), + ty: Default::default(), + }) + } + + fn is_get_value_typed(typed_get_value: &Box) -> bool { + typed_get_value.is::>() + } +} + +impl ValueMeta { + pub fn new() -> Self { + Self { + name: I::name(), + deserialize: Box::new(I::deserialize) as _, + serialize: Box::new(I::serialize) as _, + typed_get: Box::new(I::typed_get) as _, + is_get_value_typed: Box::new(I::is_get_value_typed) as _, + } + } +} + +pub struct OperationMeta { + pub name: String, + pub object_kind: String, + pub deserialize: + Box Result, serde_json::Error> + Send + Sync>, + pub any_is_same: Box bool + Send + Sync>, + pub serialize_success: + Box) -> Result, serde_json::Error> + Send + Sync>, + pub serialize_error: + Box) -> Result, serde_json::Error> + Send + Sync>, +} + +pub trait IntoOperationMeta { + fn name() -> String; + fn deserialize(buffer: &[u8]) -> Result, serde_json::Error>; + fn serialize_success(success: Box) -> Result, serde_json::Error>; + fn serialize_failure(failure: Box) -> 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, serde_json::Error> { + Ok(Box::new(serde_json::from_slice::(buffer)?) as Box) + } + + fn serialize_success(success: Box) -> Result, serde_json::Error> { + let to_serialize = success.downcast::().unwrap(); + serde_json::to_vec(&to_serialize) + } + + fn serialize_failure(failure: Box) -> Result, serde_json::Error> { + let to_serialize = failure.downcast::().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: Box::new(I::deserialize) as _, + serialize_success: Box::new(I::serialize_success) as _, + serialize_error: Box::new(I::serialize_failure) as _, + object_kind: O::object_name().to_string(), + any_is_same: Box::new(I::any_is_same) as _, + } + } +} + +pub struct ObjectMeta { + pub name: String, + pub from_str: Box Result, ()> + Send + Sync>, + pub any_is_same: Box bool + Send + Sync>, +} + +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(Box::new(object) as Box) + }), + any_is_same: Box::new(I::any_is_same) as _, + } + } +} + +pub struct SettingMeta { + pub name: String, + pub deserialize: Box Result, serde_json::Error> + Send + Sync>, + pub serialize: + Box) -> Result + Send + Sync>, +} + +pub trait IntoSettingMeta { + fn name() -> String; + fn deserialize(buffer: &[u8]) -> Result, serde_json::Error>; + fn serialize(setting: Box) -> Result; +} + +impl IntoSettingMeta for S { + fn name() -> String { + S::name().to_string() + } + + fn deserialize(buffer: &[u8]) -> Result, serde_json::Error> { + Ok(Box::new(serde_json::from_slice(buffer)?)) + } + + fn serialize(setting: Box) -> Result { + Ok(*setting.downcast::().unwrap()) + } +} + +impl SettingMeta { + pub fn new() -> Self { + Self { + name: I::name(), + deserialize: Box::new(I::deserialize) as _, + serialize: Box::new(I::serialize) as _, + } + } +}