use std::sync::OnceLock; use giterated_models::{ object::GiteratedObject, operation::GiteratedOperation, settings::Setting, value::GiteratedObjectValue, }; use giterated_plugin::{ callback::{ CallbackPtr, IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter, IntoPluginValueGetter, OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback, }, handle::PluginInitializationState, new_stack::PluginState, vtable::{ InitializationVTable, IntoObjectVTable, IntoOperationVTable, IntoSettingVTable, IntoValueVTable, ObjectVtable, OperationVTable, SettingVtable, ValueVTable, }, AnyObject, NewAnyValue, }; use tracing::trace_span; pub struct PluginStackBuilder<'init, S> { init_state: *mut PluginInitializationState, vtable: &'init InitializationVTable, state: S, } impl<'init, S> PluginStackBuilder<'init, S> { pub fn new( plugin_state: S, state: *mut PluginInitializationState, vtable: &'init InitializationVTable, ) -> Self { Self { init_state: state, vtable, state: plugin_state, } } pub fn object(&mut self) -> &mut Self { let _guard = trace_span!("register object").entered(); let func = self.vtable.register_object; unsafe { func(self.init_state, O::object_name(), ObjectVtable::new::()) }; self } pub fn register_operation(&mut self) -> &mut Self where D: IntoOperationVTable + GiteratedOperation, O: GiteratedObject, { let _guard = trace_span!("register operation").entered(); unsafe { (self.vtable.register_operation)( self.init_state, O::object_name(), D::operation_name(), OperationVTable::new::(), ) } self } pub fn object_setting(&mut self, get: HG, set: HS) -> &mut Self where O: GiteratedObject, OS: IntoSettingVTable + Setting, HG: IntoPluginSettingGetter, HS: IntoPluginSettingSetter, { let _guard = trace_span!("register setting").entered(); unsafe { (self.vtable.register_setting)( self.init_state, O::object_name(), OS::name(), SettingVtable::new::(), ) } self } pub fn object_user_setting(&mut self) -> &mut Self where O: GiteratedObject, OS: IntoSettingVTable + Setting, { let _guard = trace_span!("register setting").entered(); unsafe { (self.vtable.register_setting)( self.init_state, O::object_name(), OS::name(), SettingVtable::new::(), ) } self } pub fn value(&mut self, handler: T) -> &mut Self where O: GiteratedObject, V: IntoValueVTable + GiteratedObjectValue, T: IntoPluginValueGetter, { let _guard = trace_span!("register value").entered(); unsafe { (self.vtable.register_value)( self.init_state, O::object_name(), V::value_name(), ValueVTable::new::(), ) } unsafe { (self.vtable.value_getter)( self.init_state, O::object_name(), V::value_name(), ValueGetterCallback::new::(handler), ) } self } pub fn operation< DS, DF, A, O: GiteratedObject + IntoObjectVTable, D: IntoOperationVTable + GiteratedOperation, T: IntoPluginOperationHandler, >( &mut self, handler: T, ) -> &mut Self { let _guard = trace_span!("register operation handler").entered(); unsafe { (self.vtable.operation_handler)( self.init_state, O::object_name(), D::operation_name(), OperationHandlerCallback::new::(handler), ) } // TODO: Yikes? self.object::(); self.register_operation::(); self } // pub fn value_getter(&mut self, handler: T) -> &mut Self // where // O: GiteratedObject + IntoObjectVTable, // V: GiteratedObjectValue + IntoValueVTable, // T: IntoPluginValueGetter, // { // let _guard = trace_span!("register value_getter handler").entered(); // unsafe { // (self.vtable.value_getter)( // self.init_state, // O::object_name(), // V::value_name(), // ValueGetterCallback::new::(handler), // ) // } // // TODO: Yikes? // self.object::(); // self.value::(); // self // } // pub fn setting_getter(&mut self, handler: T) -> &mut Self // where // O: GiteratedObject + IntoObjectVTable, // OS: Setting + IntoSettingVTable, // T: IntoPluginSettingGetter, // { // let _guard = trace_span!("register setting_getter handler").entered(); // unsafe { // (self.vtable.setting_getter)( // self.init_state, // O::object_name(), // OS::name(), // SettingGetterCallback::new::(handler), // ) // } // self.object::(); // // self.setting::(); // self // } } pub trait ValueSettingExt { fn value_setting(&mut self, get: HG, set: HS) -> &mut Self where O: GiteratedObject + IntoObjectVTable + 'static, VS: GiteratedObjectValue + IntoValueVTable + Setting + IntoSettingVTable, HG: IntoPluginSettingGetter, HS: IntoPluginSettingSetter; } impl ValueSettingExt for PluginStackBuilder<'_, PS> { fn value_setting(&mut self, get: HG, set: HS) -> &mut Self where O: GiteratedObject + IntoObjectVTable + 'static, VS: GiteratedObjectValue + IntoValueVTable + Setting + IntoSettingVTable, HG: IntoPluginSettingGetter, HS: IntoPluginSettingSetter, { self } } pub trait ValueSettingGetter { unsafe extern "C" fn get_value( callback: CallbackPtr, state: &PluginState, object: AnyObject, ) -> Result; fn callback_ptr(&self) -> CallbackPtr; } impl ValueSettingGetter for HG where O: GiteratedObject, VS: GiteratedObjectValue, HG: IntoPluginSettingGetter, { unsafe extern "C" fn get_value( callback: CallbackPtr, state: &PluginState, object: AnyObject, ) -> Result { let result = HG::get_setting(callback, state, object)?; let setting = *result.transmute_owned::(); Ok(NewAnyValue::new(setting)) } fn callback_ptr(&self) -> CallbackPtr { self.callback_ptr() } }