use crate::callback::RuntimeState; use giterated_models::{operation::GiteratedOperation, settings::GetSetting, value::GetValue}; use tracing::{debug_span, trace, trace_span}; use crate::new_stack::{ObjectOperationPair, PluginState}; use super::{HandlerError, ObjectSettingPair, ObjectValuePair, RuntimeHandlers}; /// A wrapper for operation handling that enforces handling rules. /// /// # Handler Resolution /// In order, handler resolution will be attempted as follows: /// /// | Index | object_kind | operation_kind | Special Case? | /// |-------|-------------|-----------------|---------------| /// | 1 | `any` | `typed` | No | /// | 2 | `typed` | `any` | No | /// | 3 | `any` | `any` | No | /// | 4 | `any` | `GetValue` | ⚠️ Yes ⚠️ | /// | 5 | `any` | `GetSetting` | ⚠️ Yes ⚠️ | /// | 6 | `any` | `SetSetting` | ⚠️ Yes ⚠️ | /// | 7 | `any` | `ObjectRequest` | ⚠️ Yes ⚠️ | /// | 8 | `typed` | `typed` | No | pub struct OperationHandlerRules<'a> { object_kind: &'a str, operation_name: &'a str, handlers: &'a RuntimeHandlers, } impl<'o> OperationHandlerRules<'o> { pub fn new( object_kind: &'o str, operation_name: &'o str, handlers: &'o RuntimeHandlers, ) -> Self { Self { object_kind, operation_name, handlers, } } pub fn handle( &self, runtime_state: &RuntimeState, object: &str, operation_payload: &[u8], ) -> Result<(), HandlerError> { // object_kind: `any` // operation_kind: `typed` if let Some(handler) = self .handlers .operation_handlers .get(&ObjectOperationPair::new("any", self.operation_name)) { todo!() } // object_kind: `typed` // operation_kind: `any` if let Some(handler) = self .handlers .operation_handlers .get(&ObjectOperationPair::new(self.object_kind, "any")) {} // object_kind: `any` // operation_kind: `any` if let Some(handler) = self .handlers .operation_handlers .get(&ObjectOperationPair::new("any", "any")) {} // ⚠️ Special Case ⚠️ // object_kind: `any` // operation_kind: `GetValue` if self.operation_name == "get_value" { let operation: GetValue = serde_json::from_slice(operation_payload).unwrap(); let _guard = trace_span!( "get_value handler resolving", object = self.object_kind, value = operation.value_name ) .entered(); if let Some((domain, callback)) = self.handlers.value_getters.get( &ObjectValuePair::new(self.object_kind, &operation.value_name), ) { trace_span!( "get_value handler.", object = self.object_kind, value_name = operation.value_name ); let object_vtable = domain .object_vtable(self.object_kind) .ok_or_else(|| HandlerError::Unhandled)?; trace!("Resolved object vtable for {}", self.object_kind); let value_vtable = domain .value_vtable(self.object_kind, &operation.value_name) .ok_or_else(|| HandlerError::Unhandled)?; trace!( "Resolved value vtable for {}::{}", self.object_kind, operation.value_name ); let object = unsafe { (object_vtable.from_str)(object) } .map_err(|_| HandlerError::Internal(()))?; let _guard = debug_span!("get_value handler"); let result = unsafe { (callback.func)(callback.callback_ptr, &domain.plugin.state, object) }; // Todo deser return Ok(()); } else { trace!("Failed to resolve handler."); } } // ⚠️ Special Case ⚠️ // object_kind: `any` // operation_kind: `GetSetting` if self.operation_name == "get_setting" { let operation: GetSetting = serde_json::from_slice(operation_payload).unwrap(); let _guard = trace_span!( "get_setting handler resolving", object = self.object_kind, setting = operation.setting_name ) .entered(); if let Some((domain, callback)) = self.handlers.setting_getters.get( &ObjectSettingPair::new(self.object_kind, &operation.setting_name), ) { trace_span!( "get_setting handler.", object = self.object_kind, setting_name = operation.setting_name ); let object_vtable = domain .object_vtable(self.object_kind) .ok_or_else(|| HandlerError::Unhandled)?; trace!("Resolved object vtable for {}", self.object_kind); let setting_vtable = domain .setting_vtable(self.object_kind, &operation.setting_name) .ok_or_else(|| HandlerError::Unhandled)?; trace!("Resolved setting vtable for {}", operation.setting_name); let object = unsafe { (object_vtable.from_str)(object) } .map_err(|_| HandlerError::Internal(()))?; let _guard = debug_span!("get_value handler"); let result = unsafe { (callback.func)(callback.callback_ptr, &domain.plugin.state, object) }; // Todo deser return Ok(()); } else { trace!("Failed to resolve handler."); } } // ⚠️ Special Case ⚠️ // object_kind: `any` // operation_kind: `SetSetting` if self.operation_name == "set_setting" {} // ⚠️ Special Case ⚠️ // object_kind: `any` // operation_kind: `ObjectRequest` if self.operation_name == "object_request" {} // object_kind: `typed` // operation_kind: `typed` if let Some((domain, handler)) = self.handlers .operation_handlers .get(&ObjectOperationPair::new( self.object_kind, self.operation_name, )) { let _guard = trace_span!("typed_typed handler resolved").entered(); let object_vtable = domain .object_vtable(self.object_kind) .ok_or_else(|| HandlerError::Unhandled)?; trace!("Resolved object vtable for {}", self.object_kind); let operation_vtable = domain .operation_vtable(self.object_kind, self.operation_name) .ok_or_else(|| HandlerError::Unhandled)?; trace!( "Resolved operation vtable for {}::{}", self.object_kind, self.operation_name ); let object = unsafe { (object_vtable.from_str)(object) } .map_err(|_| HandlerError::Internal(()))?; let operation = unsafe { (operation_vtable.deserialize)(operation_payload) } .map_err(|_| HandlerError::Internal(()))?; trace!("Parsed operation data"); let _guard = debug_span!("calling handler").entered(); let result = unsafe { (handler.func)( handler.callback_ptr, runtime_state, &domain.plugin.state, object, operation, ) }; // todo return Ok(()); } Err(HandlerError::Unhandled) } }