use giterated_models::error::OperationError; use crate::{new_stack::PluginState, AnyObject, AnyOperation}; use std::{any::type_name, fmt::Debug, future::Future}; use super::CallbackPtr; #[derive(Clone, Copy)] pub struct OperationHandlerCallback { pub callback_ptr: CallbackPtr, pub func: unsafe extern "C" fn(CallbackPtr, &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, 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, 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 ()) } } }