use futures_util::{future::BoxFuture, FutureExt}; use giterated_models::{ object::GiteratedObject, settings::{AnySetting, Setting}, value::{AnyValue, GiteratedObjectValue}, }; use crate::StackOperationState; #[async_trait::async_trait] pub trait HandleValueUpdate> { async fn handle_value_update( &mut self, object: O, value_name: String, value: V, operation_state: &StackOperationState, ) -> Result<(), ()>; } #[async_trait::async_trait] impl HandleValueUpdate for F where F: Fn(O, String, V, &StackOperationState) -> BoxFuture<'static, Result<(), ()>> + Send + Sync, O: GiteratedObject + Send + Sync + 'static, V: GiteratedObjectValue + Send + Sync + 'static, { async fn handle_value_update( &mut self, object: O, value_name: String, value: V, operation_state: &StackOperationState, ) -> Result<(), ()> { self(object, value_name, value, operation_state).await } } #[async_trait::async_trait] pub trait HandleSettingUpdate { async fn handle_setting_update( &mut self, object: O, setting_name: String, setting: S, operation_state: &StackOperationState, ) -> Result<(), ()>; } #[async_trait::async_trait] impl HandleSettingUpdate for F where F: Fn(O, String, S, &StackOperationState) -> BoxFuture<'static, Result<(), ()>> + Send + Sync, O: GiteratedObject + Send + Sync + 'static, S: Setting + Send + Sync + 'static, { async fn handle_setting_update( &mut self, object: O, setting_name: String, setting: S, operation_state: &StackOperationState, ) -> Result<(), ()> { self(object, setting_name, setting, operation_state).await } } #[async_trait::async_trait] pub trait ValueUpdatedHandler { async fn value_updated(&mut self, object: &O, value_name: &str, value: AnyValue<()>); } #[async_trait::async_trait] pub trait SettingUpdatedHandler { async fn setting_updated(&mut self, object: &O, setting_name: &str, setting: AnySetting); } #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct ValueUpdateKind { pub object_kind: String, pub value_name: String, } #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct SettingUpdateKind { pub object_kind: String, pub setting_name: String, } pub struct HandleSettingUpdatedFunction { pub target: SettingUpdateKind, pub function: Box< dyn FnOnce( String, String, AnySetting, StackOperationState, ) -> BoxFuture<'static, Result<(), ()>> + Send + Sync, >, } impl HandleSettingUpdatedFunction { pub fn new< S: Setting + Send + Sync, T: HandleSettingUpdate + 'static + Clone + Send + Sync, O: GiteratedObject + Send + Sync, >( handler: T, setting_name: &str, ) -> Self { Self { target: SettingUpdateKind { object_kind: O::object_name().to_string(), setting_name: setting_name.to_string(), }, function: Box::new(move |object, setting_name, value, state| { async move { let mut handler = handler; let object = match O::from_str(&object) { Ok(object) => object, Err(_) => return Err(()), }; let setting: S = serde_json::from_value(value.0).unwrap(); let _ = handler .handle_setting_update(object, setting_name, setting, &state) .await; Ok(()) } .boxed() }), } } } pub struct HandleValueUpdatedFunction { pub target: ValueUpdateKind, pub function: Box< dyn FnOnce( String, String, AnySetting, StackOperationState, ) -> BoxFuture<'static, Result<(), ()>> + Send + Sync, >, } impl HandleValueUpdatedFunction { pub fn new< V: GiteratedObjectValue + Send + Sync, T: HandleValueUpdate + 'static + Clone + Send + Sync, O: GiteratedObject + Send + Sync, >( handler: T, value_name: &str, ) -> Self { Self { target: ValueUpdateKind { object_kind: O::object_name().to_string(), value_name: value_name.to_string(), }, function: Box::new(move |object, setting_name, value, state| { async move { let mut handler = handler; let object = match O::from_str(&object) { Ok(object) => object, Err(_) => return Err(()), }; let setting: V = serde_json::from_value(value.0).unwrap(); let _ = handler .handle_value_update(object, setting_name, setting, &state) .await; Ok(()) } .boxed() }), } } }