use std::{any::Any, collections::HashMap, sync::Arc}; use futures_util::FutureExt; use giterated_models::{ authenticated::AuthenticatedPayload, error::{GetValueError, IntoInternalError, OperationError}, instance::Instance, message::GiteratedMessage, object::{ AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse, }, object_backend::ObjectBackend, operation::{AnyOperation, GiteratedOperation}, settings::{GetSetting, GetSettingError, SetSetting, Setting}, value::{AnyValue, GetValue, GetValueTyped, GiteratedObjectValue}, }; use serde::{Deserialize, Serialize}; use tracing::trace; use crate::{ provider::MetadataProvider, GiteratedOperationHandler, MissingValue, ObjectMeta, ObjectOperationPair, ObjectSettingPair, ObjectValuePair, OperationMeta, OperationWrapper, SettingMeta, SettingUpdate, StackOperationState, ValueMeta, }; /// Temporary name for the next generation of Giterated stack #[derive(Default)] pub struct GiteratedStack { operation_handlers: HashMap, value_getters: HashMap, setting_getters: HashMap, value_change: HashMap, setting_change: HashMap, metadata_providers: Vec>, metadata: RuntimeMetadata, } impl Debug for GiteratedStack { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("GiteratedStack").finish() } } #[derive(Clone)] pub struct ValueChangeEvent(Arc); impl GiteratedStack { pub fn merge_builder( &mut self, mut builder: SubstackBuilder, ) -> &mut Self { for (target, handler) in builder.operation_handlers { let tree = self.get_or_create_tree(&target); tree.push(handler); } for (target, handler) in builder.value_getters { assert!(self.value_getters.insert(target, handler).is_none()); } for (target, handler) in builder.setting_getters { assert!(self.setting_getters.insert(target, handler).is_none()); } for (target, handler) in builder.value_change { self.value_change.insert(target, handler); } for (target, handler) in builder.setting_change { self.setting_change.insert(target, handler); } self.metadata_providers .append(&mut builder.metadata_providers); self.metadata.append(builder.metadata); self } pub async fn value_update( &self, object: O, new_value: V, operation_state: &StackOperationState, ) where O: GiteratedObject + 'static, V: GiteratedObjectValue + 'static, { trace!("value updated {}::{}", O::object_name(), V::value_name()); let target = ObjectValuePair::from_types::(); if let Some(handler) = self.value_change.get(&target) { // TODO let _ = handler .handle( &(Box::new(object) as _), &(Box::new(ValueChangedShim { new_value }) as _), operation_state, ) .await; } } pub async fn setting_update( &self, object: O, new_setting: S, operation_state: &StackOperationState, ) where O: GiteratedObject + 'static, S: Setting + 'static, { trace!("setting updated {}::{}", O::object_name(), S::name()); let target = ObjectSettingPair::from_types::(); if let Some(handler) = self.setting_change.get(&target) { let _ = handler .handle( &(Box::new(object) as _), &(Box::new(SettingUpdate(new_setting)) as _), operation_state, ) .await; } } pub async fn new_object(&self, _new_object: &O, _operation_state: &StackOperationState) where O: GiteratedObject, { // TODO } /// Writes a setting for the specified object. pub async fn write_setting( &self, object: &O, setting: S, ) -> Result<(), OperationError<()>> where O: GiteratedObject + 'static, S: Setting + 'static + Clone, { for provider in self.metadata_providers.iter() { if provider.provides_for(object as &dyn Any) { let setting_meta = self .metadata .settings .get(&ObjectSettingPair { object_kind: O::object_name().to_string(), setting_name: S::name().to_string(), }) .ok_or_else(|| OperationError::Unhandled)?; let object_meta = self .metadata .objects .get(O::object_name()) .ok_or_else(|| OperationError::Unhandled)?; let result = provider .write(object, object_meta, &setting, setting_meta) .await .as_internal_error_with_context(format!("writing setting {}", S::name())); return result; } } Err(OperationError::Unhandled) } /// Gets a setting for the specified object. pub async fn new_get_setting(&self, object: &O) -> Result> where O: GiteratedObject + 'static, S: Setting + 'static, { for provider in self.metadata_providers.iter() { if provider.provides_for(object as &dyn Any) { trace!( "Resolving setting {} for object {} from provider.", S::name(), O::object_name() ); let setting_meta = self .metadata .settings .get(&ObjectSettingPair { object_kind: O::object_name().to_string(), setting_name: S::name().to_string(), }) .ok_or_else(|| OperationError::Unhandled)?; let object_meta = self .metadata .objects .get(O::object_name()) .ok_or_else(|| OperationError::Unhandled)?; let value = provider .read(object, object_meta, setting_meta) .await .as_internal_error_with_context(format!("getting setting {}", S::name()))?; return serde_json::from_value(value) .as_internal_error_with_context("deserializing setting"); } } trace!( "No provider registered for setting {} and object {}", S::name(), O::object_name() ); Err(OperationError::Unhandled) } fn get_or_create_tree(&mut self, target: &ObjectOperationPair) -> &mut HandlerTree { if self.operation_handlers.contains_key(target) { self.operation_handlers.get_mut(target).unwrap() } else { self.operation_handlers .insert(target.clone(), HandlerTree::default()); self.operation_handlers.get_mut(target).unwrap() } } } #[derive(Default)] pub struct HandlerTree { elements: Vec, } impl HandlerTree { pub fn push(&mut self, handler: OperationWrapper) { self.elements.push(handler); } pub async fn handle( &self, object: &Box, operation: &Box, operation_state: &StackOperationState, ) -> Result, OperationError>> { for handler in self.elements.iter() { match handler.handle(object, operation, operation_state).await { Ok(success) => return Ok(success), Err(err) => match err { OperationError::Operation(failure) => { return Err(OperationError::Operation(failure)) } OperationError::Internal(e) => return Err(OperationError::Internal(e)), _ => { continue; } }, } } Err(OperationError::Unhandled) } } /// Stores runtime metadata for all in-use Giterated protocol types. #[derive(Default)] struct RuntimeMetadata { objects: HashMap, operations: HashMap, values: HashMap, settings: HashMap, } /// Defines a type that is a valid Giterated runtime state. /// /// This allows for extraction of state in handlers, based on a /// [`FromOperationState`] impl on (what is in this case) [`Self`]. pub trait GiteratedStackState: Send + Sync + Clone {} impl GiteratedStackState for T {} pub struct SubstackBuilder { operation_handlers: HashMap, value_getters: HashMap, setting_getters: HashMap, metadata: RuntimeMetadata, value_change: HashMap, metadata_providers: Vec>, setting_change: HashMap, state: S, } impl SubstackBuilder { pub fn new(state: S) -> Self { Self { operation_handlers: Default::default(), value_getters: Default::default(), setting_getters: Default::default(), metadata: Default::default(), value_change: Default::default(), metadata_providers: Default::default(), setting_change: Default::default(), state, } } } impl SubstackBuilder { /// Insert an operation handler into the runtime builder. /// /// # Type Registration /// Inserting the handler will automatically, if required, register the operation type of the /// handler. It will **not** register the object type automatically. pub fn operation(&mut self, handler: H) -> &mut Self where O: GiteratedObject + 'static, D: GiteratedOperation + 'static + Clone, H: GiteratedOperationHandler + 'static + Clone + Send + Sync, D::Failure: Send + Sync, D::Success: Send + Sync, { let object_name = handler.object_name().to_string(); let operation_name = handler.operation_name().to_string(); let wrapped = OperationWrapper::new(handler, self.state.clone()); let pair = ObjectOperationPair { object_name, operation_name, }; self.operation_handlers.insert(pair, wrapped); self.metadata.register_operation::(); self } /// Register a [`GiteratedObject`] type with the runtime. /// /// # Type Registration /// This will register the provided object type. pub fn object(&mut self) -> &mut Self { self.metadata.register_object::(); // Insert handler so ObjectRequest is handled properly let handler = move |_object: &Instance, operation: ObjectRequest, _state: S, _operation_state: StackOperationState, stack: Arc| { async move { for (_object_name, object_meta) in stack.metadata.objects.iter() { if (object_meta.from_str)(&operation.0).is_ok() { return Ok(ObjectResponse(operation.0)); } } Err(OperationError::Unhandled) } .boxed_local() }; self.operation(handler); self } /// Register a [`Setting`] type with the runtime. /// /// # Type Registration /// This will register the provided setting type. pub fn setting(&mut self) -> &mut Self { self.metadata.register_setting::(); self } /// Register a [`GiteratedObjectValue`] that is also a [`Setting`], which /// allows for automatic value updates. pub fn value_setting< O: GiteratedObject + 'static + Clone, T: GiteratedObjectValue + Setting + 'static + Clone, >( &mut self, ) -> &mut Self { self.metadata.register_setting::(); self.metadata.register_value::(); self.setting_change.insert( ObjectSettingPair { object_kind: O::object_name().to_string(), setting_name: T::name().to_string(), }, OperationWrapper::new( move |object: &O, setting: SettingUpdate, _state: (), operation_state: StackOperationState, stack: Arc| { trace!( "value setting updated {}::{}", O::object_name(), T::value_name() ); let object = object.clone(); async move { stack .value_update(object, setting.0, &operation_state) .await; Ok(()) } .boxed_local() }, (), ), ); let wrapped = OperationWrapper::new( |object: &O, operation: GetValueTyped, state: _, operation_state: StackOperationState, stack: Arc| { let object = object.clone(); async move { match stack .get_setting( Box::new(object.clone()) as _, O::object_name().to_string(), GetSetting { setting_name: T::name().to_string(), }, &operation_state, ) .await { Ok(setting) => Ok(*setting.downcast::().unwrap()), Err(err) => { panic!("Error: {:?}", err); } } } .boxed_local() }, self.state.clone(), ); self.value_getters.insert( ObjectValuePair { object_kind: O::object_name().to_string(), value_kind: T::value_name().to_string(), }, wrapped, ); self } /// Register a [`GiteratedObjectValue`] type with the runtime, providing /// its associated handler for [`GetValue`]. /// /// # Type Registration /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified /// object type. It will **not** register the object type automatically. pub fn value(&mut self, handler: F) -> &mut Self where O: GiteratedObject + 'static, V: GiteratedObjectValue + 'static + Clone, F: GiteratedOperationHandler, S> + Clone + 'static + Send + Sync, { let object_name = handler.object_name().to_string(); let value_name = V::value_name().to_string(); let wrapped = OperationWrapper::new(handler, self.state.clone()); let handler_object_name = object_name.clone(); let handler_value_name = value_name.clone(); // Insert handler so GetValue is handled properly let _handler = move |object: &O, operation: GetValueTyped>, _state: S, operation_state: StackOperationState, stack: Arc| { let stack = stack; let object_name = handler_object_name; let value_name = handler_value_name; let object = object.clone(); async move { for (target, getter) in stack.value_getters.iter() { if target.object_kind != object_name { continue; } if target.value_kind != value_name { continue; } return match getter .handle( &(Box::new(object.clone()) as Box), &(Box::new(GetValueTyped:: { value_name: operation.value_name, ty: Default::default(), }) as Box), &operation_state, ) .await { Ok(success) => Ok(*success.downcast::< as GiteratedOperation>::Success>().unwrap()), Err(err) => Err(match err { OperationError::Operation(failure) => OperationError::Operation(*failure.downcast::< as GiteratedOperation>::Failure>().unwrap()), OperationError::Internal(internal) => OperationError::Internal(internal), OperationError::Unhandled => OperationError::Unhandled, }), } } Err(OperationError::Unhandled) } .boxed_local() }; assert!(self .value_getters .insert( ObjectValuePair { object_kind: object_name, value_kind: value_name }, wrapped ) .is_none()); self.metadata.register_value::(); self } /// Register a handler for [`GetSetting`] for it's associated object type. pub fn object_settings(&mut self, handler: F) -> &mut Self where O: GiteratedObject + 'static, F: GiteratedOperationHandler + Clone + 'static + Send + Sync, { let object_name = handler.object_name().to_string(); let wrapped = OperationWrapper::new(handler, self.state.clone()); assert!(self.setting_getters.insert(object_name, wrapped).is_none()); self } pub fn value_change(&mut self, handler: F) -> &mut Self where O: GiteratedObject + 'static, F: GiteratedOperationHandler, S> + Clone + 'static + Send + Sync, V: GiteratedObjectValue + Clone + 'static, { let object_name = handler.object_name().to_string(); let wrapped = OperationWrapper::new(handler, self.state.clone()); assert!(self.setting_getters.insert(object_name, wrapped).is_none()); self } pub fn object_metadata_provider(&mut self, provider: Box) -> &mut Self { self.metadata_providers.push(provider); self } } #[derive(Serialize, Deserialize, Clone)] pub struct ValueChangedShim { new_value: V, } impl GiteratedOperation for ValueChangedShim where O: GiteratedObject, V: GiteratedObjectValue, { type Success = V; type Failure = MissingValue; } impl RuntimeMetadata { 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()) } } 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 { object_name: object_name, operation_name: operation_name, }, 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() ) } } 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 { object_kind: object_name, value_kind: value_name, }, 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() ); } } fn register_setting(&mut self) { if self .settings .insert( ObjectSettingPair { object_kind: O::object_name().to_string(), setting_name: S::name().to_string(), }, SettingMeta::new::(), ) .is_some() { trace!( "Registration of setting {} overwrote previous registration.", S::name() ); } else { trace!("Registration of setting {}.", S::name()); } } 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); } } impl GiteratedStack { /// Handles a giterated network message, returning either a raw success /// payload or a serialized error payload. pub async fn handle_network_message( &self, message: AuthenticatedPayload, operation_state: &StackOperationState, ) -> Result, OperationError>> { let message: GiteratedMessage = message.into_message(); // Deserialize the object, also getting the object type's name let (object_type, object) = { let mut result = None; for (object_type, object_meta) in self.metadata.objects.iter() { if let Ok(object) = (object_meta.from_str)(&message.object.0) { result = Some((object_type.clone(), object)); break; } } result } .ok_or_else(|| OperationError::Unhandled)?; trace!( "Handling network message {}::<{}>", message.operation, object_type ); if message.operation == "get_value" { // Special case let operation: GetValue = serde_json::from_slice(&message.payload.0).unwrap(); let result = self .network_get_value( object, object_type.clone(), operation.clone(), operation_state, ) .await; // In the case of internal errors, attach context let result = result.map_err(|err| match err { OperationError::Operation(operation) => OperationError::Operation(operation), OperationError::Internal(internal) => { OperationError::Internal(internal.context(format!( "{}::get_value::<{}> outcome", object_type, operation.value_name ))) } OperationError::Unhandled => OperationError::Unhandled, }); return result; } else if message.operation == "get_setting" { let operation: GetSetting = serde_json::from_slice(&message.payload.0).unwrap(); let setting_meta = self .metadata .settings .get(&ObjectSettingPair { object_kind: object_type.clone(), setting_name: operation.setting_name.clone(), }) .ok_or_else(|| OperationError::Unhandled)?; let raw_result = self .get_setting(object, object_type.clone(), operation, operation_state) .await; return match raw_result { Ok(success) => { // Success is the setting type, serialize it let serialized = (setting_meta.serialize)(&(*success)).unwrap(); Ok(serde_json::to_vec(&serialized).unwrap()) } Err(err) => Err(match err { OperationError::Operation(failure) => { // We know how to resolve this type let failure: GetSettingError = *failure.downcast().unwrap(); OperationError::Operation(serde_json::to_vec(&failure).unwrap()) } OperationError::Internal(internal) => { OperationError::Internal(internal.context(format!( "{}::get_setting::<{}> handler outcome", object_type, setting_meta.name ))) } OperationError::Unhandled => OperationError::Unhandled, }), }; } else if message.operation == "set_setting" { let operation: SetSetting = serde_json::from_slice(&message.payload.0).unwrap(); trace!( "Handling network {}::set_setting for {}", object_type, operation.setting_name ); let setting_meta = self .metadata .settings .get(&ObjectSettingPair { object_kind: object_type.clone(), setting_name: operation.setting_name.clone(), }) .unwrap(); let setting = (setting_meta.deserialize)(operation.value.0) .as_internal_error_with_context(format!( "deserializing setting {} for object {}", operation.setting_name, object_type ))?; trace!( "Deserialized setting {} for object {}", operation.setting_name, object_type, ); for provider in self.metadata_providers.iter() { if provider.provides_for(object.as_ref()) { trace!( "Resolved setting provider for setting {} for object {}", operation.setting_name, object_type, ); let object_meta = self .metadata .objects .get(&object_type) .ok_or_else(|| OperationError::Unhandled)?; let raw_result = provider .write(&(*object), object_meta, &(*setting), setting_meta) .await; return match raw_result { Ok(_) => { (setting_meta.setting_updated)( object, setting, operation_state.runtime.clone(), operation_state, ) .await; Ok(serde_json::to_vec(&()).unwrap()) } Err(e) => Err(OperationError::Internal(e.context(format!( "writing object {} setting {}", object_type, operation.setting_name )))), }; } trace!( "Failed to resolve setting provider for setting {} for object {}", operation.setting_name, object_type, ); } } let target = ObjectOperationPair { object_name: object_type.clone(), operation_name: message.operation.clone(), }; // Resolve the target operations from the handlers table let handler = self .operation_handlers .get(&target) .ok_or_else(|| OperationError::Unhandled)?; trace!( "Resolved operation handler for network message {}::<{}>", message.operation, object_type ); // Deserialize the operation let meta = self .metadata .operations .get(&target) .ok_or_else(|| OperationError::Unhandled)?; let operation = (meta.deserialize)(&message.payload.0).as_internal_error_with_context(format!( "deserializing operation {}::{}", target.object_name, target.operation_name ))?; trace!( "Deserialized operation for network message {}::<{}>", message.operation, object_type ); trace!( "Calling handler for network message {}::<{}>", message.operation, object_type ); // Get the raw result of the operation, where the return values are boxed. let raw_result = handler.handle(&object, &operation, operation_state).await; trace!( "Finished handling network message {}::<{}>", message.operation, object_type ); // Deserialize the raw result for the network match raw_result { Ok(success) => Ok((meta.serialize_success)(success).as_internal_error()?), Err(err) => Err(match err { OperationError::Operation(failure) => { OperationError::Operation((meta.serialize_error)(failure).as_internal_error()?) } OperationError::Internal(internal) => { OperationError::Internal(internal.context(format!( "operation {}::{} handler outcome", target.object_name, target.operation_name ))) } OperationError::Unhandled => OperationError::Unhandled, }), } } pub async fn network_get_value( &self, object: Box, object_kind: String, operation: GetValue, operation_state: &StackOperationState, ) -> Result, OperationError>> { trace!("Handling network get_value for {}", operation.value_name); let value_meta = self .metadata .values .get(&ObjectValuePair { object_kind: object_kind.clone(), value_kind: operation.value_name.clone(), }) .ok_or_else(|| OperationError::Unhandled)?; for (target, getter) in self.value_getters.iter() { if target.object_kind != object_kind { continue; } if target.value_kind != operation.value_name { continue; } return match getter .handle(&(object), &((value_meta.typed_get)()), operation_state) .await { Ok(success) => { // Serialize success, which is the value type itself let serialized = (value_meta.serialize)(success).as_internal_error()?; Ok(serialized) } Err(err) => Err(match err { OperationError::Operation(failure) => { // Failure is sourced from GetValue operation, but this is hardcoded for now let failure: GetValueError = *failure.downcast().unwrap(); OperationError::Operation(serde_json::to_vec(&failure).as_internal_error()?) } OperationError::Internal(internal) => OperationError::Internal(internal), OperationError::Unhandled => OperationError::Unhandled, }), }; } Err(OperationError::Unhandled) } pub async fn get_setting( &self, object: Box, object_kind: String, operation: GetSetting, operation_state: &StackOperationState, ) -> Result, OperationError>> { trace!( "Handling network {}::get_setting for {}", object_kind, operation.setting_name ); for provider in self.metadata_providers.iter() { if provider.provides_for(object.as_ref()) { let setting_meta = self .metadata .settings .get(&ObjectSettingPair { object_kind: object_kind.clone(), setting_name: operation.setting_name.clone(), }) .ok_or_else(|| OperationError::Unhandled)?; let object_meta = self .metadata .objects .get(&object_kind) .ok_or_else(|| OperationError::Unhandled)?; let result = provider .read(object.as_ref(), object_meta, setting_meta) .await .as_internal_error_with_context(format!( "reading setting {}", operation.setting_name ))?; return Ok( (setting_meta.deserialize)(result).as_internal_error_with_context(format!( "deserializing setting {}", operation.setting_name ))?, ); } } todo!() } pub async fn network_set_setting( &self, object: Box, object_kind: String, operation: SetSetting, operation_state: &StackOperationState, ) -> Result, OperationError>> { trace!( "Handling network {}::set_setting for {}", object_kind, operation.setting_name ); let target = ObjectSettingPair { object_kind: object_kind.clone(), setting_name: operation.setting_name.clone(), }; let handler = self.setting_change.get(&target).unwrap(); let raw_result = handler .handle(&object, &(Box::new(operation) as _), operation_state) .await; match raw_result { Ok(_) => { // Serialize success, which is the value type itself let serialized = serde_json::to_vec(&()).as_internal_error()?; Ok(serialized) } Err(err) => Err(match err { OperationError::Operation(failure) => { // Failure is sourced from GetValue operation, but this is hardcoded for now let failure: GetValueError = *failure.downcast().unwrap(); OperationError::Operation(serde_json::to_vec(&failure).as_internal_error()?) } OperationError::Internal(internal) => OperationError::Internal(internal), OperationError::Unhandled => OperationError::Unhandled, }), } } } use core::fmt::Debug; #[async_trait::async_trait(?Send)] impl ObjectBackend for Arc { async fn object_operation( &self, in_object: O, operation_name: &str, payload: D, operation_state: &StackOperationState, ) -> Result> where O: GiteratedObject + Debug + 'static, D: GiteratedOperation + Debug + 'static, { // Erase object and operation types. let object = Box::new(in_object.clone()) as Box; let operation = Box::new(payload) as Box; // We need to hijack get_value, set_setting, and get_setting. if operation_name == "get_value" { let mut value_meta = None; for (_, meta) in self.metadata.values.iter() { if (meta.is_get_value_typed)(&operation) { value_meta = Some(meta); break; } } let value_meta = value_meta.ok_or_else(|| OperationError::Unhandled)?; let value_name = value_meta.name.clone(); trace!( "Handling get_value for {}::{}", O::object_name(), value_name ); for (target, getter) in self.value_getters.iter() { if target.object_kind != O::object_name() { continue; } if target.value_kind != value_name { continue; } return match getter .handle(&(object), &((value_meta.typed_get)()), operation_state) .await { Ok(success) => Ok(*success.downcast().unwrap()), Err(err) => Err(match err { OperationError::Operation(failure) => { OperationError::Operation(*failure.downcast::().unwrap()) } OperationError::Internal(internal) => { OperationError::Internal(internal.context(format!( "{}::get_value::<{}> handler outcome", O::object_name(), value_name ))) } OperationError::Unhandled => OperationError::Unhandled, }), }; } return Err(OperationError::Unhandled); } else if operation.is::() { let get_setting: Box = operation.downcast().unwrap(); let setting_name = get_setting.setting_name.clone(); let raw_result = self .get_setting( object, O::object_name().to_string(), *get_setting, operation_state, ) .await; return match raw_result { Ok(success) => { // Success is the setting type, serialize it // let serialized = (setting_meta.serialize)(success).unwrap(); // Ok(serde_json::to_vec(&serialized).unwrap()) Ok(*success.downcast().unwrap()) } Err(err) => Err(match err { OperationError::Operation(failure) => { // We know this is the right type OperationError::Operation(*failure.downcast().unwrap()) } OperationError::Internal(internal) => { OperationError::Internal(internal.context(format!( "{}::get_setting::<{}> handler outcome", O::object_name(), setting_name ))) } OperationError::Unhandled => OperationError::Unhandled, }), }; } else if operation.is::() { todo!() } else if operation.is::() { todo!() } // Resolve the operation from the known operations table. let operation_type = { let mut operation_type = None; for (target, operation_meta) in self.metadata.operations.iter() { // Skip elements that we know will not match if target.object_name != O::object_name() { continue; } if target.operation_name != operation_name { continue; } if (operation_meta.any_is_same)(&operation) { operation_type = Some(target.clone()); break; } } operation_type } .ok_or_else(|| OperationError::Unhandled)?; // Resolve the handler from our handler tree let handler_tree = self .operation_handlers .get(&operation_type) .ok_or_else(|| OperationError::Unhandled)?; let raw_result = handler_tree .handle(&object, &operation, operation_state) .await; // Convert the dynamic result back into its concrete type match raw_result { Ok(result) => Ok(*result.downcast::().unwrap()), Err(err) => Err(match err { OperationError::Internal(internal) => { OperationError::Internal(internal.context(format!( "operation {}::{} handler outcome", operation_type.object_name, operation_type.operation_name ))) } OperationError::Operation(boxed_error) => { OperationError::Operation(*boxed_error.downcast::().unwrap()) } OperationError::Unhandled => OperationError::Unhandled, }), } } async fn get_object( &self, object_str: &str, _operation_state: &StackOperationState, ) -> Result, OperationError> { // TODO: Authorization? for (_object_name, object_meta) in self.metadata.objects.iter() { if let Ok(object) = (object_meta.from_str)(object_str) { return Ok(unsafe { Object::new_unchecked(*object.downcast::().unwrap(), self.clone()) }); } } Err(OperationError::Unhandled) } }