use std::future::Future; use giterated_models::{ error::OperationError, object::GiteratedObject, settings::{AnySetting, Setting}, }; use crate::{ future::{RuntimeFuture, RuntimeFuturesExt}, new_stack::PluginState, AnyObject, NewAnySetting, }; use super::{CallbackPtr, RuntimeState}; #[derive(Clone, Copy)] pub struct SettingGetterCallback { pub callback_ptr: CallbackPtr, pub func: unsafe extern "C" fn( CallbackPtr, runtime_state: &RuntimeState, &PluginState, object: AnyObject, ) -> RuntimeFuture>, } impl SettingGetterCallback { pub fn new>(callback: T) -> Self { Self { func: T::get_setting, callback_ptr: callback.callback_ptr(), } } } pub trait IntoPluginSettingGetter { unsafe extern "C" fn get_setting( callback_ptr: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, object: AnyObject, ) -> RuntimeFuture>; fn callback_ptr(&self) -> CallbackPtr { unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } } } impl IntoPluginSettingGetter for F where Fut: Future>> + Send + Sync + 'static, S: Clone + Send + Sync + 'static, O: GiteratedObject + Send + Sync + 'static, OS: Setting + Send + Sync + 'static, F: Fn(S, O) -> Fut + Send + Sync + 'static, { unsafe extern "C" fn get_setting( callback: CallbackPtr, runtime_state: &RuntimeState, state: &PluginState, mut object: AnyObject, ) -> RuntimeFuture> { let _guard = trace_span!( "get_setting handler", object = O::object_name(), setting = OS::name() ) .entered(); let state = unsafe { state.transmute_ref::() }; let object = unsafe { object.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).await; match result { Ok(success) => unsafe { Ok(NewAnySetting::new(success)) }, Err(err) => match err { OperationError::Operation(_) => todo!(), OperationError::Internal(_) => todo!(), OperationError::Unhandled => todo!(), }, } }) } } pub trait IntoPluginSettingSetter { unsafe extern "C" fn set_setting( callback_ptr: CallbackPtr, state: &PluginState, object: AnyObject, setting: AnySetting, ) -> RuntimeFuture>; fn callback_ptr(&self) -> CallbackPtr { unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } } } impl IntoPluginSettingSetter for F where Fut: Future>>, S: Clone, O: GiteratedObject, OS: Setting, F: Fn(S, O, OS) -> Fut, { unsafe extern "C" fn set_setting( callback: CallbackPtr, state: &PluginState, mut object: AnyObject, _setting: AnySetting, ) -> RuntimeFuture> { let _guard = trace_span!( "get_setting handler", object = O::object_name(), setting = OS::name() ) .entered(); let _state = unsafe { state.transmute_ref::() }; let _object = unsafe { object.transmute_owned::() }; // Cast the callback ptr to ourselves let callback: *const F = std::mem::transmute(callback.0); let _callback = callback.as_ref().unwrap(); // let result = callback(state.clone(), *object); // match result { // Ok(setting) => Ok(NewAnySetting::new(setting)), // Err(_) => todo!(), // } todo!() } } pub struct SettingChangeCallback { func: unsafe extern "C" fn( &PluginState, object: AnyObject, setting_name: &str, new_setting: NewAnySetting, ), } pub trait IntoSettingChangeCallback { unsafe extern "C" fn setting_changed( state: &PluginState, object: AnyObject, setting_name: &str, new_setting: NewAnySetting, ); } impl IntoSettingChangeCallback for F { unsafe extern "C" fn setting_changed( _state: &PluginState, _object: AnyObject, _setting_name: &str, _new_setting: NewAnySetting, ) { todo!() } } impl SettingChangeCallback { pub fn new>() -> Self { Self { func: T::setting_changed, } } }