use giterated_models::{ error::OperationError, object::GiteratedObject, operation::{GiteratedOperation, OperationState}, }; use crate::{ future::{RuntimeFuture, RuntimeFuturesExt}, new_stack::{handle::RuntimeHandle, PluginState}, vtable::OperationVTable, AnyFailure, AnyObject, AnyOperation, AnySuccess, FFIBox, }; use std::{any::type_name, fmt::Debug, future::Future}; use super::{CallbackPtr, RuntimeState}; #[derive(Clone, Copy)] pub struct OperationHandlerCallback { pub callback_ptr: CallbackPtr, pub func: unsafe extern "C" fn( CallbackPtr, &RuntimeState, &PluginState, object: AnyObject, operation: AnyOperation, ) -> RuntimeFuture>>, } impl OperationHandlerCallback { pub fn new< S, O: GiteratedObject, D: GiteratedOperation, A, T: IntoPluginOperationHandler, >( handler: T, ) -> Self { OperationHandlerCallback { func: T::handle, callback_ptr: T::callback_ptr(&handler), } } } pub trait IntoPluginOperationHandler, A> { unsafe extern "C" fn handle( callback_ptr: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, object: AnyObject, operation: AnyOperation, ) -> RuntimeFuture>>; fn callback_ptr(&self) -> CallbackPtr; } impl IntoPluginOperationHandler for F where Fut: Future>> + Send + Sync, F: Fn(S, O, D) -> Fut + Send + Sync + 'static, S: Clone + Debug + Send + Sync + 'static, O: Debug + GiteratedObject + 'static, D: Debug + GiteratedOperation + 'static, { unsafe extern "C" fn handle( callback: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, mut object: AnyObject, mut operation: AnyOperation, ) -> RuntimeFuture>> { let _guard = trace_span!( "operation handler", object = type_name::(), operation = type_name::() ) .entered(); let state = unsafe { state.transmute_ref::() }; // Since this is Rust code, we know that the AnyObject and AnyOperation are just boxes let object = unsafe { object.transmute_owned::() }; let operation = unsafe { operation.transmute_owned::() }; // Cast the callback ptr to ourselves let callback: *const F = std::mem::transmute(callback.0); let callback = callback.as_ref().unwrap(); let state = state.clone(); runtime_state.spawn_future(async move { let result = callback(state, *object, *operation).await; match result { Ok(success) => unsafe { Ok(AnySuccess::from_raw( FFIBox::from_box(Box::new(success)).untyped(), OperationVTable::new::(), )) }, Err(err) => match err { OperationError::Operation(_) => todo!(), OperationError::Internal(_) => todo!(), OperationError::Unhandled => todo!(), }, } }) } fn callback_ptr(&self) -> CallbackPtr { unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } } } impl IntoPluginOperationHandler for F where Fut: Future>>, F: Fn(S, O, D, A1) -> Fut, S: Clone + Debug, O: Debug + GiteratedObject, D: Debug + GiteratedOperation, { unsafe extern "C" fn handle( _callback_ptr: CallbackPtr, _runtime_state: &RuntimeState, _state: &PluginState, _object: AnyObject, _operation: AnyOperation, ) -> RuntimeFuture>> { todo!() } fn callback_ptr(&self) -> CallbackPtr { todo!() } } impl IntoPluginOperationHandler for F where Fut: Future>>, F: Fn(S, O, D, A1, A2) -> Fut, S: Clone + Debug, O: Debug + GiteratedObject, D: Debug + GiteratedOperation, { unsafe extern "C" fn handle( _callback_ptr: CallbackPtr, _runtime_state: &RuntimeState, _state: &PluginState, _object: AnyObject, _operation: AnyOperation, ) -> RuntimeFuture>> { todo!() } fn callback_ptr(&self) -> CallbackPtr { todo!() } } pub trait FromOperationState: Sized { fn from_operation_state( operation_state: &OperationState, runtime_state: &RuntimeState, object: &O, operation: &D, ) -> Result>; } impl FromOperationState for RuntimeHandle { fn from_operation_state( _operation_state: &OperationState, runtime_state: &RuntimeState, _object: &O, _operation: &D, ) -> Result> { Ok(unsafe { RuntimeHandle::from_vtable(runtime_state.vtable) }) } } impl FromOperationState for Option where T: FromOperationState, { fn from_operation_state( operation_state: &OperationState, runtime_state: &RuntimeState, object: &O, operation: &D, ) -> Result> { Ok(T::from_operation_state(operation_state, runtime_state, object, operation).ok()) } }