use std::{any::Any, 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 crate::{GiteratedStack, StackOperationState}; pub struct ValueMeta { pub name: String, pub deserialize: fn(&[u8]) -> Result, serde_json::Error>, pub serialize: fn(Box) -> Result, serde_json::Error>, pub typed_get: fn() -> Box, pub is_get_value_typed: fn(&Box) -> bool, } 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(); 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: 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, serde_json::Error>, pub any_is_same: fn(&dyn Any) -> bool, pub serialize_success: fn(Box) -> Result, serde_json::Error>, pub serialize_error: fn(Box) -> Result, serde_json::Error>, } 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: 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(Box::new(object) as Box) }), any_is_same: I::any_is_same, } } } pub struct SettingMeta { pub name: String, pub deserialize: fn(Value) -> Result, serde_json::Error>, pub serialize: fn(&(dyn Any + Send + Sync)) -> Result, pub setting_updated: for<'fut> fn( Box, Box, Arc, &StackOperationState, ) -> LocalBoxFuture<'_, ()>, } pub trait IntoSettingMeta { fn name() -> String; fn deserialize(value: Value) -> Result, serde_json::Error>; fn serialize(setting: &(dyn Any + Send + Sync)) -> Result; fn setting_updated( object: Box, setting: Box, stack: Arc, operation_state: &StackOperationState, ) -> LocalBoxFuture<'_, ()>; } impl IntoSettingMeta for S { fn name() -> String { S::name().to_string() } fn deserialize(value: Value) -> Result, serde_json::Error> { Ok(Box::new(serde_json::from_value::(value)?)) } fn serialize(setting: &(dyn Any + Send + Sync)) -> Result { serde_json::to_value(setting.downcast_ref::().unwrap()) } fn setting_updated( object: Box, setting: Box, stack: Arc, operation_state: &StackOperationState, ) -> LocalBoxFuture<'_, ()> { async move { stack .setting_update( *object.downcast::().unwrap(), *setting.downcast::().unwrap(), 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, } } }