diff --git a/Cargo.lock b/Cargo.lock index fe33a68..351366c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -488,7 +488,6 @@ dependencies = [ "dlopen2", "giterated-models", "giterated-plugin", - "giterated-plugin-sys", "giterated-static-runtime", "serde_json", "tokio", @@ -699,7 +698,6 @@ dependencies = [ "anyhow", "giterated-models", "giterated-plugin", - "giterated-plugin-sys", "serde", "serde_json", "sqlx", @@ -757,7 +755,6 @@ dependencies = [ "anyhow", "giterated-models", "giterated-plugin", - "giterated-plugin-sys", "serde", "serde_json", "sqlx", @@ -773,6 +770,7 @@ name = "giterated-macros" version = "0.1.0" dependencies = [ "quote", + "syn 2.0.39", ] [[package]] @@ -820,16 +818,6 @@ dependencies = [ ] [[package]] -name = "giterated-plugin-sys" -version = "0.1.0" -dependencies = [ - "giterated-abi", - "giterated-models", - "giterated-plugin", - "tracing", -] - -[[package]] name = "giterated-protocol" version = "0.1.0" dependencies = [ @@ -839,7 +827,6 @@ dependencies = [ "futures-util", "giterated-models", "giterated-plugin", - "giterated-plugin-sys", "rand", "rsa", "serde", diff --git a/Cargo.toml b/Cargo.toml index 4d0237f..7fd5c53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,9 @@ members = [ "giterated-abi", "giterated-core", "giterated-daemon", "giterated-models", "giterated-plugin", - "giterated-plugin/giterated-macros", - "giterated-plugin/giterated-plugin-sys", - "giterated-plugin/giterated-static-runtime", "giterated-runtime", + "giterated-macros", + "giterated-runtime/giterated-static-runtime", + "giterated-runtime", "plugins/example-plugin", "plugins/giterated-backend", "plugins/giterated-issues", diff --git a/giterated-abi/src/vtable/mod.rs b/giterated-abi/src/vtable/mod.rs index 78f7571..88000c5 100644 --- a/giterated-abi/src/vtable/mod.rs +++ b/giterated-abi/src/vtable/mod.rs @@ -4,6 +4,8 @@ mod object; pub mod operation; mod setting; mod value; +mod runtime; +mod plugin_initialization; pub use object::*; pub use setting::*; diff --git a/giterated-abi/src/vtable/plugin_initialization.rs b/giterated-abi/src/vtable/plugin_initialization.rs new file mode 100644 index 0000000..5f3702a --- /dev/null +++ b/giterated-abi/src/vtable/plugin_initialization.rs @@ -0,0 +1,61 @@ +#[repr(C)] +pub struct HostVTable {} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Initialization { + pub register_object: + unsafe extern "C" fn(*mut PluginInitializationState, &'static str, &'static VTable), + pub register_operation: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + &'static VTable, + ), + pub register_setting: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + &'static VTable, + ), + pub register_value: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + &'static VTable, + ), + + pub operation_handler: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + CallbackPtr, + ), + + pub value_getter: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + CallbackPtr, + ), + + pub setting_getter: unsafe extern "C" fn( + *mut PluginInitializationState, + &'static str, + &'static str, + CallbackPtr, + ), +} + +impl ObjectABI for Initialization { + type VTable = Initialization; +} + +impl Debug for Initialization { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InitializationVTable").finish() + } +} + +unsafe impl Sync for Initialization {} +unsafe impl Send for Initialization {} diff --git a/giterated-abi/src/vtable/runtime.rs b/giterated-abi/src/vtable/runtime.rs new file mode 100644 index 0000000..1592e03 --- /dev/null +++ b/giterated-abi/src/vtable/runtime.rs @@ -0,0 +1,56 @@ +use giterated_abi::{ + result::{FfiError, FfiResult}, + value_ex::FfiValueUntyped, + vtable::Object, + FfiSliceRef, +}; +use giterated_models::{ + error::OperationError, object::ObjectRequestError, operation::OperationState, +}; + +use crate::{ + future::RuntimeFuture, + new_stack::{PluginState, TypeMetadata}, +}; + +#[derive(Clone, Copy)] +pub struct RuntimeVTable { + pub(crate) runtime: PluginState, + pub(crate) type_metadata: *const TypeMetadata, + pub(crate) handle_fn: unsafe extern "C" fn( + PluginState, + FfiSliceRef, + FfiSliceRef, + FfiSliceRef, + FfiSliceRef<[u8]>, + FfiSliceRef<[u8]>, + ) -> RuntimeFuture< + FfiResult>, + >, + pub(crate) get_object: + unsafe extern "C" fn( + PluginState, + &str, + *mut OperationState, + ) -> FfiResult>, +} + +unsafe impl Send for RuntimeVTable {} +unsafe impl Sync for RuntimeVTable {} + +pub trait IntoRuntimeVtable { + unsafe extern "C" fn handle( + this: PluginState, + object_kind: FfiSliceRef, + operation_name: FfiSliceRef, + object: FfiSliceRef, + operation_payload: FfiSliceRef<[u8]>, + operation_state: FfiSliceRef<[u8]>, + ) -> RuntimeFuture>>; + + unsafe extern "C" fn get_object( + this: PluginState, + object_str: &str, + operation_state: *mut OperationState, + ) -> FfiResult>; +} diff --git a/giterated-abi/src/vtable/setting.rs b/giterated-abi/src/vtable/setting.rs index fbfe56b..4daa590 100644 --- a/giterated-abi/src/vtable/setting.rs +++ b/giterated-abi/src/vtable/setting.rs @@ -32,7 +32,7 @@ impl SettingVTable { pub const fn new() -> Self { Self { serialize: S::serialize, - deserialize: S::deserialize + deserialize: S::deserialize, } } diff --git a/giterated-core/src/callback/mod.rs b/giterated-core/src/callback/mod.rs index 3e60183..078eb9d 100644 --- a/giterated-core/src/callback/mod.rs +++ b/giterated-core/src/callback/mod.rs @@ -1 +1,3 @@ mod operation; +mod setting; +mod value; diff --git a/giterated-core/src/callback/setting.rs b/giterated-core/src/callback/setting.rs new file mode 100644 index 0000000..931ea62 --- /dev/null +++ b/giterated-core/src/callback/setting.rs @@ -0,0 +1,150 @@ +pub struct SettingGetterCallback(FfiValueUntyped); + +impl Callback for SettingGetterCallback { + type CallbackFunc = unsafe extern "C" fn( + CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + ) -> RuntimeFuture>; +} + +pub trait IntoPluginSettingGetter { + unsafe extern "C" fn get_setting( + callback_ptr: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + ) -> RuntimeFuture>; + + fn callback_ptr(&self) -> CallbackPtr { + // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + todo!() + } +} + +impl IntoPluginSettingGetter for F +where + Fut: Future>> + Send + Sync + 'static, + S: Clone + Send + Sync + 'static, + O: GiteratedObject + Send + Sync + 'static, + OS: giterated_models::settings::Setting + Send + Sync + 'static, + F: Fn(S, O) -> Fut + Send + Sync + 'static, +{ + unsafe extern "C" fn get_setting( + callback: CallbackPtr, + state: FfiValueMut, + mut object: FfiValueRef, + ) -> 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!(), + // }, + // } + + todo!() + // }) + } +} + +pub trait IntoPluginSettingSetter { + unsafe extern "C" fn set_setting( + callback_ptr: CallbackPtr, + state: &PluginState, + object: FfiValueRef, + setting: Setting, + ) -> RuntimeFuture>; + + fn callback_ptr(&self) -> CallbackPtr { + // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + todo!() + } +} + +impl IntoPluginSettingSetter for F +where + Fut: Future>>, + S: Clone, + O: GiteratedObject, + OS: giterated_models::settings::Setting, + F: Fn(S, O, OS) -> Fut, +{ + unsafe extern "C" fn set_setting( + callback: CallbackPtr, + state: &PluginState, + mut object: FfiValueRef, + _setting: Setting, + ) -> 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(FfiValueUntyped); + +impl Callback for SettingChangeCallback { + type CallbackFunc = unsafe extern "C" fn( + &PluginState, + object: FfiValueRef, + setting_name: &str, + new_setting: Setting, + ); +} + +pub trait IntoSettingChangeCallback { + unsafe extern "C" fn setting_changed( + state: &PluginState, + object: FfiValueRef, + setting_name: &str, + new_setting: Setting, + ); +} + +impl IntoSettingChangeCallback for F { + unsafe extern "C" fn setting_changed( + _state: &PluginState, + _object: FfiValueRef, + _setting_name: &str, + _new_setting: Setting, + ) { + todo!() + } +} diff --git a/giterated-core/src/callback/value.rs b/giterated-core/src/callback/value.rs new file mode 100644 index 0000000..d9fa84c --- /dev/null +++ b/giterated-core/src/callback/value.rs @@ -0,0 +1,103 @@ +#[derive(Copy, Clone)] +pub struct ValueGetterCallback(CallbackPtr); + +impl Callback for ValueGetterCallback { + type CallbackFunc = unsafe extern "C" fn( + CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + ) -> RuntimeFuture>; +} + +pub trait IntoPluginValueGetter { + unsafe extern "C" fn get_value( + callback: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + ) -> RuntimeFuture>; + + fn callback_ptr(&self) -> CallbackPtr; +} + +impl IntoPluginValueGetter for F +where + Fut: Future>> + Send + Sync, + S: Clone + Send + Sync + 'static, + O: GiteratedObject + 'static, + V: GiteratedObjectValue + Send + Sync + 'static, + F: Fn(S, O) -> Fut + Send + Sync + 'static, +{ + unsafe extern "C" fn get_value( + callback: CallbackPtr, + state: FfiValueMut, + mut object: FfiValueRef, + ) -> RuntimeFuture> { + // let _guard = trace_span!( + // "get_value handler", + // object = O::object_name(), + // value = V::value_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(NewAnyValue::new(success)) }, + // Err(err) => match err { + // OperationError::Operation(_) => todo!(), + // OperationError::Internal(_) => todo!(), + // OperationError::Unhandled => todo!(), + // }, + // } + // }) + + todo!() + } + + fn callback_ptr(&self) -> CallbackPtr { + todo!() + // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + } +} + +pub struct ValueChangeCallback(CallbackPtr); + +impl Callback for ValueChangeCallback { + type CallbackFunc = unsafe extern "C" fn( + &PluginState, + object: FfiValueRef, + value_name: FfiSliceRef, + new_value: Value, + ) -> RuntimeFuture<()>; +} + +pub trait IntoValueChangeCallback { + unsafe extern "C" fn value_changed( + callback: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + value_name: FfiSliceRef, + new_value: Value, + ) -> RuntimeFuture<()>; +} + +impl IntoValueChangeCallback for F { + unsafe extern "C" fn value_changed( + callback: CallbackPtr, + state: FfiValueMut, + _object: FfiValueRef, + _value_name: FfiSliceRef, + _new_value: Value, + ) -> RuntimeFuture<()> { + todo!() + } +} diff --git a/giterated-core/src/lib.rs b/giterated-core/src/lib.rs index 05cbac6..359f24f 100644 --- a/giterated-core/src/lib.rs +++ b/giterated-core/src/lib.rs @@ -1,5 +1,6 @@ mod callback; mod state; +mod types; #[derive(Clone)] #[repr(C)] diff --git a/giterated-core/src/operation_walker.rs b/giterated-core/src/operation_walker.rs new file mode 100644 index 0000000..e3fb91a --- /dev/null +++ b/giterated-core/src/operation_walker.rs @@ -0,0 +1,273 @@ +use crate::callback::RuntimeState; +use giterated_abi::{result::FfiError, value_ex::FfiValueUntyped}; +use giterated_models::{ + error::OperationError, operation::GiteratedOperation, settings::GetSetting, value::GetValue, +}; + +use serde_json::Value; +use tracing::{debug_span, trace, trace_span}; + +use crate::new_stack::ObjectOperationPair; + +use super::{ObjectSettingPair, ObjectValuePair, RuntimeHandlers}; + +/// A wrapper for operation handling that enforces handling rules. +/// +/// # Handler Resolution +/// In order, handler resolution will be attempted as follows: +/// +/// | Index | object_kind | operation_kind | Special Case? | +/// |-------|-------------|-----------------|---------------| +/// | 1 | `any` | `typed` | No | +/// | 2 | `typed` | `any` | No | +/// | 3 | `any` | `any` | No | +/// | 4 | `any` | `GetValue` | ⚠️ Yes ⚠️ | +/// | 5 | `any` | `GetSetting` | ⚠️ Yes ⚠️ | +/// | 6 | `any` | `SetSetting` | ⚠️ Yes ⚠️ | +/// | 7 | `any` | `ObjectRequest` | ⚠️ Yes ⚠️ | +/// | 8 | `typed` | `typed` | No | +pub struct OperationHandlerRules<'a> { + object_kind: &'a str, + operation_name: &'a str, + handlers: &'a RuntimeHandlers, +} + +impl<'o> OperationHandlerRules<'o> { + pub fn new( + object_kind: &'o str, + operation_name: &'o str, + handlers: &'o RuntimeHandlers, + ) -> Self { + Self { + object_kind, + operation_name, + handlers, + } + } + + pub async fn handle( + &self, + runtime_state: &RuntimeState, + object: &str, + operation_payload: &[u8], + ) -> Result> { + // object_kind: `any` + // operation_kind: `typed` + if let Some(_handler) = self + .handlers + .operation_handlers + .get(&ObjectOperationPair::new("any", self.operation_name)) + { + todo!() + } + + // object_kind: `typed` + // operation_kind: `any` + if let Some(_handler) = self + .handlers + .operation_handlers + .get(&ObjectOperationPair::new(self.object_kind, "any")) + {} + + // object_kind: `any` + // operation_kind: `any` + if let Some(_handler) = self + .handlers + .operation_handlers + .get(&ObjectOperationPair::new("any", "any")) + {} + + // ⚠️ Special Case ⚠️ + // object_kind: `any` + // operation_kind: `GetValue` + if self.operation_name == "get_value" { + let operation: GetValue = serde_json::from_slice(operation_payload).unwrap(); + let _guard = trace_span!( + "get_value handler resolving", + object = self.object_kind, + value = operation.value_name + ) + .entered(); + + if let Some((domain, callback)) = self.handlers.value_getters.get( + &ObjectValuePair::new(self.object_kind, &operation.value_name), + ) { + trace_span!( + "get_value handler.", + object = self.object_kind, + value_name = operation.value_name + ); + + let object_vtable = domain + .object_vtable(self.object_kind) + .ok_or_else(|| OperationError::Unhandled)?; + trace!("Resolved object vtable for {}", self.object_kind); + + let _value_vtable = domain + .value_vtable(self.object_kind, &operation.value_name) + .ok_or_else(|| OperationError::Unhandled)?; + trace!( + "Resolved value vtable for {}::{}", + self.object_kind, + operation.value_name + ); + + // let object = unsafe { (object_vtable.from_str)(object) } + // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; + + // let _guard = debug_span!("get_value handler"); + + // let result = unsafe { + // (callback.func)( + // callback.callback_ptr, + // runtime_state, + // &domain.plugin.state, + // object, + // ) + // } + // .await; + + // match result { + // Ok(value) => return Ok(value.into()), + // Err(_err) => todo!(), + // } + + todo!() + } else { + trace!("Failed to resolve handler."); + } + } + + // ⚠️ Special Case ⚠️ + // object_kind: `any` + // operation_kind: `GetSetting` + if self.operation_name == "get_setting" { + let operation: GetSetting = serde_json::from_slice(operation_payload).unwrap(); + let _guard = trace_span!( + "get_setting handler resolving", + object = self.object_kind, + setting = operation.setting_name + ) + .entered(); + + if let Some((domain, callback)) = self.handlers.setting_getters.get( + &ObjectSettingPair::new(self.object_kind, &operation.setting_name), + ) { + trace_span!( + "get_setting handler.", + object = self.object_kind, + setting_name = operation.setting_name + ); + + let object_vtable = domain + .object_vtable(self.object_kind) + .ok_or_else(|| OperationError::Unhandled)?; + trace!("Resolved object vtable for {}", self.object_kind); + + let _setting_vtable = domain + .setting_vtable(self.object_kind, &operation.setting_name) + .ok_or_else(|| OperationError::Unhandled)?; + trace!("Resolved setting vtable for {}", operation.setting_name); + + todo!() + + // let object = unsafe { (object_vtable.from_str)(object) } + // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; + + // let _guard = debug_span!("get_value handler"); + + // let result = unsafe { + // (callback.func())( + // callback.callback_ptr, + // runtime_state, + // &domain.plugin.state, + // object, + // ) + // } + // .await; + + // match result { + // Ok(value) => { + // let vtable = unsafe { (value.vtable.get_setting_vtable)() }; + // let return_value: Value = serde_json::from_slice(unsafe { + // (value.vtable.serialize)(value).unwrap().as_ref() + // }) + // .unwrap(); + + // todo!() + + // // return Ok(unsafe { + // // AnySuccess::from_raw( + // // FFIBox::from_box(Box::new(return_value)).untyped(), + // // vtable, + // // ) + // // }); + // } + // Err(_err) => todo!(), + // } + } else { + trace!("Failed to resolve handler."); + } + } + + // ⚠️ Special Case ⚠️ + // object_kind: `any` + // operation_kind: `SetSetting` + self.operation_name == "set_setting"; + + // ⚠️ Special Case ⚠️ + // object_kind: `any` + // operation_kind: `ObjectRequest` + self.operation_name == "object_request"; + + // object_kind: `typed` + // operation_kind: `typed` + if let Some((domain, handler)) = + self.handlers + .operation_handlers + .get(&ObjectOperationPair::new( + self.object_kind, + self.operation_name, + )) + { + let _guard = trace_span!("typed_typed handler resolved").entered(); + + let object_vtable = domain + .object_vtable(self.object_kind) + .ok_or_else(|| OperationError::Unhandled)?; + trace!("Resolved object vtable for {}", self.object_kind); + + let operation_vtable = domain + .operation_vtable(self.object_kind, self.operation_name) + .ok_or_else(|| OperationError::Unhandled)?; + trace!( + "Resolved operation vtable for {}::{}", + self.object_kind, + self.operation_name + ); + + todo!() + + // let object = unsafe { (object_vtable.from_str)(object) } + // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; + // let operation = unsafe { (operation_vtable.deserialize)(operation_payload) } + // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; + // trace!("Parsed operation data"); + + // let _guard = debug_span!("calling handler").entered(); + // let result = unsafe { + // (handler.func)( + // handler.callback_ptr, + // runtime_state, + // &domain.plugin.state, + // object, + // operation, + // ) + // }; + + // return result.await; + } + + Err(OperationError::Unhandled) + } +} diff --git a/giterated-core/src/state.rs b/giterated-core/src/state.rs index 77beb51..57cf29e 100644 --- a/giterated-core/src/state.rs +++ b/giterated-core/src/state.rs @@ -13,3 +13,120 @@ impl FromState for StateExtractor { todo!() } } + +use giterated_abi::prelude::*; +use giterated_abi::value_ex::FfiValueUntyped; +use giterated_abi::vtable::ObjectABI; +use giterated_abi::vtable::VTable; + +#[repr(transparent)] +pub struct State { + inner: StateHandle, +} + +#[repr(transparent)] +struct StateHandle { + state: FfiValue<()>, +} + +#[repr(C)] +struct StateItem { + /// The pointer to the next item. + /// + /// `next_item` is most likely always an `FfiValue>` and that's how we free them. + next_item: *const StateItem<()>, + pub state_uuid: u128, + pub state: T, +} + +impl Drop for State { + fn drop(&mut self) { + let state_manager = unsafe { StateManager::new(self) }; + + for state in state_manager {} + } +} + +struct StateManager<'s> { + state: &'s mut State, + last: Option, +} + +impl<'s> StateManager<'s> { + pub unsafe fn new(handle: &'s mut State) -> Self { + todo!() + } + + pub unsafe fn write_state(&mut self, state: S) -> Self { + todo!() + } + + pub unsafe fn get_state(&mut self) -> Option<&S> { + todo!() + } +} + +impl<'s> Iterator for StateManager<'s> { + type Item = StateItem<()>; + + fn next(&mut self) -> Option> { + todo!() + } +} + +pub trait StateUUID { + fn uuid() -> u128; + + fn unsafe_hint_copy() -> Option { + None + } +} + +/// State values for the current execution domain. 99.99% of the time this means "plugin-specific" +/// +/// The remainder 0.01% of the time it refers to the daemon's runtime domain. +pub struct DomainState(StateItem<()>); + +impl StateUUID for DomainState { + fn uuid() -> u128 { + todo!() + } +} + +pub struct RuntimeState(StateItem<&'static VTable>); + +impl StateUUID for RuntimeState { + fn uuid() -> u128 { + todo!() + } +} + +impl RuntimeState { + pub fn queue_insert_state(&mut self, state: S) { + todo!() + } +} + +pub struct Runtime { + pub queue_insert_state: unsafe extern "C" fn(state_uuid: u128, state: FfiValueUntyped), +} + +impl ObjectABI for Runtime { + type VTable = Runtime; +} + +pub trait FromState: Sized { + fn from_state(state: &mut State) -> Result; +} + +impl FromState for T { + fn from_state(state: &mut State) -> Result { + todo!() + } +} + +impl FromState for Option { + fn from_state(state: &mut State) -> Result { + todo!() + } +} diff --git a/giterated-core/src/types/mod.rs b/giterated-core/src/types/mod.rs new file mode 100644 index 0000000..8ecb3c7 --- /dev/null +++ b/giterated-core/src/types/mod.rs @@ -0,0 +1,77 @@ +#[derive(Default, Clone)] +pub struct TypeMetadata { + pub objects: HashMap<&'static str, &'static VTable>, + pub operations: HashMap, &'static VTable>, + pub settings: HashMap, &'static VTable>, + pub values: HashMap, &'static VTable>, +} + +impl TypeMetadata { + pub unsafe fn from_static() -> &'static Self { + giterated_static_runtime::get_type_metadata_reference() + .cast::() + .as_ref() + } + + pub fn register_object(&mut self, object_kind: &'static str, vtable: &'static VTable) { + trace!("Registering type metadata for {}", object_kind); + + self.objects.insert(object_kind, vtable); + } + + pub fn register_operation( + &mut self, + object_kind: &'static str, + operation_name: &'static str, + vtable: &'static VTable, + ) { + trace!( + "Registering operation metadata for {}::{}", + object_kind, + operation_name + ); + + self.operations.insert( + ObjectOperationPair { + object_kind, + operation_name, + }, + vtable, + ); + } + + pub fn register_setting( + &mut self, + object_kind: &'static str, + setting_name: &'static str, + vtable: &'static VTable, + ) { + trace!("Registering setting {}::{}", object_kind, setting_name); + + self.settings.insert( + ObjectSettingPair { + object_kind, + setting_name, + }, + vtable, + ); + } + + pub fn register_value( + &mut self, + object_kind: &'static str, + value_name: &'static str, + vtable: &'static VTable, + ) { + trace!("Registering value {}::{}", object_kind, value_name); + + self.values.insert( + ObjectValuePair { + object_kind, + value_name, + }, + vtable, + ); + } +} + diff --git a/giterated-macros/Cargo.toml b/giterated-macros/Cargo.toml new file mode 100644 index 0000000..bfaaae6 --- /dev/null +++ b/giterated-macros/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "giterated-macros" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +quote = "1" +syn = "2" \ No newline at end of file diff --git a/giterated-macros/src/lib.rs b/giterated-macros/src/lib.rs new file mode 100644 index 0000000..f94b617 --- /dev/null +++ b/giterated-macros/src/lib.rs @@ -0,0 +1,40 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, Abi, Attribute, ItemFn}; + +extern crate proc_macro; + +#[proc_macro] +pub fn plugin(metadata: TokenStream) -> TokenStream { + emit_plugin_api().into() +} + +#[proc_macro_attribute] +pub fn plugin_init(attribute: TokenStream, item: TokenStream) -> TokenStream { + let mut input = parse_macro_input!(item as ItemFn); + + quote! { + #[doc(hidden)] + #[no_mangle] + unsafe extern "C" fn __plugin_init() { + #input.sig.ident() + } + } + .into() +} + +fn emit_plugin_api() -> impl Into { + quote! { + #[doc(hidden)] + #[no_mangle] + unsafe extern "C" fn __load_runtime_vtable(vtable: &'static ::giterated_abi::VTable) { + todo!() + } + + #[doc(hidden)] + #[no_mangle] + unsafe extern "C" fn __get_plugin_vtable() -> &'static ::giterated_abi::VTable { + todo!() + } + } +} diff --git a/giterated-models/src/object.rs b/giterated-models/src/object.rs index 262efdd..03a054f 100644 --- a/giterated-models/src/object.rs +++ b/giterated-models/src/object.rs @@ -115,3 +115,18 @@ impl Object { + pub object_kind: &'s str, + pub operation_name: &'s str, +} + +impl<'s> ObjectOperationPair<'s> { + pub fn new(object_kind: &'s str, operation_name: &'s str) -> Self { + Self { + object_kind, + operation_name, + } + } +} diff --git a/giterated-models/src/settings/mod.rs b/giterated-models/src/settings/mod.rs index 78c416d..bd3119c 100644 --- a/giterated-models/src/settings/mod.rs +++ b/giterated-models/src/settings/mod.rs @@ -9,5 +9,17 @@ pub trait Setting: Serialize + DeserializeOwned + Send + Sync { fn name() -> &'static str; } -#[derive(Debug, Clone)] -pub struct AnySetting(pub Arc); +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +pub struct ObjectSettingPair<'s> { + pub object_kind: &'s str, + pub setting_name: &'s str, +} + +impl<'s> ObjectSettingPair<'s> { + pub fn new(object_kind: &'s str, setting_name: &'s str) -> Self { + Self { + object_kind, + setting_name, + } + } +} diff --git a/giterated-models/src/update/mod.rs b/giterated-models/src/update/mod.rs index 7fce100..5e31c23 100644 --- a/giterated-models/src/update/mod.rs +++ b/giterated-models/src/update/mod.rs @@ -1,22 +1,7 @@ -use crate::value::AnyValue; - mod instance; mod repository; mod user; -pub struct ValueUpdate { - pub object: String, - pub value_name: String, - pub value: AnyValue<()>, -} - -#[allow(unused)] -pub struct SettingUpdate { - object: String, - value_name: String, - value: AnyValue<()>, -} - pub enum GiteratedUpdateKind { Instance, Repository, diff --git a/giterated-models/src/value.rs b/giterated-models/src/value.rs index 888145f..5ca6069 100644 --- a/giterated-models/src/value.rs +++ b/giterated-models/src/value.rs @@ -39,31 +39,17 @@ impl> GiteratedOp type Failure = GetValueError; } -#[derive(Debug, Clone, Deserialize, Serialize)] -#[serde(transparent)] -pub struct AnyValue { - value: Value, - #[serde(skip)] - _marker: PhantomData, +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +pub struct ObjectValuePair<'s> { + pub object_kind: &'s str, + pub value_name: &'s str, } -impl AnyValue { - pub unsafe fn from_raw(value: Value) -> Self { +impl<'s> ObjectValuePair<'s> { + pub fn new(object_kind: &'s str, value_name: &'s str) -> Self { Self { - value, - _marker: Default::default(), + object_kind, + value_name, } } - - pub fn into_inner(self) -> Value { - self.value - } -} - -impl GiteratedObjectValue for AnyValue { - type Object = O; - - fn value_name() -> &'static str { - todo!() - } } diff --git a/giterated-plugin/Cargo.toml b/giterated-plugin/Cargo.toml index 93a9741..d483138 100644 --- a/giterated-plugin/Cargo.toml +++ b/giterated-plugin/Cargo.toml @@ -11,7 +11,7 @@ anyhow = "1" thiserror = "1" tracing = "0.1" giterated-models = { path = "../giterated-models" } -giterated-static-runtime = { path = "giterated-static-runtime" } +giterated-static-runtime = { path = "../giterated-runtime/giterated-static-runtime" } giterated-abi = { path = "../giterated-abi" } semver = "*" serde_json = "1.0" @@ -19,4 +19,4 @@ async-trait = "0.1" serde = "*" futures-util = "0.3.30" tokio = { version = "1.32", features = [ "full" ] } -giterated-macros = { path = "giterated-macros" } \ No newline at end of file +giterated-macros = { path = "../giterated-macros" } \ No newline at end of file diff --git a/giterated-plugin/giterated-macros/Cargo.toml b/giterated-plugin/giterated-macros/Cargo.toml deleted file mode 100644 index a8d1cd3..0000000 --- a/giterated-plugin/giterated-macros/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "giterated-macros" -version = "0.1.0" -edition = "2021" - -[lib] -proc-macro = true - -[dependencies] -quote = "1.0" \ No newline at end of file diff --git a/giterated-plugin/giterated-macros/src/lib.rs b/giterated-plugin/giterated-macros/src/lib.rs deleted file mode 100644 index b2344b2..0000000 --- a/giterated-plugin/giterated-macros/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -use proc_macro::TokenStream; - -extern crate proc_macro; - -#[proc_macro] -pub fn plugin(metadata: TokenStream) -> TokenStream { - "".parse().unwrap() -} - -#[proc_macro_attribute] -pub fn plugin_init(attribute: TokenStream, item: TokenStream) -> TokenStream { - "".parse().unwrap() -} \ No newline at end of file diff --git a/giterated-plugin/giterated-plugin-sys/Cargo.toml b/giterated-plugin/giterated-plugin-sys/Cargo.toml deleted file mode 100644 index 83ea865..0000000 --- a/giterated-plugin/giterated-plugin-sys/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "giterated-plugin-sys" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -giterated-plugin = { path = "../." } -tracing = "0.1" -giterated-models = { path = "../../giterated-models" } -giterated-abi = { path = "../../giterated-abi" } diff --git a/giterated-plugin/giterated-plugin-sys/src/lib.rs b/giterated-plugin/giterated-plugin-sys/src/lib.rs deleted file mode 100644 index 1ba8196..0000000 --- a/giterated-plugin/giterated-plugin-sys/src/lib.rs +++ /dev/null @@ -1,302 +0,0 @@ -mod local_runtime; - -use giterated_abi::{ - callback::{Callback, CallbackPtr}, - result::FfiError, - value_ex::FfiValueUntyped, - vtable::{ - operation::{IntoOperationVTable, OperationVTable}, - IntoObjectVTable, IntoSettingVTable, IntoValueVTable, Object, ObjectVTable, SettingVTable, - VTable, ValueVTable, - }, - FfiValueRef, -}; -use giterated_models::{ - object::GiteratedObject, operation::GiteratedOperation, settings::Setting, - value::GiteratedObjectValue, -}; -use giterated_plugin::{ - callback::{ - IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter, - IntoPluginValueGetter, OperationHandlerCallback, SettingGetterCallback, - ValueGetterCallback, - }, - handle::PluginInitializationState, - new_stack::PluginState, - vtable::Initialization, -}; -use tracing::trace_span; - -pub struct PluginStackBuilder { - init_state: *mut PluginInitializationState, - vtable: &'static VTable, - state: S, -} - -impl PluginStackBuilder { - pub fn new( - plugin_state: S, - state: *mut PluginInitializationState, - vtable: &'static VTable, - ) -> PluginStackBuilder { - PluginStackBuilder { - 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(), - O::VTABLE - ) - }; - - 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(), - >::VTABLE, - ) - } - - 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(), - OS::VTABLE, - ) - } - - 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(), - OS::VTABLE, - ) - } - - 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(), - V::VTABLE, - ) - } - - // unsafe { - // (self.vtable.value_getter)( - // self.init_state, - // O::object_name(), - // V::value_name(), - // ValueGetterCallback::new::(handler), - // ) - // } - - self - } - - pub fn operation< - 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::(); - - unsafe { - (self.vtable.register_setting)( - self.init_state, - O::object_name(), - OS::name(), - OS::VTABLE, - ) - }; - - 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 { - 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 - } -} - -#[derive(Clone, Copy)] -pub struct ValueSettingGetterCallback; - -impl Callback for ValueSettingGetterCallback { - type CallbackFunc = unsafe extern "C" fn( - callback: CallbackPtr, - state: &PluginState, - object: FfiValueRef, - ) -> Result; -} - -pub trait ValueSettingGetter { - unsafe extern "C" fn get_value( - callback: CallbackPtr, - state: &PluginState, - object: FfiValueRef, - ) -> 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: FfiValueRef, - ) -> Result { - // let result = HG::get_setting(callback, state, object)?; - - // let setting = *result.transmute_owned::(); - - todo!(); - - // Ok(NewAnyValue::new(setting)) - } - - fn callback_ptr(&self) -> CallbackPtr { - todo!() - } -} diff --git a/giterated-plugin/giterated-plugin-sys/src/local_runtime.rs b/giterated-plugin/giterated-plugin-sys/src/local_runtime.rs deleted file mode 100644 index 8b13789..0000000 --- a/giterated-plugin/giterated-plugin-sys/src/local_runtime.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/giterated-plugin/giterated-static-runtime/Cargo.toml b/giterated-plugin/giterated-static-runtime/Cargo.toml deleted file mode 100644 index b7cdeab..0000000 --- a/giterated-plugin/giterated-static-runtime/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "giterated-static-runtime" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/giterated-plugin/giterated-static-runtime/src/lib.rs b/giterated-plugin/giterated-static-runtime/src/lib.rs deleted file mode 100644 index 1fd008b..0000000 --- a/giterated-plugin/giterated-static-runtime/src/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::{mem::MaybeUninit, ptr::NonNull}; - -struct RuntimePointer(NonNull<()>); - -unsafe impl Send for RuntimePointer {} -unsafe impl Sync for RuntimePointer {} - -static mut GITERATED_RUNTIME: MaybeUninit = MaybeUninit::zeroed(); - -pub unsafe fn initialize_runtime(runtime_pointer: *mut ()) { - GITERATED_RUNTIME.write(RuntimePointer(NonNull::new(runtime_pointer).unwrap())); -} - -pub unsafe fn get_runtime_reference() -> NonNull<()> { - GITERATED_RUNTIME.assume_init_read().0 -} - -static mut GITERATED_TYPE_METADATA: MaybeUninit = MaybeUninit::zeroed(); - -pub unsafe fn initialize_type_metadata(runtime_pointer: *mut ()) { - GITERATED_TYPE_METADATA.write(RuntimePointer(NonNull::new(runtime_pointer).unwrap())); -} - -pub unsafe fn get_type_metadata_reference() -> NonNull<()> { - GITERATED_TYPE_METADATA.assume_init_read().0 -} diff --git a/giterated-plugin/src/callback/mod.rs b/giterated-plugin/src/callback/mod.rs deleted file mode 100644 index f0a963f..0000000 --- a/giterated-plugin/src/callback/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -mod operation; - -use giterated_models::{ - error::OperationError, - object::{GiteratedObject, Object, ObjectRequestError}, - object_backend::ObjectBackend, - operation::{GiteratedOperation, OperationState}, -}; -use std::fmt::Debug; - -pub use operation::*; -mod value; -pub use value::*; -mod setting; -pub use setting::*; - -use crate::{ - new_stack::{PluginState, Runtime}, - vtable::RuntimeVTable, -}; \ No newline at end of file diff --git a/giterated-plugin/src/callback/operation.rs b/giterated-plugin/src/callback/operation.rs deleted file mode 100644 index 395e3c8..0000000 --- a/giterated-plugin/src/callback/operation.rs +++ /dev/null @@ -1,212 +0,0 @@ -use giterated_abi::{ - callback::{Callback, CallbackPtr}, - result::FfiResult, - value_ex::FfiValueUntyped, - vtable::{operation::Operation, Object}, - FfiValueMut, FfiValueRef, -}; -use giterated_models::{ - error::OperationError, - object::GiteratedObject, - operation::{GiteratedOperation, OperationState}, -}; - -use crate::{ - future::{RuntimeFuture, RuntimeFuturesExt}, - new_stack::{handle::RuntimeHandle, PluginState}, - state::{FromState, State, StateUUID}, -}; - -use std::{any::type_name, fmt::Debug, future::Future}; - -use super::RuntimeState; - -pub struct OperationHandlerCallback(FfiValueUntyped); - -impl Callback for OperationHandlerCallback { - type CallbackFunc = unsafe extern "C" fn( - CallbackPtr, - state: FfiValueMut, - object: FfiValueRef, - operation: FfiValueRef, - ) -> RuntimeFuture< - FfiResult>, - >; -} - -impl OperationHandlerCallback { - // pub fn new< - // S, - // O: GiteratedObject, - // D: GiteratedOperation, - // A, - // T: IntoPluginOperationHandler, - // >( - // handler: T, - // ) -> Self { - // OperationHandlerCallback(unsafe { CallbackPtr::from_raw(&handler, T::handle as _) }) - // } -} - -pub trait IntoPluginOperationHandler, A> { - unsafe extern "C" fn handle( - callback_ptr: CallbackPtr, - state: FfiValueMut, - object: FfiValueRef, - operation: FfiValueRef, - ) -> 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, - state: FfiValueMut, - object: FfiValueRef, - operation: FfiValueRef, - ) -> RuntimeFuture>> { - todo!() - // 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 { - // todo!() - // // 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 ()) } - - todo!() - } -} - -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, - state: FfiValueMut, - object: FfiValueRef, - operation: FfiValueRef, - ) -> 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, - state: FfiValueMut, - object: FfiValueRef, - operation: FfiValueRef, - ) -> RuntimeFuture>> { - todo!() - } - - fn callback_ptr(&self) -> CallbackPtr { - todo!() - } -} - -pub trait FromOperationState: Sized { - fn from_operation_state( - state: &mut State, - object: &O, - operation: &D, - ) -> Result>; -} - -pub struct StateExtractor(T); - -impl FromState for StateExtractor { - fn from_state(state: &mut State) -> Result { - todo!() - } -} - -// pub trait FromOperationState: Sized { -// fn from_operation_state( -// operation_state: &OperationState, -// state: &mut State, -// object: &O, -// operation: &D, -// ) -> Result>; -// } - -// impl FromOperationState for RuntimeHandle { -// fn from_operation_state( -// _operation_state: &OperationState, -// state: &mut State, -// _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, -// state: &mut State, -// object: &O, -// operation: &D, -// ) -> Result> { -// Ok(T::from_operation_state(operation_state, runtime_state, object, operation).ok()) -// } -// } diff --git a/giterated-plugin/src/callback/setting.rs b/giterated-plugin/src/callback/setting.rs deleted file mode 100644 index 849b2f7..0000000 --- a/giterated-plugin/src/callback/setting.rs +++ /dev/null @@ -1,185 +0,0 @@ -use std::future::Future; - -use giterated_abi::{ - callback::{Callback, CallbackPtr}, - value_ex::FfiValueUntyped, - vtable::{Object, Setting}, - FfiValueMut, FfiValueRef, -}; -use giterated_models::{error::OperationError, object::GiteratedObject}; - -use crate::{ - future::{RuntimeFuture, RuntimeFuturesExt}, - new_stack::PluginState, - state::State, -}; - -use super::RuntimeState; - -pub struct SettingGetterCallback(FfiValueUntyped); - -impl Callback for SettingGetterCallback { - type CallbackFunc = unsafe extern "C" fn( - CallbackPtr, - state: FfiValueMut, - object: FfiValueRef, - ) -> 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, - state: FfiValueMut, - object: FfiValueRef, - ) -> RuntimeFuture>; - - fn callback_ptr(&self) -> CallbackPtr { - // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } - todo!() - } -} - -impl IntoPluginSettingGetter for F -where - Fut: Future>> + Send + Sync + 'static, - S: Clone + Send + Sync + 'static, - O: GiteratedObject + Send + Sync + 'static, - OS: giterated_models::settings::Setting + Send + Sync + 'static, - F: Fn(S, O) -> Fut + Send + Sync + 'static, -{ - unsafe extern "C" fn get_setting( - callback: CallbackPtr, - state: FfiValueMut, - mut object: FfiValueRef, - ) -> 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!(), - // }, - // } - - todo!() - // }) - } -} - -pub trait IntoPluginSettingSetter { - unsafe extern "C" fn set_setting( - callback_ptr: CallbackPtr, - state: &PluginState, - object: FfiValueRef, - setting: Setting, - ) -> RuntimeFuture>; - - fn callback_ptr(&self) -> CallbackPtr { - // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } - todo!() - } -} - -impl IntoPluginSettingSetter for F -where - Fut: Future>>, - S: Clone, - O: GiteratedObject, - OS: giterated_models::settings::Setting, - F: Fn(S, O, OS) -> Fut, -{ - unsafe extern "C" fn set_setting( - callback: CallbackPtr, - state: &PluginState, - mut object: FfiValueRef, - _setting: Setting, - ) -> 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(FfiValueUntyped); - -impl Callback for SettingChangeCallback { - type CallbackFunc = unsafe extern "C" fn( - &PluginState, - object: FfiValueRef, - setting_name: &str, - new_setting: Setting, - ); -} - -pub trait IntoSettingChangeCallback { - unsafe extern "C" fn setting_changed( - state: &PluginState, - object: FfiValueRef, - setting_name: &str, - new_setting: Setting, - ); -} - -impl IntoSettingChangeCallback for F { - unsafe extern "C" fn setting_changed( - _state: &PluginState, - _object: FfiValueRef, - _setting_name: &str, - _new_setting: Setting, - ) { - todo!() - } -} - -// impl SettingChangeCallback { -// pub fn new>() -> Self { -// Self { -// func: T::setting_changed, -// } -// } -// } diff --git a/giterated-plugin/src/callback/value.rs b/giterated-plugin/src/callback/value.rs deleted file mode 100644 index 365a473..0000000 --- a/giterated-plugin/src/callback/value.rs +++ /dev/null @@ -1,136 +0,0 @@ -use std::future::Future; - -use giterated_abi::{ - callback::{Callback, CallbackPtr}, - result::{FfiError, FfiResult}, - vtable::{Object, Value}, - FfiSliceRef, FfiValueMut, FfiValueRef, -}; -use giterated_models::{ - error::OperationError, object::GiteratedObject, value::GiteratedObjectValue, -}; - -use crate::{future::RuntimeFuture, new_stack::PluginState, state::State}; - -use super::{RuntimeState, SettingGetterCallback}; - -#[derive(Copy, Clone)] -pub struct ValueGetterCallback(CallbackPtr); - -impl Callback for ValueGetterCallback { - type CallbackFunc = unsafe extern "C" fn( - CallbackPtr, - state: FfiValueMut, - object: FfiValueRef, - ) -> RuntimeFuture>; -} - -impl ValueGetterCallback { - // pub fn new>(handler: T) -> Self { - // Self { - // func: T::get_value, - // callback_ptr: handler.callback_ptr(), - // } - // } -} - -pub trait IntoPluginValueGetter { - unsafe extern "C" fn get_value( - callback: CallbackPtr, - state: FfiValueMut, - object: FfiValueRef, - ) -> RuntimeFuture>; - - fn callback_ptr(&self) -> CallbackPtr; -} - -impl IntoPluginValueGetter for F -where - Fut: Future>> + Send + Sync, - S: Clone + Send + Sync + 'static, - O: GiteratedObject + 'static, - V: GiteratedObjectValue + Send + Sync + 'static, - F: Fn(S, O) -> Fut + Send + Sync + 'static, -{ - unsafe extern "C" fn get_value( - callback: CallbackPtr, - state: FfiValueMut, - mut object: FfiValueRef, - ) -> RuntimeFuture> { - // let _guard = trace_span!( - // "get_value handler", - // object = O::object_name(), - // value = V::value_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(NewAnyValue::new(success)) }, - // Err(err) => match err { - // OperationError::Operation(_) => todo!(), - // OperationError::Internal(_) => todo!(), - // OperationError::Unhandled => todo!(), - // }, - // } - // }) - - todo!() - } - - fn callback_ptr(&self) -> CallbackPtr { - todo!() - // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } - } -} - -pub struct ValueChangeCallback(CallbackPtr); - -impl Callback for ValueChangeCallback { - type CallbackFunc = unsafe extern "C" fn( - &PluginState, - object: FfiValueRef, - value_name: FfiSliceRef, - new_value: Value, - ) -> RuntimeFuture<()>; -} - -pub trait IntoValueChangeCallback { - unsafe extern "C" fn value_changed( - callback: CallbackPtr, - state: FfiValueMut, - object: FfiValueRef, - value_name: FfiSliceRef, - new_value: Value, - ) -> RuntimeFuture<()>; -} - -impl IntoValueChangeCallback for F { - unsafe extern "C" fn value_changed( - callback: CallbackPtr, - state: FfiValueMut, - _object: FfiValueRef, - _value_name: FfiSliceRef, - _new_value: Value, - ) -> RuntimeFuture<()> { - todo!() - } -} - -impl ValueChangeCallback { - // pub fn new>() -> Self { - // Self { - // func: T::value_changed, - // } - // } -} diff --git a/giterated-plugin/src/future.rs b/giterated-plugin/src/future.rs index bdd9872..c50447a 100644 --- a/giterated-plugin/src/future.rs +++ b/giterated-plugin/src/future.rs @@ -9,8 +9,6 @@ use std::{ task::{Context, RawWaker, RawWakerVTable, Waker}, }; -use crate::{callback::RuntimeState, new_stack::PluginState}; - #[repr(C)] pub struct RuntimeWakerCallback { callback: PluginState, diff --git a/giterated-plugin/src/handle.rs b/giterated-plugin/src/handle.rs deleted file mode 100644 index b99b4c9..0000000 --- a/giterated-plugin/src/handle.rs +++ /dev/null @@ -1,270 +0,0 @@ -use std::{collections::HashMap, marker::PhantomData, sync::Arc}; - -use anyhow::Error; -use dlopen2::wrapper::Container; -use giterated_abi::{ - callback::CallbackPtr, - vtable::{operation::Operation, Object, Setting, VTable, Value}, -}; -use giterated_models::operation::OperationState; -use semver::Version; -use tracing::{debug, trace}; - -use crate::{ - callback::{ - OperationHandlerCallback, RuntimeState, SettingGetterCallback, ValueGetterCallback, - }, - new_stack::{ - ObjectOperationPair, ObjectSettingPair, ObjectValuePair, PluginMeta, PluginState, - TypeMetadata, - }, - vtable::Initialization, - GiteratedPluginApi, -}; - -#[derive(Clone)] -pub struct PluginHandle { - pub meta: PluginMeta, - pub raw: Arc>, - pub domain_metadata: Arc, - pub state: PluginState, -} - -unsafe impl Send for PluginHandle {} -unsafe impl Sync for PluginHandle {} - -impl PluginHandle { - pub fn from_dylib(path: &str) -> Result { - let mut handle = unsafe { Container::load(path) }?; - - // Initialize the raw handle - let init_state = - Self::initialize_raw_handle(&mut handle, &unsafe { RuntimeState::from_static() })?; - - let metadata = Self::get_meta(&mut handle)?; - - let initalization = Self::initialize_registration(&mut handle)?; - - let type_metadata = Box::new(initalization.type_metadata.clone()); - - unsafe { handle.load_type_metadata(unsafe { Box::into_raw(type_metadata).cast() }) }; - - trace!( - "Loaded plugin {} (Version: {})", - metadata.name, - metadata.version - ); - - Ok(Self { - raw: Arc::new(handle), - meta: metadata, - state: init_state, - domain_metadata: todo!(), - }) - } - - /// Builds the Plugin's Substack. - /// - /// Builds the Plugin into a substack, which can then be provided to the Giterated Runtime. - pub fn build_substack(&mut self) -> Result<(), Error> { - todo!() - } - - fn get_meta(handle: &mut Container) -> Result { - let meta = unsafe { handle.plugin_meta() }; - - let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) }; - let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) }; - - let name = std::str::from_utf8(name).unwrap(); - let version = std::str::from_utf8(version).unwrap(); - - Ok(PluginMeta { - name: String::from(name), - version: Version::parse(version).unwrap(), - }) - } - - pub fn initialize_registration( - handle: &mut Container, - ) -> Result { - debug!("Initializing plugin registration..."); - let mut builder = PluginInitializationTable::default(); - - // SAFETY: The lifetime of the returned type is only valid as long - // as the builder that returned it lives - let func_table = unsafe { builder.func_table() }; - - let state = Box::new(PluginInitializationState::new()); - - unsafe { handle.load_initialization_vtable(&func_table) }; - let state = unsafe { handle.initialize_registration(Box::into_raw(state)) }; - - debug!("Plugin handle initialized!"); - Ok(unsafe { *Box::from_raw(state) }) - } - - fn initialize_raw_handle( - handle: &mut Container, - runtime_state: &RuntimeState, - ) -> Result { - debug!("Initializing plugin handle..."); - - let state = unsafe { handle.initialize(runtime_state) }; - - debug!("Plugin handle initialized!"); - - Ok(state) - } -} - -#[derive(Debug, thiserror::Error)] -pub enum CreationError { - #[error("an error occured opening the library {0}")] - LoadingLibrary(#[from] dlopen2::Error), -} - -pub struct PluginSubstackBuilder {} - -#[derive(Default)] -pub struct PluginInitializationState { - pub type_metadata: TypeMetadata, - pub operation_handlers: - HashMap, CallbackPtr>, - pub value_getters: HashMap, CallbackPtr>, - pub setting_getters: HashMap, CallbackPtr>, -} - -impl PluginInitializationState { - pub fn new() -> Self { - Self::default() - } -} - -#[derive(Default)] -pub struct PluginInitializationTable<'a> { - _marker: PhantomData<&'a ()>, -} - -impl<'a> PluginInitializationTable<'a> { - pub unsafe fn func_table(&mut self) -> &'static VTable { - VTable::new(&Initialization { - register_object, - register_operation, - register_setting, - register_value, - operation_handler, - value_getter, - setting_getter, - }) - } -} - -unsafe extern "C" fn register_object( - state: *mut PluginInitializationState, - object_kind: &'static str, - vtable: &'static VTable, -) { - let mut state = Box::from_raw(state); - - state.type_metadata.register_object(object_kind, vtable); - - Box::into_raw(state); -} - -unsafe extern "C" fn register_operation( - state: *mut PluginInitializationState, - object_kind: &'static str, - operation_name: &'static str, - vtable: &'static VTable, -) { - let mut state = Box::from_raw(state); - - state - .type_metadata - .register_operation(object_kind, operation_name, vtable); - - Box::into_raw(state); -} - -unsafe extern "C" fn register_setting( - state: *mut PluginInitializationState, - object_kind: &'static str, - setting_name: &'static str, - vtable: &'static VTable, -) { - let mut state = Box::from_raw(state); - - state - .type_metadata - .register_setting(object_kind, setting_name, vtable); - - Box::into_raw(state); -} - -unsafe extern "C" fn register_value( - state: *mut PluginInitializationState, - object_kind: &'static str, - value_name: &'static str, - vtable: &'static VTable, -) { - let mut state = Box::from_raw(state); - - state - .type_metadata - .register_value(object_kind, value_name, vtable); - - Box::into_raw(state); -} - -unsafe extern "C" fn operation_handler( - state: *mut PluginInitializationState, - object_kind: &'static str, - operation_name: &'static str, - handler: CallbackPtr, -) { - let mut state = Box::from_raw(state); - - trace!("Operation handler for {}::{}", object_kind, operation_name); - - state.operation_handlers.insert( - ObjectOperationPair::new(object_kind, operation_name), - handler, - ); - - Box::into_raw(state); -} - -unsafe extern "C" fn value_getter( - state: *mut PluginInitializationState, - object_kind: &'static str, - value_name: &'static str, - handler: CallbackPtr, -) { - let mut state = Box::from_raw(state); - - trace!("Value getter for {}::{}", object_kind, value_name); - - state - .value_getters - .insert(ObjectValuePair::new(object_kind, value_name), handler); - - Box::into_raw(state); -} - -unsafe extern "C" fn setting_getter( - state: *mut PluginInitializationState, - object_kind: &'static str, - setting_name: &'static str, - handler: CallbackPtr, -) { - let mut state = Box::from_raw(state); - - trace!("Setting getter for {}::{}", object_kind, setting_name); - - state - .setting_getters - .insert(ObjectSettingPair::new(object_kind, setting_name), handler); - - Box::into_raw(state); -} diff --git a/giterated-plugin/src/lib.rs b/giterated-plugin/src/lib.rs index ab541f1..638d2ef 100644 --- a/giterated-plugin/src/lib.rs +++ b/giterated-plugin/src/lib.rs @@ -1,38 +1,10 @@ #![allow(improper_ctypes_definitions)] -pub mod callback; pub mod future; -pub mod handle; -pub mod new_stack; -pub mod state; -pub mod vtable; #[macro_use] extern crate tracing; -use std::{marker::PhantomData, mem::forget}; - -use callback::RuntimeState; -use dlopen2::wrapper::WrapperApi; - -use giterated_abi::vtable::VTable; -use handle::PluginInitializationState; -use new_stack::{FFIPluginMeta, PluginState}; - -use vtable::{HostVTable, Initialization}; - -#[derive(WrapperApi)] -pub struct GiteratedPluginApi { - plugin_meta: unsafe extern "C" fn() -> FFIPluginMeta, - load_host_vtable: unsafe extern "C" fn(vtable: &HostVTable), - load_initialization_vtable: unsafe extern "C" fn(vtable: &'static VTable), - initialize: unsafe extern "C" fn(runtime_state: *const RuntimeState) -> PluginState, - initialize_registration: unsafe extern "C" fn( - init_state: *mut PluginInitializationState, - ) -> *mut PluginInitializationState, - load_type_metadata: unsafe extern "C" fn(metadata: *mut ()), -} - pub mod plugin { pub use giterated_macros::plugin_init as init; } diff --git a/giterated-plugin/src/local.rs b/giterated-plugin/src/local.rs new file mode 100644 index 0000000..1ba8196 --- /dev/null +++ b/giterated-plugin/src/local.rs @@ -0,0 +1,302 @@ +mod local_runtime; + +use giterated_abi::{ + callback::{Callback, CallbackPtr}, + result::FfiError, + value_ex::FfiValueUntyped, + vtable::{ + operation::{IntoOperationVTable, OperationVTable}, + IntoObjectVTable, IntoSettingVTable, IntoValueVTable, Object, ObjectVTable, SettingVTable, + VTable, ValueVTable, + }, + FfiValueRef, +}; +use giterated_models::{ + object::GiteratedObject, operation::GiteratedOperation, settings::Setting, + value::GiteratedObjectValue, +}; +use giterated_plugin::{ + callback::{ + IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter, + IntoPluginValueGetter, OperationHandlerCallback, SettingGetterCallback, + ValueGetterCallback, + }, + handle::PluginInitializationState, + new_stack::PluginState, + vtable::Initialization, +}; +use tracing::trace_span; + +pub struct PluginStackBuilder { + init_state: *mut PluginInitializationState, + vtable: &'static VTable, + state: S, +} + +impl PluginStackBuilder { + pub fn new( + plugin_state: S, + state: *mut PluginInitializationState, + vtable: &'static VTable, + ) -> PluginStackBuilder { + PluginStackBuilder { + 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(), + O::VTABLE + ) + }; + + 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(), + >::VTABLE, + ) + } + + 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(), + OS::VTABLE, + ) + } + + 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(), + OS::VTABLE, + ) + } + + 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(), + V::VTABLE, + ) + } + + // unsafe { + // (self.vtable.value_getter)( + // self.init_state, + // O::object_name(), + // V::value_name(), + // ValueGetterCallback::new::(handler), + // ) + // } + + self + } + + pub fn operation< + 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::(); + + unsafe { + (self.vtable.register_setting)( + self.init_state, + O::object_name(), + OS::name(), + OS::VTABLE, + ) + }; + + 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 { + 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 + } +} + +#[derive(Clone, Copy)] +pub struct ValueSettingGetterCallback; + +impl Callback for ValueSettingGetterCallback { + type CallbackFunc = unsafe extern "C" fn( + callback: CallbackPtr, + state: &PluginState, + object: FfiValueRef, + ) -> Result; +} + +pub trait ValueSettingGetter { + unsafe extern "C" fn get_value( + callback: CallbackPtr, + state: &PluginState, + object: FfiValueRef, + ) -> 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: FfiValueRef, + ) -> Result { + // let result = HG::get_setting(callback, state, object)?; + + // let setting = *result.transmute_owned::(); + + todo!(); + + // Ok(NewAnyValue::new(setting)) + } + + fn callback_ptr(&self) -> CallbackPtr { + todo!() + } +} diff --git a/giterated-plugin/src/new_stack/handle.rs b/giterated-plugin/src/new_stack/handle.rs deleted file mode 100644 index 77e4cca..0000000 --- a/giterated-plugin/src/new_stack/handle.rs +++ /dev/null @@ -1,60 +0,0 @@ -use giterated_models::{ - error::OperationError, - object::{GiteratedObject, Object, ObjectRequestError}, - object_backend::ObjectBackend, - operation::GiteratedOperation, -}; -use std::fmt::Debug; - -use crate::vtable::RuntimeVTable; - -use super::OperationState; - -#[derive(Clone)] -pub struct RuntimeHandle { - runtime_vtable: RuntimeVTable, -} - -impl RuntimeHandle { - pub async fn handle_serialized( - &self, - _object: &str, - _operation_name: &str, - _payload: &[u8], - ) -> Result, OperationError>> { - todo!() - } -} - -impl RuntimeHandle { - pub(crate) unsafe fn from_vtable(runtime_vtable: RuntimeVTable) -> Self { - Self { runtime_vtable } - } -} - -#[async_trait::async_trait(?Send)] -impl ObjectBackend for RuntimeHandle { - async fn object_operation( - &self, - _object: O, - _operation: &str, - _payload: D, - _operation_state: &OperationState, - ) -> Result> - where - O: GiteratedObject + Debug + 'static, - D: GiteratedOperation + Debug + 'static, - D::Success: Clone, - D::Failure: Clone, - { - todo!() - } - - async fn get_object( - &self, - _object_str: &str, - _operation_state: &OperationState, - ) -> Result, OperationError> { - todo!() - } -} diff --git a/giterated-plugin/src/new_stack/mod.rs b/giterated-plugin/src/new_stack/mod.rs deleted file mode 100644 index 4f4f72f..0000000 --- a/giterated-plugin/src/new_stack/mod.rs +++ /dev/null @@ -1,593 +0,0 @@ -pub mod handle; -pub mod operation_walker; -pub mod runtime_handler; - -use std::{collections::HashMap, fmt::Debug, mem::transmute, ptr::null_mut, sync::Arc}; - -use giterated_abi::{ - callback::CallbackPtr, - result::FfiResult, - value_ex::FfiValueUntyped, - vtable::{operation::Operation, Object, Setting, VTable, Value}, - FfiSliceRef, -}; -use giterated_models::{ - error::OperationError, - object::{GiteratedObject, ObjectRequestError}, - operation::{GiteratedOperation, OperationState}, -}; -use semver::Version; - -use tracing::{debug, debug_span, trace, trace_span, warn}; - -use crate::{ - callback::{ - OperationHandlerCallback, RuntimeState, SettingChangeCallback, SettingGetterCallback, - ValueChangeCallback, ValueGetterCallback, - }, - future::RuntimeFuture, - handle::{PluginHandle, PluginInitializationState, PluginInitializationTable}, - vtable::{IntoRuntimeVtable, RuntimeVTable}, -}; - -use self::operation_walker::OperationHandlerRules; - -pub struct State(pub S); - -impl std::ops::Deref for State { - type Target = S; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[derive(Default, Clone)] -pub struct TypeMetadata { - pub objects: HashMap<&'static str, &'static VTable>, - pub operations: HashMap, &'static VTable>, - pub settings: HashMap, &'static VTable>, - pub values: HashMap, &'static VTable>, -} - -impl TypeMetadata { - pub unsafe fn from_static() -> &'static Self { - giterated_static_runtime::get_type_metadata_reference() - .cast::() - .as_ref() - } - - pub fn register_object(&mut self, object_kind: &'static str, vtable: &'static VTable) { - trace!("Registering type metadata for {}", object_kind); - - self.objects.insert(object_kind, vtable); - } - - pub fn register_operation( - &mut self, - object_kind: &'static str, - operation_name: &'static str, - vtable: &'static VTable, - ) { - trace!( - "Registering operation metadata for {}::{}", - object_kind, - operation_name - ); - - self.operations.insert( - ObjectOperationPair { - object_kind, - operation_name, - }, - vtable, - ); - } - - pub fn register_setting( - &mut self, - object_kind: &'static str, - setting_name: &'static str, - vtable: &'static VTable, - ) { - trace!("Registering setting {}::{}", object_kind, setting_name); - - self.settings.insert( - ObjectSettingPair { - object_kind, - setting_name, - }, - vtable, - ); - } - - pub fn register_value( - &mut self, - object_kind: &'static str, - value_name: &'static str, - vtable: &'static VTable, - ) { - trace!("Registering value {}::{}", object_kind, value_name); - - self.values.insert( - ObjectValuePair { - object_kind, - value_name, - }, - vtable, - ); - } -} - -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] -pub struct ObjectOperationPair<'s> { - pub object_kind: &'s str, - pub operation_name: &'s str, -} - -impl<'s> ObjectOperationPair<'s> { - pub fn new(object_kind: &'s str, operation_name: &'s str) -> Self { - Self { - object_kind, - operation_name, - } - } -} - -#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] -pub struct ObjectSettingPair<'s> { - pub object_kind: &'s str, - pub setting_name: &'s str, -} - -impl<'s> ObjectSettingPair<'s> { - pub fn new(object_kind: &'s str, setting_name: &'s str) -> Self { - Self { - object_kind, - setting_name, - } - } -} - -#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] -pub struct ObjectValuePair<'s> { - pub object_kind: &'s str, - pub value_name: &'s str, -} - -impl<'s> ObjectValuePair<'s> { - pub fn new(object_kind: &'s str, value_name: &'s str) -> Self { - Self { - object_kind, - value_name, - } - } -} - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct PluginState { - pub inner: *mut (), -} - -unsafe impl Send for PluginState {} -unsafe impl Sync for PluginState {} - -impl PluginState { - pub unsafe fn transmute_owned(&mut self) -> Box { - Box::from_raw(self.inner as *mut T) - } - - pub unsafe fn transmute_ref(&self) -> &T { - let ptr: *const T = transmute(self.inner); - - ptr.as_ref().unwrap() - } -} - -impl PluginState { - pub fn from(source: S) -> Self { - Self { - inner: Box::into_raw(Box::new(source)) as *mut _, - } - } - - pub unsafe fn from_box(raw: Box) -> Self { - Self { - inner: Box::into_raw(raw) as *mut _, - } - } - - pub unsafe fn from_raw_ptr(raw: *const ()) -> Self { - Self { - inner: raw as *mut (), - } - } - - pub fn null() -> Self { - Self { inner: null_mut() } - } -} - -pub struct Runtime { - plugins: Vec, - handlers: RuntimeHandlers, -} - -pub struct FfiRuntimeMetadata { - runtime: PluginState, -} - -impl IntoRuntimeVtable for Runtime { - unsafe extern "C" fn handle( - _this: PluginState, - _object_kind: FfiSliceRef, - _operation_name: FfiSliceRef, - _object: FfiSliceRef, - _operation_payload: FfiSliceRef<[u8]>, - _operation_state: FfiSliceRef<[u8]>, - ) -> RuntimeFuture>> - { - todo!() - } - - unsafe extern "C" fn get_object( - this: PluginState, - object_str: &str, - operation_state: *mut OperationState, - ) -> FfiResult> { - let runtime_state = unsafe { RuntimeState::from_static() }; - - let type_metada = runtime_state - .vtable - .type_metadata - .as_ref() - .unwrap_or_else(|| { - let runtime = this.transmute_ref::(); - - &runtime.plugins.first().unwrap().domain_metadata - }); - - // for (object_type, object_vtable) in &type_metada.objects { - // if let Ok(object) = (object_vtable.from_str)(object_str) { - // return Ok(object); - // } - // } - - // Err(OperationError::Operation(ObjectRequestError::Invalid)) - - todo!() - } -} - -impl Runtime { - pub fn new() -> Box { - Box::new(Self { - plugins: vec![], - handlers: RuntimeHandlers::default(), - }) - } - - pub fn state(self: &Box) -> RuntimeState { - RuntimeState { - vtable: RuntimeVTable { - runtime: PluginState::from(self), - handle_fn: ::handle, - get_object: ::get_object, - type_metadata: unsafe { TypeMetadata::from_static() }, - }, - } - } - - pub fn insert_plugin( - &mut self, - mut plugin: PluginHandle, - mut initialization: PluginInitializationState, - ) { - let _guard = debug_span!("inserting plugin", meta = debug(&plugin.meta)).entered(); - - for (pair, callback) in initialization.operation_handlers.drain() { - let _guard = - trace_span!("processing operation handler callbacks", pair = debug(pair)).entered(); - - if self - .handlers - .operation_handlers - .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) - .is_some() - { - warn!("Warning! Insertion of handler for overwrote a previous handler.") - } - - trace!("Insertion of operation handler successful") - } - - for (pair, callback) in initialization.value_getters.drain() { - let _guard = - trace_span!("processing value getter callbacks", pair = debug(pair)).entered(); - - if self - .handlers - .value_getters - .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) - .is_some() - { - warn!("Warning! Insertion of handler for overwrote a previous handler.") - } - - trace!("Insertion of operation handler successful") - } - - for (pair, callback) in initialization.setting_getters { - let _guard = - trace_span!("processing setting getter callbacks", pair = debug(pair)).entered(); - - if self - .handlers - .setting_getters - .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) - .is_some() - { - warn!("Warning! Insertion of setting handler for overwrote a previous handler.") - } - - trace!("Insertion of setting handler successful") - } - - self.plugins.push(plugin); - } - - pub fn init(self: Box) { - unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) } - } - - // pub async fn handle( - // &self, - // object_kind: &str, - // operation_name: &str, - // object: &str, - // operation_payload: &[u8], - // operation_state: &OperationState, - // ) -> Result> { - // let rules = self.handlers.handle_operation(object_kind, operation_name); - - // let state = self.state(operation_state); - - // rules.handle(&state, object, operation_payload).await - // } - - pub fn handle_typed>( - &self, - _object: O, - _operation: D, - ) -> Result> { - todo!() - } -} - -#[derive(Default)] -pub struct RuntimeHandlers { - operation_handlers: HashMap< - ObjectOperationPair<'static>, - (RuntimeDomain, CallbackPtr), - >, - value_getters: - HashMap, (RuntimeDomain, CallbackPtr)>, - setting_getters: - HashMap, (RuntimeDomain, CallbackPtr)>, - value_change: - HashMap, (RuntimeDomain, CallbackPtr)>, - setting_change: - HashMap, (RuntimeDomain, CallbackPtr)>, -} - -unsafe impl Send for RuntimeHandlers {} -unsafe impl Sync for RuntimeHandlers {} - -impl RuntimeHandlers { - pub fn operation_handler( - &mut self, - pair: ObjectOperationPair<'static>, - handler: CallbackPtr, - domain: RuntimeDomain, - ) { - trace!( - "Inserting operation handler for {}::{}", - pair.object_kind, - pair.operation_name - ); - - // There can only be one handler per operation (at least for now?), send a warning if - // a newly registered handler overwrites the previous handler. - if self - .operation_handlers - .insert(pair, (domain, handler)) - .is_some() - { - debug!("Warning! A newly inserted operation handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.operation_name); - } - } - - pub fn value_getter( - &mut self, - pair: ObjectValuePair<'static>, - handler: CallbackPtr, - domain: RuntimeDomain, - ) { - trace!( - "Inserting value getter for {}::{}", - pair.object_kind, - pair.value_name - ); - - if self.value_getters.insert(pair, (domain, handler)).is_some() { - debug!( - "Warning! A newly inserted value getter for {}::{} overwrites a previous handler.", - pair.object_kind, pair.value_name - ); - } - } - - pub fn setting_getter( - &mut self, - pair: ObjectSettingPair<'static>, - handler: CallbackPtr, - domain: RuntimeDomain, - ) { - trace!( - "Inserting setting getter for {}::{}", - pair.object_kind, - pair.setting_name - ); - - if self - .setting_getters - .insert(pair, (domain, handler)) - .is_some() - { - debug!("Warning! A newly inserted setting getter for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name); - } - } - - pub fn value_change( - &mut self, - pair: ObjectValuePair<'static>, - handler: CallbackPtr, - domain: RuntimeDomain, - ) { - trace!( - "Inserting value change handler for {}::{}", - pair.object_kind, - pair.value_name - ); - - if self.value_change.insert(pair, (domain, handler)).is_some() { - debug!("Warning! A newly inserted value change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.value_name); - panic!("Not intended"); - } - } - - pub fn setting_change( - &mut self, - pair: ObjectSettingPair<'static>, - handler: CallbackPtr, - domain: RuntimeDomain, - ) { - trace!( - "Inserting setting change handler for {}::{}", - pair.object_kind, - pair.setting_name - ); - - if self - .setting_change - .insert(pair, (domain, handler)) - .is_some() - { - debug!("Warning! A newly inserted setting change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name); - panic!("Not intended"); - } - } -} - -impl RuntimeHandlers { - pub fn handle_operation<'o>( - &'o self, - object_kind: &'o str, - operation_name: &'o str, - ) -> OperationHandlerRules<'o> { - OperationHandlerRules::new(object_kind, operation_name, self) - } -} - -pub struct RuntimeDomain { - plugin: PluginHandle, -} - -impl RuntimeDomain { - pub fn from_plugin(plugin: &PluginHandle) -> Self { - Self { - plugin: plugin.clone(), - } - } - - pub fn object_vtable(&self, object_kind: &str) -> Option<&'static VTable> { - self.plugin - .domain_metadata - .objects - .get(object_kind) - .copied() - } - - pub fn operation_vtable( - &self, - object_kind: &str, - operation_name: &str, - ) -> Option<&'static VTable> { - self.plugin - .domain_metadata - .operations - .get(&ObjectOperationPair::new(object_kind, operation_name)) - .copied() - } - - pub fn setting_vtable( - &self, - object_kind: &str, - setting_name: &str, - ) -> Option<&'static VTable> { - self.plugin - .domain_metadata - .settings - .get(&ObjectSettingPair::new(object_kind, setting_name)) - .copied() - } - - pub fn value_vtable( - &self, - object_kind: &str, - value_name: &str, - ) -> Option<&'static VTable> { - self.plugin - .domain_metadata - .values - .get(&ObjectValuePair::new(object_kind, value_name)) - .copied() - } -} - -#[derive(Clone, Debug)] -pub struct PluginMeta { - pub name: String, - pub version: Version, -} - -#[repr(C)] -pub struct FFIPluginMeta { - pub name: *const u8, - pub name_len: usize, - pub version: *const u8, - pub version_len: usize, -} - -pub struct RuntimePlugin { - handle: PluginHandle, - type_metadata: Arc, -} - -impl RuntimePlugin { - pub fn plugin_meta(&self) -> PluginMeta { - let meta = unsafe { self.handle.raw.plugin_meta() }; - - let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) }; - let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) }; - - let name = std::str::from_utf8(name).unwrap(); - let version = std::str::from_utf8(version).unwrap(); - - PluginMeta { - name: String::from(name), - version: Version::parse(version).unwrap(), - } - } -} diff --git a/giterated-plugin/src/new_stack/operation_walker.rs b/giterated-plugin/src/new_stack/operation_walker.rs deleted file mode 100644 index e3fb91a..0000000 --- a/giterated-plugin/src/new_stack/operation_walker.rs +++ /dev/null @@ -1,273 +0,0 @@ -use crate::callback::RuntimeState; -use giterated_abi::{result::FfiError, value_ex::FfiValueUntyped}; -use giterated_models::{ - error::OperationError, operation::GiteratedOperation, settings::GetSetting, value::GetValue, -}; - -use serde_json::Value; -use tracing::{debug_span, trace, trace_span}; - -use crate::new_stack::ObjectOperationPair; - -use super::{ObjectSettingPair, ObjectValuePair, RuntimeHandlers}; - -/// A wrapper for operation handling that enforces handling rules. -/// -/// # Handler Resolution -/// In order, handler resolution will be attempted as follows: -/// -/// | Index | object_kind | operation_kind | Special Case? | -/// |-------|-------------|-----------------|---------------| -/// | 1 | `any` | `typed` | No | -/// | 2 | `typed` | `any` | No | -/// | 3 | `any` | `any` | No | -/// | 4 | `any` | `GetValue` | ⚠️ Yes ⚠️ | -/// | 5 | `any` | `GetSetting` | ⚠️ Yes ⚠️ | -/// | 6 | `any` | `SetSetting` | ⚠️ Yes ⚠️ | -/// | 7 | `any` | `ObjectRequest` | ⚠️ Yes ⚠️ | -/// | 8 | `typed` | `typed` | No | -pub struct OperationHandlerRules<'a> { - object_kind: &'a str, - operation_name: &'a str, - handlers: &'a RuntimeHandlers, -} - -impl<'o> OperationHandlerRules<'o> { - pub fn new( - object_kind: &'o str, - operation_name: &'o str, - handlers: &'o RuntimeHandlers, - ) -> Self { - Self { - object_kind, - operation_name, - handlers, - } - } - - pub async fn handle( - &self, - runtime_state: &RuntimeState, - object: &str, - operation_payload: &[u8], - ) -> Result> { - // object_kind: `any` - // operation_kind: `typed` - if let Some(_handler) = self - .handlers - .operation_handlers - .get(&ObjectOperationPair::new("any", self.operation_name)) - { - todo!() - } - - // object_kind: `typed` - // operation_kind: `any` - if let Some(_handler) = self - .handlers - .operation_handlers - .get(&ObjectOperationPair::new(self.object_kind, "any")) - {} - - // object_kind: `any` - // operation_kind: `any` - if let Some(_handler) = self - .handlers - .operation_handlers - .get(&ObjectOperationPair::new("any", "any")) - {} - - // ⚠️ Special Case ⚠️ - // object_kind: `any` - // operation_kind: `GetValue` - if self.operation_name == "get_value" { - let operation: GetValue = serde_json::from_slice(operation_payload).unwrap(); - let _guard = trace_span!( - "get_value handler resolving", - object = self.object_kind, - value = operation.value_name - ) - .entered(); - - if let Some((domain, callback)) = self.handlers.value_getters.get( - &ObjectValuePair::new(self.object_kind, &operation.value_name), - ) { - trace_span!( - "get_value handler.", - object = self.object_kind, - value_name = operation.value_name - ); - - let object_vtable = domain - .object_vtable(self.object_kind) - .ok_or_else(|| OperationError::Unhandled)?; - trace!("Resolved object vtable for {}", self.object_kind); - - let _value_vtable = domain - .value_vtable(self.object_kind, &operation.value_name) - .ok_or_else(|| OperationError::Unhandled)?; - trace!( - "Resolved value vtable for {}::{}", - self.object_kind, - operation.value_name - ); - - // let object = unsafe { (object_vtable.from_str)(object) } - // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; - - // let _guard = debug_span!("get_value handler"); - - // let result = unsafe { - // (callback.func)( - // callback.callback_ptr, - // runtime_state, - // &domain.plugin.state, - // object, - // ) - // } - // .await; - - // match result { - // Ok(value) => return Ok(value.into()), - // Err(_err) => todo!(), - // } - - todo!() - } else { - trace!("Failed to resolve handler."); - } - } - - // ⚠️ Special Case ⚠️ - // object_kind: `any` - // operation_kind: `GetSetting` - if self.operation_name == "get_setting" { - let operation: GetSetting = serde_json::from_slice(operation_payload).unwrap(); - let _guard = trace_span!( - "get_setting handler resolving", - object = self.object_kind, - setting = operation.setting_name - ) - .entered(); - - if let Some((domain, callback)) = self.handlers.setting_getters.get( - &ObjectSettingPair::new(self.object_kind, &operation.setting_name), - ) { - trace_span!( - "get_setting handler.", - object = self.object_kind, - setting_name = operation.setting_name - ); - - let object_vtable = domain - .object_vtable(self.object_kind) - .ok_or_else(|| OperationError::Unhandled)?; - trace!("Resolved object vtable for {}", self.object_kind); - - let _setting_vtable = domain - .setting_vtable(self.object_kind, &operation.setting_name) - .ok_or_else(|| OperationError::Unhandled)?; - trace!("Resolved setting vtable for {}", operation.setting_name); - - todo!() - - // let object = unsafe { (object_vtable.from_str)(object) } - // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; - - // let _guard = debug_span!("get_value handler"); - - // let result = unsafe { - // (callback.func())( - // callback.callback_ptr, - // runtime_state, - // &domain.plugin.state, - // object, - // ) - // } - // .await; - - // match result { - // Ok(value) => { - // let vtable = unsafe { (value.vtable.get_setting_vtable)() }; - // let return_value: Value = serde_json::from_slice(unsafe { - // (value.vtable.serialize)(value).unwrap().as_ref() - // }) - // .unwrap(); - - // todo!() - - // // return Ok(unsafe { - // // AnySuccess::from_raw( - // // FFIBox::from_box(Box::new(return_value)).untyped(), - // // vtable, - // // ) - // // }); - // } - // Err(_err) => todo!(), - // } - } else { - trace!("Failed to resolve handler."); - } - } - - // ⚠️ Special Case ⚠️ - // object_kind: `any` - // operation_kind: `SetSetting` - self.operation_name == "set_setting"; - - // ⚠️ Special Case ⚠️ - // object_kind: `any` - // operation_kind: `ObjectRequest` - self.operation_name == "object_request"; - - // object_kind: `typed` - // operation_kind: `typed` - if let Some((domain, handler)) = - self.handlers - .operation_handlers - .get(&ObjectOperationPair::new( - self.object_kind, - self.operation_name, - )) - { - let _guard = trace_span!("typed_typed handler resolved").entered(); - - let object_vtable = domain - .object_vtable(self.object_kind) - .ok_or_else(|| OperationError::Unhandled)?; - trace!("Resolved object vtable for {}", self.object_kind); - - let operation_vtable = domain - .operation_vtable(self.object_kind, self.operation_name) - .ok_or_else(|| OperationError::Unhandled)?; - trace!( - "Resolved operation vtable for {}::{}", - self.object_kind, - self.operation_name - ); - - todo!() - - // let object = unsafe { (object_vtable.from_str)(object) } - // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; - // let operation = unsafe { (operation_vtable.deserialize)(operation_payload) } - // .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?; - // trace!("Parsed operation data"); - - // let _guard = debug_span!("calling handler").entered(); - // let result = unsafe { - // (handler.func)( - // handler.callback_ptr, - // runtime_state, - // &domain.plugin.state, - // object, - // operation, - // ) - // }; - - // return result.await; - } - - Err(OperationError::Unhandled) - } -} diff --git a/giterated-plugin/src/new_stack/runtime_handler.rs b/giterated-plugin/src/new_stack/runtime_handler.rs deleted file mode 100644 index 1d92afd..0000000 --- a/giterated-plugin/src/new_stack/runtime_handler.rs +++ /dev/null @@ -1,27 +0,0 @@ -use giterated_abi::{ - value_ex::FfiValueUntyped, - vtable::{operation::Operation, VTable}, -}; -use giterated_models::error::OperationError; - -use super::PluginState; - -#[repr(C)] -struct RuntimeHandleInner { - state: PluginState, - handle_serialized: unsafe extern "C" fn( - object_kind: &str, - operation_name: &str, - object: &str, - operation_payload: &[u8], - ) -> HandlerResult, -} - -unsafe impl Send for RuntimeHandleInner {} -unsafe impl Sync for RuntimeHandleInner {} - -#[repr(C)] -struct HandlerResult { - operation_vtable: VTable, - result: Result>, -} diff --git a/giterated-plugin/src/state.rs b/giterated-plugin/src/state.rs deleted file mode 100644 index f996944..0000000 --- a/giterated-plugin/src/state.rs +++ /dev/null @@ -1,116 +0,0 @@ -use giterated_abi::prelude::*; -use giterated_abi::value_ex::FfiValueUntyped; -use giterated_abi::vtable::ObjectABI; -use giterated_abi::vtable::VTable; - -#[repr(transparent)] -pub struct State { - inner: StateHandle, -} - -#[repr(transparent)] -struct StateHandle { - state: FfiValue<()>, -} - -#[repr(C)] -struct StateItem { - /// The pointer to the next item. - /// - /// `next_item` is most likely always an `FfiValue>` and that's how we free them. - next_item: *const StateItem<()>, - pub state_uuid: u128, - pub state: T, -} - -impl Drop for State { - fn drop(&mut self) { - let state_manager = unsafe { StateManager::new(self) }; - - for state in state_manager {} - } -} - -struct StateManager<'s> { - state: &'s mut State, - last: Option, -} - -impl<'s> StateManager<'s> { - pub unsafe fn new(handle: &'s mut State) -> Self { - todo!() - } - - pub unsafe fn write_state(&mut self, state: S) -> Self { - todo!() - } - - pub unsafe fn get_state(&mut self) -> Option<&S> { - todo!() - } -} - -impl<'s> Iterator for StateManager<'s> { - type Item = StateItem<()>; - - fn next(&mut self) -> Option> { - todo!() - } -} - -pub trait StateUUID { - fn uuid() -> u128; - - fn unsafe_hint_copy() -> Option { - None - } -} - -/// State values for the current execution domain. 99.99% of the time this means "plugin-specific" -/// -/// The remainder 0.01% of the time it refers to the daemon's runtime domain. -pub struct DomainState(StateItem<()>); - -impl StateUUID for DomainState { - fn uuid() -> u128 { - todo!() - } -} - -pub struct RuntimeState(StateItem<&'static VTable>); - -impl StateUUID for RuntimeState { - fn uuid() -> u128 { - todo!() - } -} - -impl RuntimeState { - pub fn queue_insert_state(&mut self, state: S) { - todo!() - } -} - -pub struct Runtime { - pub queue_insert_state: unsafe extern "C" fn(state_uuid: u128, state: FfiValueUntyped), -} - -impl ObjectABI for Runtime { - type VTable = Runtime; -} - -pub trait FromState: Sized { - fn from_state(state: &mut State) -> Result; -} - -impl FromState for T { - fn from_state(state: &mut State) -> Result { - todo!() - } -} - -impl FromState for Option { - fn from_state(state: &mut State) -> Result { - todo!() - } -} diff --git a/giterated-plugin/src/vtable/host.rs b/giterated-plugin/src/vtable/host.rs deleted file mode 100644 index 099cae8..0000000 --- a/giterated-plugin/src/vtable/host.rs +++ /dev/null @@ -1,72 +0,0 @@ -use giterated_abi::{ - callback::CallbackPtr, - vtable::{operation::Operation, Object, ObjectABI, Setting, VTable, Value}, -}; - -use crate::{ - callback::{OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback}, - handle::PluginInitializationState, -}; -use std::fmt::Debug; - -#[repr(C)] -pub struct HostVTable {} - -#[repr(C)] -#[derive(Clone, Copy)] -pub struct Initialization { - pub register_object: - unsafe extern "C" fn(*mut PluginInitializationState, &'static str, &'static VTable), - pub register_operation: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - &'static VTable, - ), - pub register_setting: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - &'static VTable, - ), - pub register_value: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - &'static VTable, - ), - - pub operation_handler: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - CallbackPtr, - ), - - pub value_getter: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - CallbackPtr, - ), - - pub setting_getter: unsafe extern "C" fn( - *mut PluginInitializationState, - &'static str, - &'static str, - CallbackPtr, - ), -} - -impl ObjectABI for Initialization { - type VTable = Initialization; -} - -impl Debug for Initialization { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("InitializationVTable").finish() - } -} - -unsafe impl Sync for Initialization {} -unsafe impl Send for Initialization {} diff --git a/giterated-plugin/src/vtable/mod.rs b/giterated-plugin/src/vtable/mod.rs deleted file mode 100644 index f27c252..0000000 --- a/giterated-plugin/src/vtable/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Giterated's VTable System -//! -//! Docs here? :) -mod runtime; -pub use runtime::*; -mod host; -pub use host::*; diff --git a/giterated-plugin/src/vtable/runtime.rs b/giterated-plugin/src/vtable/runtime.rs deleted file mode 100644 index 1592e03..0000000 --- a/giterated-plugin/src/vtable/runtime.rs +++ /dev/null @@ -1,56 +0,0 @@ -use giterated_abi::{ - result::{FfiError, FfiResult}, - value_ex::FfiValueUntyped, - vtable::Object, - FfiSliceRef, -}; -use giterated_models::{ - error::OperationError, object::ObjectRequestError, operation::OperationState, -}; - -use crate::{ - future::RuntimeFuture, - new_stack::{PluginState, TypeMetadata}, -}; - -#[derive(Clone, Copy)] -pub struct RuntimeVTable { - pub(crate) runtime: PluginState, - pub(crate) type_metadata: *const TypeMetadata, - pub(crate) handle_fn: unsafe extern "C" fn( - PluginState, - FfiSliceRef, - FfiSliceRef, - FfiSliceRef, - FfiSliceRef<[u8]>, - FfiSliceRef<[u8]>, - ) -> RuntimeFuture< - FfiResult>, - >, - pub(crate) get_object: - unsafe extern "C" fn( - PluginState, - &str, - *mut OperationState, - ) -> FfiResult>, -} - -unsafe impl Send for RuntimeVTable {} -unsafe impl Sync for RuntimeVTable {} - -pub trait IntoRuntimeVtable { - unsafe extern "C" fn handle( - this: PluginState, - object_kind: FfiSliceRef, - operation_name: FfiSliceRef, - object: FfiSliceRef, - operation_payload: FfiSliceRef<[u8]>, - operation_state: FfiSliceRef<[u8]>, - ) -> RuntimeFuture>>; - - unsafe extern "C" fn get_object( - this: PluginState, - object_str: &str, - operation_state: *mut OperationState, - ) -> FfiResult>; -} diff --git a/giterated-runtime/giterated-static-runtime/Cargo.toml b/giterated-runtime/giterated-static-runtime/Cargo.toml new file mode 100644 index 0000000..b7cdeab --- /dev/null +++ b/giterated-runtime/giterated-static-runtime/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "giterated-static-runtime" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/giterated-runtime/giterated-static-runtime/src/lib.rs b/giterated-runtime/giterated-static-runtime/src/lib.rs new file mode 100644 index 0000000..1fd008b --- /dev/null +++ b/giterated-runtime/giterated-static-runtime/src/lib.rs @@ -0,0 +1,26 @@ +use std::{mem::MaybeUninit, ptr::NonNull}; + +struct RuntimePointer(NonNull<()>); + +unsafe impl Send for RuntimePointer {} +unsafe impl Sync for RuntimePointer {} + +static mut GITERATED_RUNTIME: MaybeUninit = MaybeUninit::zeroed(); + +pub unsafe fn initialize_runtime(runtime_pointer: *mut ()) { + GITERATED_RUNTIME.write(RuntimePointer(NonNull::new(runtime_pointer).unwrap())); +} + +pub unsafe fn get_runtime_reference() -> NonNull<()> { + GITERATED_RUNTIME.assume_init_read().0 +} + +static mut GITERATED_TYPE_METADATA: MaybeUninit = MaybeUninit::zeroed(); + +pub unsafe fn initialize_type_metadata(runtime_pointer: *mut ()) { + GITERATED_TYPE_METADATA.write(RuntimePointer(NonNull::new(runtime_pointer).unwrap())); +} + +pub unsafe fn get_type_metadata_reference() -> NonNull<()> { + GITERATED_TYPE_METADATA.assume_init_read().0 +} diff --git a/giterated-runtime/src/api.rs b/giterated-runtime/src/api.rs new file mode 100644 index 0000000..be2de7b --- /dev/null +++ b/giterated-runtime/src/api.rs @@ -0,0 +1,11 @@ +#[derive(WrapperApi)] +pub struct GiteratedPluginApi { + plugin_meta: unsafe extern "C" fn() -> FFIPluginMeta, + load_host_vtable: unsafe extern "C" fn(vtable: &HostVTable), + load_initialization_vtable: unsafe extern "C" fn(vtable: &'static VTable), + initialize: unsafe extern "C" fn(runtime_state: *const RuntimeState) -> PluginState, + initialize_registration: unsafe extern "C" fn( + init_state: *mut PluginInitializationState, + ) -> *mut PluginInitializationState, + load_type_metadata: unsafe extern "C" fn(metadata: *mut ()), +} \ No newline at end of file diff --git a/giterated-runtime/src/handle.rs b/giterated-runtime/src/handle.rs new file mode 100644 index 0000000..b99b4c9 --- /dev/null +++ b/giterated-runtime/src/handle.rs @@ -0,0 +1,270 @@ +use std::{collections::HashMap, marker::PhantomData, sync::Arc}; + +use anyhow::Error; +use dlopen2::wrapper::Container; +use giterated_abi::{ + callback::CallbackPtr, + vtable::{operation::Operation, Object, Setting, VTable, Value}, +}; +use giterated_models::operation::OperationState; +use semver::Version; +use tracing::{debug, trace}; + +use crate::{ + callback::{ + OperationHandlerCallback, RuntimeState, SettingGetterCallback, ValueGetterCallback, + }, + new_stack::{ + ObjectOperationPair, ObjectSettingPair, ObjectValuePair, PluginMeta, PluginState, + TypeMetadata, + }, + vtable::Initialization, + GiteratedPluginApi, +}; + +#[derive(Clone)] +pub struct PluginHandle { + pub meta: PluginMeta, + pub raw: Arc>, + pub domain_metadata: Arc, + pub state: PluginState, +} + +unsafe impl Send for PluginHandle {} +unsafe impl Sync for PluginHandle {} + +impl PluginHandle { + pub fn from_dylib(path: &str) -> Result { + let mut handle = unsafe { Container::load(path) }?; + + // Initialize the raw handle + let init_state = + Self::initialize_raw_handle(&mut handle, &unsafe { RuntimeState::from_static() })?; + + let metadata = Self::get_meta(&mut handle)?; + + let initalization = Self::initialize_registration(&mut handle)?; + + let type_metadata = Box::new(initalization.type_metadata.clone()); + + unsafe { handle.load_type_metadata(unsafe { Box::into_raw(type_metadata).cast() }) }; + + trace!( + "Loaded plugin {} (Version: {})", + metadata.name, + metadata.version + ); + + Ok(Self { + raw: Arc::new(handle), + meta: metadata, + state: init_state, + domain_metadata: todo!(), + }) + } + + /// Builds the Plugin's Substack. + /// + /// Builds the Plugin into a substack, which can then be provided to the Giterated Runtime. + pub fn build_substack(&mut self) -> Result<(), Error> { + todo!() + } + + fn get_meta(handle: &mut Container) -> Result { + let meta = unsafe { handle.plugin_meta() }; + + let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) }; + let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) }; + + let name = std::str::from_utf8(name).unwrap(); + let version = std::str::from_utf8(version).unwrap(); + + Ok(PluginMeta { + name: String::from(name), + version: Version::parse(version).unwrap(), + }) + } + + pub fn initialize_registration( + handle: &mut Container, + ) -> Result { + debug!("Initializing plugin registration..."); + let mut builder = PluginInitializationTable::default(); + + // SAFETY: The lifetime of the returned type is only valid as long + // as the builder that returned it lives + let func_table = unsafe { builder.func_table() }; + + let state = Box::new(PluginInitializationState::new()); + + unsafe { handle.load_initialization_vtable(&func_table) }; + let state = unsafe { handle.initialize_registration(Box::into_raw(state)) }; + + debug!("Plugin handle initialized!"); + Ok(unsafe { *Box::from_raw(state) }) + } + + fn initialize_raw_handle( + handle: &mut Container, + runtime_state: &RuntimeState, + ) -> Result { + debug!("Initializing plugin handle..."); + + let state = unsafe { handle.initialize(runtime_state) }; + + debug!("Plugin handle initialized!"); + + Ok(state) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum CreationError { + #[error("an error occured opening the library {0}")] + LoadingLibrary(#[from] dlopen2::Error), +} + +pub struct PluginSubstackBuilder {} + +#[derive(Default)] +pub struct PluginInitializationState { + pub type_metadata: TypeMetadata, + pub operation_handlers: + HashMap, CallbackPtr>, + pub value_getters: HashMap, CallbackPtr>, + pub setting_getters: HashMap, CallbackPtr>, +} + +impl PluginInitializationState { + pub fn new() -> Self { + Self::default() + } +} + +#[derive(Default)] +pub struct PluginInitializationTable<'a> { + _marker: PhantomData<&'a ()>, +} + +impl<'a> PluginInitializationTable<'a> { + pub unsafe fn func_table(&mut self) -> &'static VTable { + VTable::new(&Initialization { + register_object, + register_operation, + register_setting, + register_value, + operation_handler, + value_getter, + setting_getter, + }) + } +} + +unsafe extern "C" fn register_object( + state: *mut PluginInitializationState, + object_kind: &'static str, + vtable: &'static VTable, +) { + let mut state = Box::from_raw(state); + + state.type_metadata.register_object(object_kind, vtable); + + Box::into_raw(state); +} + +unsafe extern "C" fn register_operation( + state: *mut PluginInitializationState, + object_kind: &'static str, + operation_name: &'static str, + vtable: &'static VTable, +) { + let mut state = Box::from_raw(state); + + state + .type_metadata + .register_operation(object_kind, operation_name, vtable); + + Box::into_raw(state); +} + +unsafe extern "C" fn register_setting( + state: *mut PluginInitializationState, + object_kind: &'static str, + setting_name: &'static str, + vtable: &'static VTable, +) { + let mut state = Box::from_raw(state); + + state + .type_metadata + .register_setting(object_kind, setting_name, vtable); + + Box::into_raw(state); +} + +unsafe extern "C" fn register_value( + state: *mut PluginInitializationState, + object_kind: &'static str, + value_name: &'static str, + vtable: &'static VTable, +) { + let mut state = Box::from_raw(state); + + state + .type_metadata + .register_value(object_kind, value_name, vtable); + + Box::into_raw(state); +} + +unsafe extern "C" fn operation_handler( + state: *mut PluginInitializationState, + object_kind: &'static str, + operation_name: &'static str, + handler: CallbackPtr, +) { + let mut state = Box::from_raw(state); + + trace!("Operation handler for {}::{}", object_kind, operation_name); + + state.operation_handlers.insert( + ObjectOperationPair::new(object_kind, operation_name), + handler, + ); + + Box::into_raw(state); +} + +unsafe extern "C" fn value_getter( + state: *mut PluginInitializationState, + object_kind: &'static str, + value_name: &'static str, + handler: CallbackPtr, +) { + let mut state = Box::from_raw(state); + + trace!("Value getter for {}::{}", object_kind, value_name); + + state + .value_getters + .insert(ObjectValuePair::new(object_kind, value_name), handler); + + Box::into_raw(state); +} + +unsafe extern "C" fn setting_getter( + state: *mut PluginInitializationState, + object_kind: &'static str, + setting_name: &'static str, + handler: CallbackPtr, +) { + let mut state = Box::from_raw(state); + + trace!("Setting getter for {}::{}", object_kind, setting_name); + + state + .setting_getters + .insert(ObjectSettingPair::new(object_kind, setting_name), handler); + + Box::into_raw(state); +} diff --git a/giterated-runtime/src/lib.rs b/giterated-runtime/src/lib.rs index e69de29..8650e76 100644 --- a/giterated-runtime/src/lib.rs +++ b/giterated-runtime/src/lib.rs @@ -0,0 +1,394 @@ +pub struct Runtime { + plugins: Vec, + handlers: RuntimeHandlers, +} + +pub struct FfiRuntimeMetadata { + runtime: PluginState, +} + +impl IntoRuntimeVtable for Runtime { + unsafe extern "C" fn handle( + _this: PluginState, + _object_kind: FfiSliceRef, + _operation_name: FfiSliceRef, + _object: FfiSliceRef, + _operation_payload: FfiSliceRef<[u8]>, + _operation_state: FfiSliceRef<[u8]>, + ) -> RuntimeFuture>> + { + todo!() + } + + unsafe extern "C" fn get_object( + this: PluginState, + object_str: &str, + operation_state: *mut OperationState, + ) -> FfiResult> { + let runtime_state = unsafe { RuntimeState::from_static() }; + + let type_metada = runtime_state + .vtable + .type_metadata + .as_ref() + .unwrap_or_else(|| { + let runtime = this.transmute_ref::(); + + &runtime.plugins.first().unwrap().domain_metadata + }); + + // for (object_type, object_vtable) in &type_metada.objects { + // if let Ok(object) = (object_vtable.from_str)(object_str) { + // return Ok(object); + // } + // } + + // Err(OperationError::Operation(ObjectRequestError::Invalid)) + + todo!() + } +} + +impl Runtime { + pub fn new() -> Box { + Box::new(Self { + plugins: vec![], + handlers: RuntimeHandlers::default(), + }) + } + + pub fn state(self: &Box) -> RuntimeState { + RuntimeState { + vtable: RuntimeVTable { + runtime: PluginState::from(self), + handle_fn: ::handle, + get_object: ::get_object, + type_metadata: unsafe { TypeMetadata::from_static() }, + }, + } + } + + pub fn insert_plugin( + &mut self, + mut plugin: PluginHandle, + mut initialization: PluginInitializationState, + ) { + let _guard = debug_span!("inserting plugin", meta = debug(&plugin.meta)).entered(); + + for (pair, callback) in initialization.operation_handlers.drain() { + let _guard = + trace_span!("processing operation handler callbacks", pair = debug(pair)).entered(); + + if self + .handlers + .operation_handlers + .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) + .is_some() + { + warn!("Warning! Insertion of handler for overwrote a previous handler.") + } + + trace!("Insertion of operation handler successful") + } + + for (pair, callback) in initialization.value_getters.drain() { + let _guard = + trace_span!("processing value getter callbacks", pair = debug(pair)).entered(); + + if self + .handlers + .value_getters + .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) + .is_some() + { + warn!("Warning! Insertion of handler for overwrote a previous handler.") + } + + trace!("Insertion of operation handler successful") + } + + for (pair, callback) in initialization.setting_getters { + let _guard = + trace_span!("processing setting getter callbacks", pair = debug(pair)).entered(); + + if self + .handlers + .setting_getters + .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) + .is_some() + { + warn!("Warning! Insertion of setting handler for overwrote a previous handler.") + } + + trace!("Insertion of setting handler successful") + } + + self.plugins.push(plugin); + } + + pub fn init(self: Box) { + unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) } + } + + // pub async fn handle( + // &self, + // object_kind: &str, + // operation_name: &str, + // object: &str, + // operation_payload: &[u8], + // operation_state: &OperationState, + // ) -> Result> { + // let rules = self.handlers.handle_operation(object_kind, operation_name); + + // let state = self.state(operation_state); + + // rules.handle(&state, object, operation_payload).await + // } + + pub fn handle_typed>( + &self, + _object: O, + _operation: D, + ) -> Result> { + todo!() + } +} + +#[derive(Default)] +pub struct RuntimeHandlers { + operation_handlers: HashMap< + ObjectOperationPair<'static>, + (RuntimeDomain, CallbackPtr), + >, + value_getters: + HashMap, (RuntimeDomain, CallbackPtr)>, + setting_getters: + HashMap, (RuntimeDomain, CallbackPtr)>, + value_change: + HashMap, (RuntimeDomain, CallbackPtr)>, + setting_change: + HashMap, (RuntimeDomain, CallbackPtr)>, +} + +unsafe impl Send for RuntimeHandlers {} +unsafe impl Sync for RuntimeHandlers {} + +impl RuntimeHandlers { + pub fn operation_handler( + &mut self, + pair: ObjectOperationPair<'static>, + handler: CallbackPtr, + domain: RuntimeDomain, + ) { + trace!( + "Inserting operation handler for {}::{}", + pair.object_kind, + pair.operation_name + ); + + // There can only be one handler per operation (at least for now?), send a warning if + // a newly registered handler overwrites the previous handler. + if self + .operation_handlers + .insert(pair, (domain, handler)) + .is_some() + { + debug!("Warning! A newly inserted operation handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.operation_name); + } + } + + pub fn value_getter( + &mut self, + pair: ObjectValuePair<'static>, + handler: CallbackPtr, + domain: RuntimeDomain, + ) { + trace!( + "Inserting value getter for {}::{}", + pair.object_kind, + pair.value_name + ); + + if self.value_getters.insert(pair, (domain, handler)).is_some() { + debug!( + "Warning! A newly inserted value getter for {}::{} overwrites a previous handler.", + pair.object_kind, pair.value_name + ); + } + } + + pub fn setting_getter( + &mut self, + pair: ObjectSettingPair<'static>, + handler: CallbackPtr, + domain: RuntimeDomain, + ) { + trace!( + "Inserting setting getter for {}::{}", + pair.object_kind, + pair.setting_name + ); + + if self + .setting_getters + .insert(pair, (domain, handler)) + .is_some() + { + debug!("Warning! A newly inserted setting getter for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name); + } + } + + pub fn value_change( + &mut self, + pair: ObjectValuePair<'static>, + handler: CallbackPtr, + domain: RuntimeDomain, + ) { + trace!( + "Inserting value change handler for {}::{}", + pair.object_kind, + pair.value_name + ); + + if self.value_change.insert(pair, (domain, handler)).is_some() { + debug!("Warning! A newly inserted value change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.value_name); + panic!("Not intended"); + } + } + + pub fn setting_change( + &mut self, + pair: ObjectSettingPair<'static>, + handler: CallbackPtr, + domain: RuntimeDomain, + ) { + trace!( + "Inserting setting change handler for {}::{}", + pair.object_kind, + pair.setting_name + ); + + if self + .setting_change + .insert(pair, (domain, handler)) + .is_some() + { + debug!("Warning! A newly inserted setting change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name); + panic!("Not intended"); + } + } +} + +impl RuntimeHandlers { + pub fn handle_operation<'o>( + &'o self, + object_kind: &'o str, + operation_name: &'o str, + ) -> OperationHandlerRules<'o> { + OperationHandlerRules::new(object_kind, operation_name, self) + } +} + +pub struct RuntimeDomain { + plugin: PluginHandle, +} + +impl RuntimeDomain { + pub fn from_plugin(plugin: &PluginHandle) -> Self { + Self { + plugin: plugin.clone(), + } + } + + pub fn object_vtable(&self, object_kind: &str) -> Option<&'static VTable> { + self.plugin + .domain_metadata + .objects + .get(object_kind) + .copied() + } + + pub fn operation_vtable( + &self, + object_kind: &str, + operation_name: &str, + ) -> Option<&'static VTable> { + self.plugin + .domain_metadata + .operations + .get(&ObjectOperationPair::new(object_kind, operation_name)) + .copied() + } + + pub fn setting_vtable( + &self, + object_kind: &str, + setting_name: &str, + ) -> Option<&'static VTable> { + self.plugin + .domain_metadata + .settings + .get(&ObjectSettingPair::new(object_kind, setting_name)) + .copied() + } + + pub fn value_vtable( + &self, + object_kind: &str, + value_name: &str, + ) -> Option<&'static VTable> { + self.plugin + .domain_metadata + .values + .get(&ObjectValuePair::new(object_kind, value_name)) + .copied() + } +} + +#[derive(Clone, Debug)] +pub struct PluginMeta { + pub name: String, + pub version: Version, +} + +#[repr(C)] +pub struct FFIPluginMeta { + pub name: *const u8, + pub name_len: usize, + pub version: *const u8, + pub version_len: usize, +} + +pub struct RuntimePlugin { + handle: PluginHandle, + type_metadata: Arc, +} + +impl RuntimePlugin { + pub fn plugin_meta(&self) -> PluginMeta { + let meta = unsafe { self.handle.raw.plugin_meta() }; + + let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) }; + let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) }; + + let name = std::str::from_utf8(name).unwrap(); + let version = std::str::from_utf8(version).unwrap(); + + PluginMeta { + name: String::from(name), + version: Version::parse(version).unwrap(), + } + } +} + +#[derive(WrapperApi)] +pub struct GiteratedPluginApi { + plugin_meta: unsafe extern "C" fn() -> FFIPluginMeta, + load_host_vtable: unsafe extern "C" fn(vtable: &HostVTable), + load_initialization_vtable: unsafe extern "C" fn(vtable: &'static VTable), + initialize: unsafe extern "C" fn(runtime_state: *const RuntimeState) -> PluginState, + initialize_registration: unsafe extern "C" fn( + init_state: *mut PluginInitializationState, + ) -> *mut PluginInitializationState, + load_type_metadata: unsafe extern "C" fn(metadata: *mut ()), +} diff --git a/plugins/example-plugin/Cargo.toml b/plugins/example-plugin/Cargo.toml index 58728c7..61de762 100644 --- a/plugins/example-plugin/Cargo.toml +++ b/plugins/example-plugin/Cargo.toml @@ -12,8 +12,7 @@ crate-type = ["dylib"] [dependencies] giterated-plugin = { path = "../../giterated-plugin" } -giterated-plugin-sys = { path = "../../giterated-plugin/giterated-plugin-sys" } -giterated-static-runtime = { path = "../../giterated-plugin/giterated-static-runtime" } +giterated-static-runtime = { path = "../../giterated-runtime/giterated-static-runtime" } dlopen2 = "0.6" tracing-subscriber = "0.3" giterated-models = { path = "../../giterated-models" } diff --git a/plugins/example-plugin/src/lib.rs b/plugins/example-plugin/src/lib.rs index fad47e2..723a922 100644 --- a/plugins/example-plugin/src/lib.rs +++ b/plugins/example-plugin/src/lib.rs @@ -1,5 +1,9 @@ use anyhow::Error; -use giterated_models::{error::OperationError, object::{ObjectRequest, ObjectRequestError, ObjectResponse}, user::{DisplayName, User}}; +use giterated_models::{ + error::OperationError, + object::{ObjectRequest, ObjectRequestError, ObjectResponse}, + user::{DisplayName, User}, +}; use giterated_plugin::{new_stack::State, plugin}; plugin!( @@ -20,9 +24,7 @@ struct PluginState; pub fn init(builder: &mut PluginStackBuilder) -> Result<(), Error> { builder.insert_state(State); - builder - .object::() - .object::(); + builder.object::().object::(); builder.value(value_getter); builder.setting_getter(setting_getter); @@ -33,14 +35,14 @@ pub fn init(builder: &mut PluginStackBuilder) -> Result<(), Error> { async fn handler( object: User, operation: ObjectRequest, - state_extractor: State + state_extractor: State, ) -> Result> { todo!() } async fn setting_getter( object: User, - state_extractor: State + state_extractor: State, ) -> Result> { todo!() -} \ No newline at end of file +} diff --git a/plugins/giterated-backend/Cargo.toml b/plugins/giterated-backend/Cargo.toml index c48052e..93356a7 100644 --- a/plugins/giterated-backend/Cargo.toml +++ b/plugins/giterated-backend/Cargo.toml @@ -13,7 +13,6 @@ anyhow = "1" thiserror = "1" sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-native-tls", "postgres", "macros", "migrate", "chrono" ] } tokio = { version = "1.32", features = [ "full" ] } -giterated-plugin-sys = { path = "../../giterated-plugin/giterated-plugin-sys" } toml = { version = "0.8" } tracing = "0.1" tracing-subscriber = "0.3" diff --git a/plugins/giterated-issues/Cargo.toml b/plugins/giterated-issues/Cargo.toml index 024aef8..2688232 100644 --- a/plugins/giterated-issues/Cargo.toml +++ b/plugins/giterated-issues/Cargo.toml @@ -18,7 +18,6 @@ anyhow = "1" thiserror = "1" sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-native-tls", "postgres", "macros", "migrate", "chrono" ] } tokio = { version = "1.32", features = [ "full" ] } -giterated-plugin-sys = { path = "../../giterated-plugin/giterated-plugin-sys" } toml = { version = "0.8" } tracing = "0.1" tracing-subscriber = "0.3" diff --git a/plugins/giterated-protocol/Cargo.toml b/plugins/giterated-protocol/Cargo.toml index 99353b6..c512ba8 100644 --- a/plugins/giterated-protocol/Cargo.toml +++ b/plugins/giterated-protocol/Cargo.toml @@ -15,7 +15,6 @@ giterated-plugin = { path = "../../giterated-plugin" } giterated-models = { path = "../../giterated-models" } serde = { version = "1.0", features = [ "derive" ]} anyhow = "1" -giterated-plugin-sys = { path = "../../giterated-plugin/giterated-plugin-sys" } toml = { version = "0.8" } tracing = "0.1" tracing-subscriber = "0.3"