use giterated_models::error::OperationError; use crate::{ new_stack::{PluginState, Runtime, State}, AnyObject, AnyOperation, }; use std::{any::type_name, fmt::Debug, future::Future, sync::Arc}; 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, ), } impl OperationHandlerCallback { pub fn new>( handler: T, ) -> Self { OperationHandlerCallback { func: T::handle, callback_ptr: T::callback_ptr(&handler), } } } pub trait IntoPluginOperationHandler { unsafe extern "C" fn handle( callback_ptr: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, object: AnyObject, operation: AnyOperation, ); fn callback_ptr(&self) -> CallbackPtr; } impl IntoPluginOperationHandler for F where Fut: Future>>, F: Fn(S, O, D) -> Fut, S: Clone + Debug, O: Debug, D: Debug, { unsafe extern "C" fn handle( callback: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, mut object: AnyObject, mut operation: AnyOperation, ) { 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(); // callback(state.clone(), *object, *operation) 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, D: Debug, { unsafe extern "C" fn handle( callback_ptr: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, object: AnyObject, operation: AnyOperation, ) { 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, D: Debug, { unsafe extern "C" fn handle( callback_ptr: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, object: AnyObject, operation: AnyOperation, ) { todo!() } fn callback_ptr(&self) -> CallbackPtr { todo!() } } pub trait FromOperationState: Sized { fn from_operation_state( state: &S, runtime_state: &RuntimeState, object: &O, operation: &D, ) -> Result>; } impl FromOperationState for Arc { fn from_operation_state( state: &S, runtime_state: &RuntimeState, object: &O, operation: &D, ) -> Result> { Ok(runtime_state.runtime.clone()) } } impl FromOperationState for Option where T: FromOperationState, { fn from_operation_state( state: &S, runtime_state: &RuntimeState, object: &O, operation: &D, ) -> Result> { Ok(T::from_operation_state(state, runtime_state, object, operation).ok()) } } impl FromOperationState for State { fn from_operation_state( state: &S, runtime_state: &RuntimeState, object: &O, operation: &D, ) -> Result> { Ok(unsafe { State(runtime_state.operation_state.transmute_ref::().clone()) }) } }