use std::{any::Any, collections::HashMap, sync::Arc}; use giterated_models::{ authenticated::AuthenticatedPayload, error::OperationError, message::GiteratedMessage, object::{AnyObject, GiteratedObject, Object, ObjectRequestError}, object_backend::ObjectBackend, operation::{AnyOperationV2, GiteratedOperation}, settings::{GetSetting, SetSetting, Setting}, value::{GetValue, GetValueV2, GiteratedObjectValue}, }; use tracing::trace; use crate::{ GiteratedOperationHandler, ObjectMeta, ObjectOperationPair, ObjectValuePair, OperationMeta, OperationWrapper, SettingMeta, StackOperationState, ValueMeta, }; /// Temporary name for the next generation of Giterated stack #[derive(Default)] pub struct GiteratedRuntime { operation_handlers: HashMap, value_getters: HashMap, setting_getters: HashMap, metadata: RuntimeMetadata, } impl GiteratedRuntime { pub fn merge_builder( &mut self, builder: RuntimeBuilder, ) -> &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()); } self.metadata.append(builder.metadata); self } 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() } } } pub struct HandlerTree { elements: Vec, } impl Default for HandlerTree { fn default() -> Self { Self { elements: vec![] } } } impl HandlerTree { pub fn push(&mut self, handler: OperationWrapper) { self.elements.push(handler); } pub fn handle( &self, _object: &dyn Any, _operation: Box, _operation_state: &StackOperationState, ) -> Result, OperationError>> { todo!() } } /// 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 GiteratedRuntimeState: Send + Sync + Clone {} impl GiteratedRuntimeState for T {} pub struct RuntimeBuilder { operation_handlers: HashMap, value_getters: HashMap, setting_getters: HashMap, metadata: RuntimeMetadata, state: S, } impl RuntimeBuilder { pub fn new() -> Self { todo!() } } impl RuntimeBuilder { /// 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, H: GiteratedOperationHandler + 'static + Clone, { 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, }; assert!(self.operation_handlers.insert(pair, wrapped).is_none()); 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::(); 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`] 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, F: GiteratedOperationHandler, S> + Clone + 'static, { let object_name = handler.object_name().to_string(); let value_name = V::value_name().to_string(); let wrapped = OperationWrapper::new(handler, self.state.clone()); 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, { 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 } } 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::()), }; 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.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).unwrap()) 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) }), }, ) .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.clone(), value_kind: value_name.clone(), }, ValueMeta { name: value_name, deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(&bytes)?))), }, ) .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) { let setting_name = S::name().to_string(); if self .settings .insert( setting_name.clone(), SettingMeta { name: setting_name, deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(bytes)?))), }, ) .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); } } #[async_trait::async_trait] impl GiteratedOperationHandler for GiteratedRuntime where O: GiteratedObject + 'static, D: GiteratedOperation + 'static, S: GiteratedRuntimeState + 'static, { fn operation_name(&self) -> &str { D::operation_name() } fn object_name(&self) -> &str { O::object_name() } async fn handle( &self, object: &O, operation: D, _state: S, operation_state: &StackOperationState, ) -> Result> { // Erase object and operation types. let object = object as &dyn Any; let operation = Box::new(operation) 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)(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.is::() { todo!() } 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 != object_type { 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); // 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), OperationError::Operation(boxed_error) => { OperationError::Operation(*boxed_error.downcast::().unwrap()) } OperationError::Unhandled => OperationError::Unhandled, }), } } } impl GiteratedRuntime { /// 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, _state: &S, operation_state: &StackOperationState, ) -> Result, OperationError>> { let message: GiteratedMessage = message.into_message_v2(); // 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)?; let target = ObjectOperationPair { object_name: object_type, operation_name: message.operation, }; // Resolve the target operations from the handlers table let handler = self .operation_handlers .get(&target) .ok_or_else(|| OperationError::Unhandled)?; // Deserialize the operation let meta = self .metadata .operations .get(&target) .ok_or_else(|| OperationError::Unhandled)?; let operation = (meta.deserialize)(&message.payload.0).map_err(|_| OperationError::Unhandled)?; // Get the raw result of the operation, where the return values are boxed. let raw_result = handler.handle(&object, operation, operation_state); // Deserialize the raw result for the network match raw_result { Ok(success) => Ok((meta.serialize_success)(success) .map_err(|e| OperationError::Internal(e.to_string()))?), Err(err) => Err(match err { OperationError::Operation(failure) => OperationError::Operation( (meta.serialize_error)(failure) .map_err(|e| OperationError::Internal(e.to_string()))?, ), OperationError::Internal(internal) => OperationError::Internal(internal), OperationError::Unhandled => OperationError::Unhandled, }), } } } use core::fmt::Debug; #[async_trait::async_trait] impl ObjectBackend for Arc { async fn object_operation( &self, _object: O, _operation: &str, _payload: D, _operation_state: &StackOperationState, ) -> Result> where O: GiteratedObject + Debug + 'static, D: GiteratedOperation + Debug, { todo!() } async fn get_object( &self, _object_str: &str, _operation_state: &StackOperationState, ) -> Result, OperationError> { todo!() } }