use std::{any::Any, collections::HashMap, sync::Arc}; use futures_util::FutureExt; use giterated_models::{ authenticated::AuthenticatedPayload, error::{GetValueError, 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 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 GiteratedStack { operation_handlers: HashMap, value_getters: HashMap, setting_getters: HashMap, metadata: RuntimeMetadata, } impl GiteratedStack { pub fn merge_builder( &mut self, 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()); } 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 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, 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(), 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`] 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.clone(); 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 } } 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.clone(), operation_name: operation_name.clone(), }, 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.clone(), value_kind: value_name.clone(), }, 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) { let setting_name = S::name().to_string(); if self .settings .insert(setting_name.clone(), 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(); return self .network_get_value(object, object_type.clone(), operation, operation_state) .await; } else if message.operation == "get_setting" { let operation: GetSetting = serde_json::from_slice(&message.payload.0).unwrap(); let setting_meta = self .metadata .settings .get(&operation.setting_name) .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), OperationError::Unhandled => OperationError::Unhandled, }), }; } 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) .map_err(|e| OperationError::Internal(e.to_string()))?; 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) .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, }), } } 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) .map_err(|e| OperationError::Internal(e.to_string()))?; 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) .map_err(|e| OperationError::Internal(e.to_string()))?, ) } 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 ); let setting_getter = self .setting_getters .get(&object_kind) .ok_or_else(|| OperationError::Unhandled)?; setting_getter .handle(&object, &(Box::new(operation) as Box<_>), operation_state) .await } pub async fn network_set_setting( &self, _operation: SetSetting, _operation_state: &StackOperationState, ) -> Result, OperationError>> { todo!() } } 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), OperationError::Unhandled => OperationError::Unhandled, }), }; } return Err(OperationError::Unhandled); } else if operation.is::() { let get_setting: Box = operation.downcast().unwrap(); 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), 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), 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) } }