diff --git a/Cargo.lock b/Cargo.lock index 9738986..fe33a68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -688,6 +688,9 @@ dependencies = [ [[package]] name = "giterated-abi" version = "0.1.0" +dependencies = [ + "giterated-models", +] [[package]] name = "giterated-backend" @@ -708,6 +711,10 @@ dependencies = [ ] [[package]] +name = "giterated-core" +version = "0.1.0" + +[[package]] name = "giterated-daemon" version = "0.1.0" dependencies = [ @@ -762,6 +769,13 @@ dependencies = [ ] [[package]] +name = "giterated-macros" +version = "0.1.0" +dependencies = [ + "quote", +] + +[[package]] name = "giterated-models" version = "0.1.0" dependencies = [ @@ -794,6 +808,7 @@ dependencies = [ "dlopen2", "futures-util", "giterated-abi", + "giterated-macros", "giterated-models", "giterated-static-runtime", "semver", @@ -808,6 +823,7 @@ dependencies = [ name = "giterated-plugin-sys" version = "0.1.0" dependencies = [ + "giterated-abi", "giterated-models", "giterated-plugin", "tracing", @@ -837,6 +853,10 @@ dependencies = [ ] [[package]] +name = "giterated-runtime" +version = "0.1.0" + +[[package]] name = "giterated-static-runtime" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index f6248a4..4d0237f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,11 @@ [workspace] -members = [ "giterated-abi", +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-plugin/giterated-static-runtime", "giterated-runtime", "plugins/example-plugin", "plugins/giterated-backend", "plugins/giterated-issues", diff --git a/giterated-abi/Cargo.toml b/giterated-abi/Cargo.toml index c377b21..5f1ec2d 100644 --- a/giterated-abi/Cargo.toml +++ b/giterated-abi/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +giterated-models = { path = "../giterated-models"} \ No newline at end of file diff --git a/giterated-abi/src/callback.rs b/giterated-abi/src/callback.rs new file mode 100644 index 0000000..fac3780 --- /dev/null +++ b/giterated-abi/src/callback.rs @@ -0,0 +1,23 @@ +use std::marker::PhantomData; + +pub trait Callback { + type CallbackFunc; +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct CallbackPtr { + callback_ptr: *const (), + func: T::CallbackFunc, + _marker: PhantomData, +} + +impl CallbackPtr { + pub unsafe fn from_raw(data: T, func: T::CallbackFunc) -> Self { + todo!() + } + + pub fn func(&self) -> &T::CallbackFunc { + &self.func + } +} diff --git a/giterated-abi/src/lib.rs b/giterated-abi/src/lib.rs index bddf77c..1452da9 100644 --- a/giterated-abi/src/lib.rs +++ b/giterated-abi/src/lib.rs @@ -81,8 +81,10 @@ //! //! `RuntimeFuture`s drop the associated inner future as they drop. +pub mod callback; mod future; -mod heap; +pub mod heap; +pub mod model_impl; pub mod result; pub mod vtable; use abi_backing::{HeapValueBacking, SliceBacking}; @@ -102,6 +104,7 @@ use guards::{HeapPinnedSlice, HeapPinnedValue, StackPinnedSlice, StackPinnedValu pub mod prelude { pub use crate::Ffi; pub use crate::StackPinned; + pub use crate::*; pub use crate::{FfiSlice, FfiSliceRef, FfiValue, FfiValueRef}; } diff --git a/giterated-abi/src/model_impl/mod.rs b/giterated-abi/src/model_impl/mod.rs new file mode 100644 index 0000000..b53b42b --- /dev/null +++ b/giterated-abi/src/model_impl/mod.rs @@ -0,0 +1,104 @@ +use std::ffi::CStr; + +use giterated_models::{object::GiteratedObject, operation::GiteratedOperation}; + +use crate::{ + result::{FfiError, FfiResult}, + value_ex::{FfiValueRefUntyped, FfiValueUntyped}, + vtable::{ + operation::{IntoOperationVTable, Operation}, + IntoObjectVTable, IntoSettingVTable, IntoValueVTable, Object, Setting, + }, + FfiSlice, FfiSliceRef, FfiValueRef, +}; + +impl IntoObjectVTable for T +where + T: GiteratedObject, +{ + fn object_kind() -> &'static CStr { + todo!() + } + + unsafe extern "C" fn to_str(this: FfiValueRef) -> FfiSlice { + todo!() + } + + unsafe extern "C" fn from_str(from: FfiSliceRef) -> FfiResult { + todo!() + } + + unsafe extern "C" fn home_uri(this: FfiValueRef) -> FfiSlice { + todo!() + } +} + +impl IntoOperationVTable for T +where + T: GiteratedOperation, + O: GiteratedObject, +{ + fn operation_kind() -> &'static CStr { + todo!() + } + + unsafe extern "C" fn operation_serialize( + this: FfiValueRef, + ) -> FfiResult, FfiError> { + todo!() + } + + unsafe extern "C" fn operation_deserialize( + buffer: FfiSliceRef<[u8]>, + ) -> FfiResult { + todo!() + } + + unsafe extern "C" fn success_serialize( + success: FfiValueRefUntyped, + ) -> FfiResult, FfiError> { + todo!() + } + + unsafe extern "C" fn success_deserialize( + buffer: FfiSliceRef<[u8]>, + ) -> FfiResult { + todo!() + } + + unsafe extern "C" fn failure_serialize( + failure: FfiValueRefUntyped, + ) -> FfiResult, FfiError> { + todo!() + } + + unsafe extern "C" fn failure_deserialize( + buffer: FfiSliceRef<[u8]>, + ) -> FfiResult { + todo!() + } +} + +impl IntoValueVTable for T { + unsafe extern "C" fn serialize( + buffer: FfiSliceRef<[u8]>, + ) -> FfiResult { + todo!() + } + + unsafe extern "C" fn deserialize( + this: crate::vtable::Value, + ) -> FfiResult, FfiError> { + todo!() + } +} + +// impl IntoSettingVTable for T { +// unsafe extern "C" fn serialize(this: Setting) -> FfiResult, FfiError> { +// todo!() +// } + +// unsafe extern "C" fn deserialize(buffer: FfiSliceRef<[u8]>) -> FfiResult { +// todo!() +// } +// } diff --git a/giterated-abi/src/result.rs b/giterated-abi/src/result.rs index a5eb8bb..c77e6f9 100644 --- a/giterated-abi/src/result.rs +++ b/giterated-abi/src/result.rs @@ -1,12 +1,12 @@ use crate::FfiSlice; #[repr(C)] -pub enum Result { +pub enum FfiResult { Ok(T), Err(E), } #[repr(C)] -pub struct Error { +pub struct FfiError { last_error: FfiSlice, } diff --git a/giterated-abi/src/vtable/mod.rs b/giterated-abi/src/vtable/mod.rs index b17a1e2..78f7571 100644 --- a/giterated-abi/src/vtable/mod.rs +++ b/giterated-abi/src/vtable/mod.rs @@ -1,6 +1,4 @@ -use std::{ - marker::PhantomData, mem::transmute, ops::Deref -}; +use std::{marker::PhantomData, mem::transmute, ops::Deref}; mod object; pub mod operation; diff --git a/giterated-abi/src/vtable/object.rs b/giterated-abi/src/vtable/object.rs index 06ca5fe..ec9338f 100644 --- a/giterated-abi/src/vtable/object.rs +++ b/giterated-abi/src/vtable/object.rs @@ -1,7 +1,8 @@ -use std::ffi::CStr; +use std::{ffi::CStr, str::FromStr}; use crate::{ - result::{Error, Result}, + result::{FfiError, FfiResult}, + value_ex::FfiValueUntyped, FfiSlice, FfiSliceRef, FfiValueRef, }; @@ -9,10 +10,36 @@ use super::{ObjectABI, VTable}; #[repr(C)] pub struct Object { - inner: (), + inner: FfiValueUntyped, vtable: &'static VTable, } +impl Object { + pub fn home_uri(&self) -> String { + todo!() + } +} + +impl From for Object { + fn from(value: O) -> Self { + todo!() + } +} + +impl ToString for Object { + fn to_string(&self) -> String { + todo!() + } +} + +impl FromStr for Object { + type Err = FfiError; + + fn from_str(s: &str) -> Result { + todo!() + } +} + impl ObjectABI for Object { type VTable = ObjectVTable; } @@ -20,19 +47,21 @@ impl ObjectABI for Object { pub struct ObjectVTable { pub object_kind: &'static CStr, pub to_str: unsafe extern "C" fn(this: FfiValueRef) -> FfiSlice, - pub from_str: unsafe extern "C" fn(from: FfiSliceRef) -> Result, + pub from_str: unsafe extern "C" fn(from: FfiSliceRef) -> FfiResult, pub home_uri: unsafe extern "C" fn(this: FfiValueRef) -> FfiSlice, } impl ObjectVTable { - pub fn new() -> Self { + pub const fn new() -> Self { todo!() } } -pub trait IntoObjectVTable { +pub trait IntoObjectVTable: Sized { + const VTABLE: &'static VTable = VTable::new(&ObjectVTable::new::()); + fn object_kind() -> &'static CStr; unsafe extern "C" fn to_str(this: FfiValueRef) -> FfiSlice; - unsafe extern "C" fn from_str(from: FfiSliceRef) -> Result; + unsafe extern "C" fn from_str(from: FfiSliceRef) -> FfiResult; unsafe extern "C" fn home_uri(this: FfiValueRef) -> FfiSlice; } diff --git a/giterated-abi/src/vtable/operation.rs b/giterated-abi/src/vtable/operation.rs index d41d082..01c0906 100644 --- a/giterated-abi/src/vtable/operation.rs +++ b/giterated-abi/src/vtable/operation.rs @@ -1,7 +1,7 @@ use std::ffi::CStr; use crate::{ - result::{Error, Result}, + result::{FfiError, FfiResult}, value_ex::{FfiValueRefUntyped, FfiValueUntyped}, FfiSlice, FfiSliceRef, FfiValue, FfiValueRef, }; @@ -10,10 +10,24 @@ use super::{ObjectABI, VTable}; #[repr(C)] pub struct Operation { - inner: FfiValue<()>, + inner: FfiValueUntyped, vtable: &'static VTable, } +impl Operation { + pub fn operation_kind(&self) -> &'static str { + todo!() + } + + pub fn serialize(&self) -> Vec { + todo!() + } + + pub fn deserialize_from>(buffer: &[u8]) -> Result { + todo!() + } +} + impl ObjectABI for Operation { type VTable = OperationVTable; } @@ -21,43 +35,69 @@ impl ObjectABI for Operation { pub struct OperationVTable { pub operation_kind: &'static CStr, pub operation_serialize: - unsafe extern "C" fn(this: FfiValueRef) -> Result, Error>, + unsafe extern "C" fn(this: FfiValueRef) -> FfiResult, FfiError>, pub operation_deserialize: - unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> Result, + unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> FfiResult, pub success_serialize: - unsafe extern "C" fn(success: FfiValueRefUntyped) -> Result, Error>, + unsafe extern "C" fn(success: FfiValueRefUntyped) -> FfiResult, FfiError>, pub success_deserialize: - unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> Result, + unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> FfiResult, pub failure_serialize: - unsafe extern "C" fn(failure: FfiValueRefUntyped) -> Result, Error>, + unsafe extern "C" fn(failure: FfiValueRefUntyped) -> FfiResult, FfiError>, pub failure_deserialize: - unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> Result, + unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> FfiResult, } impl OperationVTable { - pub const fn new() -> Self { + pub const fn new>() -> Self { + todo!() + } + + pub fn serialize(&self, operation: Operation) -> Result, FfiError> { + todo!() + } + + pub fn deserialize(&self, buffer: &[u8]) -> Result { + todo!() + } + + pub fn serialize_success(&self, success: FfiValueUntyped) -> Result, FfiError> { + todo!() + } + + pub fn deserialize_success(&self, buffer: &[u8]) -> Result { + todo!() + } + + pub fn serialize_failure(&self, failure: FfiValueUntyped) -> Result, FfiError> { + todo!() + } + + pub fn deserialize_failure(&self, buffer: &[u8]) -> Result { todo!() } } -pub trait IntoOperationVTable { +pub trait IntoOperationVTable: Sized { + const VTABLE: &'static VTable = VTable::new(&OperationVTable::new::()); + fn operation_kind() -> &'static CStr; unsafe extern "C" fn operation_serialize( this: FfiValueRef, - ) -> Result, Error>; + ) -> FfiResult, FfiError>; unsafe extern "C" fn operation_deserialize( buffer: FfiSliceRef<[u8]>, - ) -> Result; + ) -> FfiResult; unsafe extern "C" fn success_serialize( success: FfiValueRefUntyped, - ) -> Result, Error>; + ) -> FfiResult, FfiError>; unsafe extern "C" fn success_deserialize( buffer: FfiSliceRef<[u8]>, - ) -> Result; + ) -> FfiResult; unsafe extern "C" fn failure_serialize( failure: FfiValueRefUntyped, - ) -> Result, Error>; + ) -> FfiResult, FfiError>; unsafe extern "C" fn failure_deserialize( buffer: FfiSliceRef<[u8]>, - ) -> Result; + ) -> FfiResult; } diff --git a/giterated-abi/src/vtable/setting.rs b/giterated-abi/src/vtable/setting.rs index 25d5414..fbfe56b 100644 --- a/giterated-abi/src/vtable/setting.rs +++ b/giterated-abi/src/vtable/setting.rs @@ -1,5 +1,6 @@ use crate::{ - result::{Error, Result}, + result::{FfiError, FfiResult}, + value_ex::FfiValueUntyped, FfiSlice, FfiSliceRef, }; @@ -7,26 +8,46 @@ use super::{ObjectABI, VTable}; #[repr(C)] pub struct Setting { - inner: (), + inner: FfiValueUntyped, vtable: &'static VTable, } +impl From for Setting { + fn from(value: T) -> Self { + todo!() + } +} + impl ObjectABI for Setting { type VTable = SettingVTable; } pub struct SettingVTable { - pub serialize: unsafe extern "C" fn(this: Setting) -> Result, Error>, - pub deserialize: unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> Result, + pub serialize: unsafe extern "C" fn(this: Setting) -> FfiResult, FfiError>, + pub deserialize: + unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> FfiResult, } impl SettingVTable { - pub fn new() -> Self { + pub const fn new() -> Self { + Self { + serialize: S::serialize, + deserialize: S::deserialize + } + } + + pub fn serialize(&self, setting: Setting) -> Result, FfiError> { + todo!() + } + + pub fn deserialize(&self, buffer: &[u8]) -> Result { todo!() } } -pub trait IntoSettingVTable { - unsafe extern "C" fn serialize(this: Setting) -> Result, Error>; - unsafe extern "C" fn deserialize(buffer: FfiSliceRef<[u8]>) -> Result; +pub trait IntoSettingVTable: Sized { + const VTABLE: &'static VTable = VTable::new(&SettingVTable::new::()); + + unsafe extern "C" fn serialize(this: Setting) -> FfiResult, FfiError>; + unsafe extern "C" fn deserialize(buffer: FfiSliceRef<[u8]>) -> FfiResult; } diff --git a/giterated-abi/src/vtable/value.rs b/giterated-abi/src/vtable/value.rs index 56f2b06..1b557cf 100644 --- a/giterated-abi/src/vtable/value.rs +++ b/giterated-abi/src/vtable/value.rs @@ -1,5 +1,6 @@ use crate::{ - result::{Error, Result}, + result::{FfiError, FfiResult}, + value_ex::FfiValueUntyped, FfiSlice, FfiSliceRef, }; @@ -7,17 +8,23 @@ use super::{ObjectABI, VTable}; #[repr(C)] pub struct Value { - inner: (), + inner: FfiValueUntyped, vtable: &'static VTable, } +impl Value { + pub fn from(value: T) -> Self { + todo!() + } +} + impl ObjectABI for Value { type VTable = ValueVTable; } pub struct ValueVTable { - pub serialize: unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> Result, - pub deserialize: unsafe extern "C" fn(this: Value) -> Result, Error>, + pub serialize: unsafe extern "C" fn(buffer: FfiSliceRef<[u8]>) -> FfiResult, + pub deserialize: unsafe extern "C" fn(this: Value) -> FfiResult, FfiError>, } impl ValueVTable { @@ -27,9 +34,19 @@ impl ValueVTable { deserialize: V::deserialize, } } + + pub fn serialize(&self, value: &Value) -> Result, FfiError> { + todo!() + } + + pub fn deserialize(&self, buffer: &[u8]) -> Result { + todo!() + } } -pub trait IntoValueVTable { - unsafe extern "C" fn serialize(buffer: FfiSliceRef<[u8]>) -> Result; - unsafe extern "C" fn deserialize(this: Value) -> Result, Error>; +pub trait IntoValueVTable: Sized { + const VTABLE: &'static VTable = VTable::new(&ValueVTable::new::()); + + unsafe extern "C" fn serialize(buffer: FfiSliceRef<[u8]>) -> FfiResult; + unsafe extern "C" fn deserialize(this: Value) -> FfiResult, FfiError>; } diff --git a/giterated-core/Cargo.toml b/giterated-core/Cargo.toml new file mode 100644 index 0000000..c7fd267 --- /dev/null +++ b/giterated-core/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "giterated-core" +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-core/src/callback/mod.rs b/giterated-core/src/callback/mod.rs new file mode 100644 index 0000000..3e60183 --- /dev/null +++ b/giterated-core/src/callback/mod.rs @@ -0,0 +1 @@ +mod operation; diff --git a/giterated-core/src/callback/operation.rs b/giterated-core/src/callback/operation.rs new file mode 100644 index 0000000..741efd2 --- /dev/null +++ b/giterated-core/src/callback/operation.rs @@ -0,0 +1,125 @@ +pub struct OperationHandlerCallback(FfiValueUntyped); + +impl Callback for OperationHandlerCallback { + type CallbackFunc = unsafe extern "C" fn( + CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + operation: FfiValueRef, + ) -> RuntimeFuture< + FfiResult>, + >; +} + +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!() + } +} diff --git a/giterated-core/src/lib.rs b/giterated-core/src/lib.rs new file mode 100644 index 0000000..05cbac6 --- /dev/null +++ b/giterated-core/src/lib.rs @@ -0,0 +1,68 @@ +mod callback; +mod state; + +#[derive(Clone)] +#[repr(C)] +pub struct RuntimeState { + pub vtable: VTable, +} + +impl RuntimeState { + pub unsafe fn from_static() -> Self { + let runtime = giterated_static_runtime::get_runtime_reference(); + + let runtime = runtime.cast::>().as_ref(); + + runtime.state() + } + + pub unsafe fn runtime_state() -> PluginState { + let runtime = giterated_static_runtime::get_runtime_reference(); + + PluginState::from_raw_ptr(giterated_static_runtime::get_runtime_reference().as_ptr()) + } +} + +#[async_trait::async_trait(?Send)] +impl ObjectBackend for RuntimeState { + 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, + { + // let _object = AnyObject::new(object); + // let _operation = AnyOperation::new(payload); + + todo!() + } + + async fn get_object( + &self, + object_str: &str, + operation_state: &OperationState, + ) -> Result, OperationError> { + // let object = unsafe { + // (self.vtable.get_object)( + // Self::runtime_state(), + // object_str, + // &mut operation_state.clone(), + // ) + // }?; + + // let object = unsafe { object.cast::() }; + + panic!("object casted"); + + // Ok(unsafe { Object::new_unchecked(object, self.clone()) }) + + todo!() + } +} diff --git a/giterated-core/src/state.rs b/giterated-core/src/state.rs new file mode 100644 index 0000000..77beb51 --- /dev/null +++ b/giterated-core/src/state.rs @@ -0,0 +1,15 @@ +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!() + } +} diff --git a/giterated-plugin/Cargo.toml b/giterated-plugin/Cargo.toml index f05c3a9..93a9741 100644 --- a/giterated-plugin/Cargo.toml +++ b/giterated-plugin/Cargo.toml @@ -19,3 +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 diff --git a/giterated-plugin/giterated-macros/Cargo.toml b/giterated-plugin/giterated-macros/Cargo.toml new file mode 100644 index 0000000..a8d1cd3 --- /dev/null +++ b/giterated-plugin/giterated-macros/Cargo.toml @@ -0,0 +1,10 @@ +[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 new file mode 100644 index 0000000..b2344b2 --- /dev/null +++ b/giterated-plugin/giterated-macros/src/lib.rs @@ -0,0 +1,13 @@ +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 index 3c4c1fa..83ea865 100644 --- a/giterated-plugin/giterated-plugin-sys/Cargo.toml +++ b/giterated-plugin/giterated-plugin-sys/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] giterated-plugin = { path = "../." } tracing = "0.1" -giterated-models = { path = "../../giterated-models" } \ No newline at end of file +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 index 69294f6..1ba8196 100644 --- a/giterated-plugin/giterated-plugin-sys/src/lib.rs +++ b/giterated-plugin/giterated-plugin-sys/src/lib.rs @@ -1,37 +1,44 @@ 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::{ - CallbackPtr, IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter, + IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter, IntoPluginValueGetter, OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback, }, handle::PluginInitializationState, new_stack::PluginState, - vtable::{ - InitializationVTable, IntoObjectVTable, IntoOperationVTable, IntoSettingVTable, - IntoValueVTable, ObjectVtable, OperationVTable, SettingVtable, ValueVTable, - }, - AnyObject, NewAnyValue, + vtable::Initialization, }; use tracing::trace_span; -pub struct PluginStackBuilder<'init, S> { +pub struct PluginStackBuilder { init_state: *mut PluginInitializationState, - vtable: &'init InitializationVTable, + vtable: &'static VTable, state: S, } -impl<'init, S> PluginStackBuilder<'init, S> { +impl PluginStackBuilder { pub fn new( plugin_state: S, state: *mut PluginInitializationState, - vtable: &'init InitializationVTable, - ) -> PluginStackBuilder<'init, S> { + vtable: &'static VTable, + ) -> PluginStackBuilder { PluginStackBuilder { init_state: state, vtable, @@ -44,7 +51,13 @@ impl<'init, S> PluginStackBuilder<'init, S> { let func = self.vtable.register_object; - unsafe { func(self.init_state, O::object_name(), ObjectVtable::new::()) }; + unsafe { + func( + self.init_state, + O::object_name(), + O::VTABLE + ) + }; self } @@ -61,7 +74,7 @@ impl<'init, S> PluginStackBuilder<'init, S> { self.init_state, O::object_name(), D::operation_name(), - OperationVTable::new::(), + >::VTABLE, ) } @@ -82,7 +95,7 @@ impl<'init, S> PluginStackBuilder<'init, S> { self.init_state, O::object_name(), OS::name(), - SettingVtable::new::(), + OS::VTABLE, ) } @@ -101,7 +114,7 @@ impl<'init, S> PluginStackBuilder<'init, S> { self.init_state, O::object_name(), OS::name(), - SettingVtable::new::(), + OS::VTABLE, ) } @@ -111,7 +124,7 @@ impl<'init, S> PluginStackBuilder<'init, S> { pub fn value(&mut self, handler: T) -> &mut Self where O: GiteratedObject, - V: IntoValueVTable + GiteratedObjectValue, + V: IntoValueVTable + GiteratedObjectValue, T: IntoPluginValueGetter, { let _guard = trace_span!("register value").entered(); @@ -121,18 +134,18 @@ impl<'init, S> PluginStackBuilder<'init, S> { self.init_state, O::object_name(), V::value_name(), - ValueVTable::new::(), + V::VTABLE, ) } - unsafe { - (self.vtable.value_getter)( - self.init_state, - O::object_name(), - V::value_name(), - ValueGetterCallback::new::(handler), - ) - } + // unsafe { + // (self.vtable.value_getter)( + // self.init_state, + // O::object_name(), + // V::value_name(), + // ValueGetterCallback::new::(handler), + // ) + // } self } @@ -148,14 +161,14 @@ impl<'init, S> PluginStackBuilder<'init, S> { ) -> &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), - ) - } + // unsafe { + // (self.vtable.operation_handler)( + // self.init_state, + // O::object_name(), + // D::operation_name(), + // OperationHandlerCallback::new::(handler), + // ) + // } // TODO: Yikes? self.object::(); @@ -197,14 +210,14 @@ impl<'init, S> PluginStackBuilder<'init, S> { { 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), - ) - } + // unsafe { + // (self.vtable.setting_getter)( + // self.init_state, + // O::object_name(), + // OS::name(), + // SettingGetterCallback::new::(handler), + // ) + // } self.object::(); @@ -213,7 +226,7 @@ impl<'init, S> PluginStackBuilder<'init, S> { self.init_state, O::object_name(), OS::name(), - SettingVtable::new::(), + OS::VTABLE, ) }; @@ -225,16 +238,16 @@ pub trait ValueSettingExt { fn value_setting(&mut self, get: HG, set: HS) -> &mut Self where O: GiteratedObject + IntoObjectVTable + 'static, - VS: GiteratedObjectValue + IntoValueVTable + Setting + IntoSettingVTable, + VS: GiteratedObjectValue + IntoValueVTable + Setting + IntoSettingVTable, HG: IntoPluginSettingGetter, HS: IntoPluginSettingSetter; } -impl ValueSettingExt for PluginStackBuilder<'_, PS> { +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, + VS: GiteratedObjectValue + IntoValueVTable + Setting + IntoSettingVTable, HG: IntoPluginSettingGetter, HS: IntoPluginSettingSetter, { @@ -242,14 +255,25 @@ impl ValueSettingExt for PluginStackBuilder<'_, PS> { } } +#[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, + callback: CallbackPtr, state: &PluginState, - object: AnyObject, - ) -> Result; + object: FfiValueRef, + ) -> Result; - fn callback_ptr(&self) -> CallbackPtr; + fn callback_ptr(&self) -> CallbackPtr; } impl ValueSettingGetter for HG @@ -259,10 +283,10 @@ where HG: IntoPluginSettingGetter, { unsafe extern "C" fn get_value( - _callback: CallbackPtr, + _callback: CallbackPtr, _state: &PluginState, - _object: AnyObject, - ) -> Result { + _object: FfiValueRef, + ) -> Result { // let result = HG::get_setting(callback, state, object)?; // let setting = *result.transmute_owned::(); @@ -272,7 +296,7 @@ where // Ok(NewAnyValue::new(setting)) } - fn callback_ptr(&self) -> CallbackPtr { - self.callback_ptr() + fn callback_ptr(&self) -> CallbackPtr { + todo!() } } diff --git a/giterated-plugin/src/callback/mod.rs b/giterated-plugin/src/callback/mod.rs index 375df1e..f0a963f 100644 --- a/giterated-plugin/src/callback/mod.rs +++ b/giterated-plugin/src/callback/mod.rs @@ -17,81 +17,4 @@ pub use setting::*; use crate::{ new_stack::{PluginState, Runtime}, vtable::RuntimeVTable, - AnyObject, AnyOperation, -}; - -/// A container for a callback pointer, used to provide an internal callback function or -/// state to a plugin when performing a callback. -#[derive(Clone, Copy)] -#[repr(C)] -pub struct CallbackPtr(*const ()); - -impl CallbackPtr { - pub unsafe fn from_raw(callback: *const ()) -> Self { - Self(callback) - } -} - -#[derive(Clone)] -#[repr(C)] -pub struct RuntimeState { - pub vtable: RuntimeVTable, -} - -impl RuntimeState { - pub unsafe fn from_static() -> Self { - let runtime = giterated_static_runtime::get_runtime_reference(); - - let runtime = runtime.cast::>().as_ref(); - - runtime.state() - } - - pub unsafe fn runtime_state() -> PluginState { - let runtime = giterated_static_runtime::get_runtime_reference(); - - PluginState::from_raw_ptr(giterated_static_runtime::get_runtime_reference().as_ptr()) - } -} - -#[async_trait::async_trait(?Send)] -impl ObjectBackend for RuntimeState { - 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, - { - let _object = AnyObject::new(object); - let _operation = AnyOperation::new(payload); - - todo!() - } - - async fn get_object( - &self, - object_str: &str, - operation_state: &OperationState, - ) -> Result, OperationError> { - let object = unsafe { - (self.vtable.get_object)( - Self::runtime_state(), - object_str, - &mut operation_state.clone(), - ) - }?; - - let object = unsafe { object.cast::() }; - - panic!("object casted"); - - Ok(unsafe { Object::new_unchecked(object, self.clone()) }) - } -} +}; \ No newline at end of file diff --git a/giterated-plugin/src/callback/operation.rs b/giterated-plugin/src/callback/operation.rs index c4076db..395e3c8 100644 --- a/giterated-plugin/src/callback/operation.rs +++ b/giterated-plugin/src/callback/operation.rs @@ -1,3 +1,10 @@ +use giterated_abi::{ + callback::{Callback, CallbackPtr}, + result::FfiResult, + value_ex::FfiValueUntyped, + vtable::{operation::Operation, Object}, + FfiValueMut, FfiValueRef, +}; use giterated_models::{ error::OperationError, object::GiteratedObject, @@ -7,53 +14,48 @@ use giterated_models::{ use crate::{ future::{RuntimeFuture, RuntimeFuturesExt}, new_stack::{handle::RuntimeHandle, PluginState}, - vtable::OperationVTable, - AnyFailure, AnyObject, AnyOperation, AnySuccess, FFIBox, + state::{FromState, State, StateUUID}, }; use std::{any::type_name, fmt::Debug, future::Future}; -use super::{CallbackPtr, RuntimeState}; - -#[derive(Clone, Copy)] -pub struct OperationHandlerCallback { - pub callback_ptr: CallbackPtr, - pub func: unsafe extern "C" fn( - CallbackPtr, - &RuntimeState, - &PluginState, - object: AnyObject, - operation: AnyOperation, - ) - -> RuntimeFuture>>, +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 { - func: T::handle, - callback_ptr: T::callback_ptr(&handler), - } - } + // 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, - runtime_state: &RuntimeState, - state: &PluginState, - object: AnyObject, - operation: AnyOperation, - ) -> RuntimeFuture>>; - fn callback_ptr(&self) -> CallbackPtr; + callback_ptr: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + operation: FfiValueRef, + ) -> RuntimeFuture>>; + fn callback_ptr(&self) -> CallbackPtr; } impl IntoPluginOperationHandler for F @@ -65,50 +67,53 @@ where D: Debug + GiteratedOperation + 'static, { unsafe extern "C" fn handle( - callback: CallbackPtr, - runtime_state: &RuntimeState, - state: &PluginState, - mut object: AnyObject, - mut operation: AnyOperation, - ) -> RuntimeFuture>> { - 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 { - 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!(), - }, - } - }) + 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 ()) } + fn callback_ptr(&self) -> CallbackPtr { + // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + + todo!() } } @@ -121,16 +126,15 @@ where D: Debug + GiteratedOperation, { unsafe extern "C" fn handle( - _callback_ptr: CallbackPtr, - _runtime_state: &RuntimeState, - _state: &PluginState, - _object: AnyObject, - _operation: AnyOperation, - ) -> RuntimeFuture>> { + _callback_ptr: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + operation: FfiValueRef, + ) -> RuntimeFuture>> { todo!() } - fn callback_ptr(&self) -> CallbackPtr { + fn callback_ptr(&self) -> CallbackPtr { todo!() } } @@ -144,50 +148,65 @@ where D: Debug + GiteratedOperation, { unsafe extern "C" fn handle( - _callback_ptr: CallbackPtr, - _runtime_state: &RuntimeState, - _state: &PluginState, - _object: AnyObject, - _operation: AnyOperation, - ) -> RuntimeFuture>> { + _callback_ptr: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + operation: FfiValueRef, + ) -> RuntimeFuture>> { todo!() } - fn callback_ptr(&self) -> CallbackPtr { + fn callback_ptr(&self) -> CallbackPtr { todo!() } } pub trait FromOperationState: Sized { fn from_operation_state( - operation_state: &OperationState, - runtime_state: &RuntimeState, + state: &mut State, object: &O, operation: &D, ) -> Result>; } -impl FromOperationState for RuntimeHandle { - fn from_operation_state( - _operation_state: &OperationState, - runtime_state: &RuntimeState, - _object: &O, - _operation: &D, - ) -> Result> { - Ok(unsafe { RuntimeHandle::from_vtable(runtime_state.vtable) }) - } -} +pub struct StateExtractor(T); -impl FromOperationState for Option -where - T: FromOperationState, -{ - fn from_operation_state( - operation_state: &OperationState, - runtime_state: &RuntimeState, - object: &O, - operation: &D, - ) -> Result> { - Ok(T::from_operation_state(operation_state, runtime_state, object, operation).ok()) +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 index 4fbf34e..849b2f7 100644 --- a/giterated-plugin/src/callback/setting.rs +++ b/giterated-plugin/src/callback/setting.rs @@ -1,49 +1,50 @@ use std::future::Future; -use giterated_models::{ - error::OperationError, - object::GiteratedObject, - settings::{AnySetting, Setting}, +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, - AnyObject, NewAnySetting, + state::State, }; -use super::{CallbackPtr, RuntimeState}; +use super::RuntimeState; -#[derive(Clone, Copy)] -pub struct SettingGetterCallback { - pub callback_ptr: CallbackPtr, - pub func: unsafe extern "C" fn( - CallbackPtr, - runtime_state: &RuntimeState, - &PluginState, - object: AnyObject, - ) -> RuntimeFuture>, +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 fn new>(callback: T) -> Self { + // Self { + // func: T::get_setting, + // callback_ptr: callback.callback_ptr(), + // } + // } } pub trait IntoPluginSettingGetter { unsafe extern "C" fn get_setting( - callback_ptr: CallbackPtr, - runtime_state: &RuntimeState, - state: &PluginState, - object: AnyObject, - ) -> RuntimeFuture>; + callback_ptr: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + ) -> RuntimeFuture>; - fn callback_ptr(&self) -> CallbackPtr { - unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + fn callback_ptr(&self) -> CallbackPtr { + // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + todo!() } } @@ -52,55 +53,57 @@ where Fut: Future>> + Send + Sync + 'static, S: Clone + Send + Sync + 'static, O: GiteratedObject + Send + Sync + 'static, - OS: Setting + 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, - runtime_state: &RuntimeState, - state: &PluginState, - mut object: AnyObject, - ) -> RuntimeFuture> { - let _guard = trace_span!( - "get_setting handler", - object = O::object_name(), - setting = OS::name() - ) - .entered(); - let state = unsafe { state.transmute_ref::() }; - - let object = unsafe { object.transmute_owned::() }; - - // Cast the callback ptr to ourselves - let callback: *const F = std::mem::transmute(callback.0); - let callback = callback.as_ref().unwrap(); - - let state = state.clone(); - runtime_state.spawn_future(async move { - let result = callback(state, *object).await; - - match result { - Ok(success) => unsafe { Ok(NewAnySetting::new(success)) }, - Err(err) => match err { - OperationError::Operation(_) => todo!(), - OperationError::Internal(_) => todo!(), - OperationError::Unhandled => todo!(), - }, - } - }) + 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, + callback_ptr: CallbackPtr, state: &PluginState, - object: AnyObject, - setting: AnySetting, + object: FfiValueRef, + setting: Setting, ) -> RuntimeFuture>; - fn callback_ptr(&self) -> CallbackPtr { - unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + fn callback_ptr(&self) -> CallbackPtr { + // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + todo!() } } @@ -109,28 +112,28 @@ where Fut: Future>>, S: Clone, O: GiteratedObject, - OS: Setting, + OS: giterated_models::settings::Setting, F: Fn(S, O, OS) -> Fut, { unsafe extern "C" fn set_setting( - callback: CallbackPtr, + callback: CallbackPtr, state: &PluginState, - mut object: AnyObject, - _setting: AnySetting, + 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 _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::() }; + // 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(); + // // 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); @@ -142,39 +145,41 @@ where } } -pub struct SettingChangeCallback { - func: unsafe extern "C" fn( +pub struct SettingChangeCallback(FfiValueUntyped); + +impl Callback for SettingChangeCallback { + type CallbackFunc = unsafe extern "C" fn( &PluginState, - object: AnyObject, + object: FfiValueRef, setting_name: &str, - new_setting: NewAnySetting, - ), + new_setting: Setting, + ); } pub trait IntoSettingChangeCallback { unsafe extern "C" fn setting_changed( state: &PluginState, - object: AnyObject, + object: FfiValueRef, setting_name: &str, - new_setting: NewAnySetting, + new_setting: Setting, ); } impl IntoSettingChangeCallback for F { unsafe extern "C" fn setting_changed( _state: &PluginState, - _object: AnyObject, + _object: FfiValueRef, _setting_name: &str, - _new_setting: NewAnySetting, + _new_setting: Setting, ) { todo!() } } -impl SettingChangeCallback { - pub fn new>() -> Self { - Self { - func: T::setting_changed, - } - } -} +// 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 index a932e8c..365a473 100644 --- a/giterated-plugin/src/callback/value.rs +++ b/giterated-plugin/src/callback/value.rs @@ -1,46 +1,47 @@ 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, RuntimeFuturesExt}, - new_stack::PluginState, - vtable::{AnyObject, NewAnyValue}, -}; +use crate::{future::RuntimeFuture, new_stack::PluginState, state::State}; -use super::{CallbackPtr, RuntimeState}; +use super::{RuntimeState, SettingGetterCallback}; #[derive(Copy, Clone)] -pub struct ValueGetterCallback { - pub callback_ptr: CallbackPtr, - pub func: unsafe extern "C" fn( - CallbackPtr, - runtime_state: &RuntimeState, - &PluginState, - object: AnyObject, - ) -> RuntimeFuture>, +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 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, - runtime_state: &RuntimeState, - state: &PluginState, - object: AnyObject, - ) -> RuntimeFuture>; + callback: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + ) -> RuntimeFuture>; - fn callback_ptr(&self) -> CallbackPtr; + fn callback_ptr(&self) -> CallbackPtr; } impl IntoPluginValueGetter for F @@ -52,78 +53,84 @@ where F: Fn(S, O) -> Fut + Send + Sync + 'static, { unsafe extern "C" fn get_value( - callback: CallbackPtr, - runtime_state: &RuntimeState, - state: &PluginState, - mut object: AnyObject, - ) -> 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!(), - }, - } - }) + 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 { - unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } + fn callback_ptr(&self) -> CallbackPtr { + todo!() + // unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) } } } -pub struct ValueChangeCallback { - func: unsafe extern "C" fn( +pub struct ValueChangeCallback(CallbackPtr); + +impl Callback for ValueChangeCallback { + type CallbackFunc = unsafe extern "C" fn( &PluginState, - object: AnyObject, - value_name: &str, - new_value: NewAnyValue, - ) -> RuntimeFuture<()>, + object: FfiValueRef, + value_name: FfiSliceRef, + new_value: Value, + ) -> RuntimeFuture<()>; } pub trait IntoValueChangeCallback { unsafe extern "C" fn value_changed( - state: &PluginState, - object: AnyObject, - value_name: &str, - new_value: NewAnyValue, + callback: CallbackPtr, + state: FfiValueMut, + object: FfiValueRef, + value_name: FfiSliceRef, + new_value: Value, ) -> RuntimeFuture<()>; } impl IntoValueChangeCallback for F { unsafe extern "C" fn value_changed( - _state: &PluginState, - _object: AnyObject, - _value_name: &str, - _new_value: NewAnyValue, + 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, - } - } + // pub fn new>() -> Self { + // Self { + // func: T::value_changed, + // } + // } } diff --git a/giterated-plugin/src/future.rs b/giterated-plugin/src/future.rs index 69d50b1..bdd9872 100644 --- a/giterated-plugin/src/future.rs +++ b/giterated-plugin/src/future.rs @@ -9,7 +9,7 @@ use std::{ task::{Context, RawWaker, RawWakerVTable, Waker}, }; -use crate::{callback::RuntimeState, new_stack::PluginState, FFIBox}; +use crate::{callback::RuntimeState, new_stack::PluginState}; #[repr(C)] pub struct RuntimeWakerCallback { @@ -51,15 +51,17 @@ impl RuntimeFuturesExt for RuntimeState { &self, future: F, ) -> RuntimeFuture { - let type_eraser = async move { - let result = future.await; + // let type_eraser = async move { + // let result = future.await; - FFIBox::from_box(Box::new(result)).untyped() - }; + // FFIBox::from_box(Box::new(result)).untyped() + // }; + + // let runtime_future = unsafe { FfiFuture::from_raw(poll_local, type_eraser.boxed()) }; - let runtime_future = unsafe { FfiFuture::from_raw(poll_local, type_eraser.boxed()) }; + // RuntimeFuture(runtime_future) - RuntimeFuture(runtime_future) + todo!() } } diff --git a/giterated-plugin/src/handle.rs b/giterated-plugin/src/handle.rs index 374e531..b99b4c9 100644 --- a/giterated-plugin/src/handle.rs +++ b/giterated-plugin/src/handle.rs @@ -2,6 +2,10 @@ 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}; @@ -14,7 +18,7 @@ use crate::{ ObjectOperationPair, ObjectSettingPair, ObjectValuePair, PluginMeta, PluginState, TypeMetadata, }, - vtable::{InitializationVTable, ObjectVtable, OperationVTable, SettingVtable, ValueVTable}, + vtable::Initialization, GiteratedPluginApi, }; @@ -22,7 +26,7 @@ use crate::{ pub struct PluginHandle { pub meta: PluginMeta, pub raw: Arc>, - pub initialization: Arc, + pub domain_metadata: Arc, pub state: PluginState, } @@ -54,8 +58,8 @@ impl PluginHandle { Ok(Self { raw: Arc::new(handle), meta: metadata, - initialization: Arc::new(initalization), state: init_state, + domain_metadata: todo!(), }) } @@ -125,9 +129,10 @@ pub struct PluginSubstackBuilder {} #[derive(Default)] pub struct PluginInitializationState { pub type_metadata: TypeMetadata, - pub operation_handlers: HashMap, OperationHandlerCallback>, - pub value_getters: HashMap, ValueGetterCallback>, - pub setting_getters: HashMap, SettingGetterCallback>, + pub operation_handlers: + HashMap, CallbackPtr>, + pub value_getters: HashMap, CallbackPtr>, + pub setting_getters: HashMap, CallbackPtr>, } impl PluginInitializationState { @@ -142,8 +147,8 @@ pub struct PluginInitializationTable<'a> { } impl<'a> PluginInitializationTable<'a> { - pub unsafe fn func_table(&mut self) -> InitializationVTable { - InitializationVTable { + pub unsafe fn func_table(&mut self) -> &'static VTable { + VTable::new(&Initialization { register_object, register_operation, register_setting, @@ -151,14 +156,14 @@ impl<'a> PluginInitializationTable<'a> { operation_handler, value_getter, setting_getter, - } + }) } } unsafe extern "C" fn register_object( state: *mut PluginInitializationState, object_kind: &'static str, - vtable: ObjectVtable, + vtable: &'static VTable, ) { let mut state = Box::from_raw(state); @@ -171,7 +176,7 @@ unsafe extern "C" fn register_operation( state: *mut PluginInitializationState, object_kind: &'static str, operation_name: &'static str, - vtable: OperationVTable, + vtable: &'static VTable, ) { let mut state = Box::from_raw(state); @@ -186,7 +191,7 @@ unsafe extern "C" fn register_setting( state: *mut PluginInitializationState, object_kind: &'static str, setting_name: &'static str, - vtable: SettingVtable, + vtable: &'static VTable, ) { let mut state = Box::from_raw(state); @@ -201,7 +206,7 @@ unsafe extern "C" fn register_value( state: *mut PluginInitializationState, object_kind: &'static str, value_name: &'static str, - vtable: ValueVTable, + vtable: &'static VTable, ) { let mut state = Box::from_raw(state); @@ -216,7 +221,7 @@ unsafe extern "C" fn operation_handler( state: *mut PluginInitializationState, object_kind: &'static str, operation_name: &'static str, - handler: OperationHandlerCallback, + handler: CallbackPtr, ) { let mut state = Box::from_raw(state); @@ -234,7 +239,7 @@ unsafe extern "C" fn value_getter( state: *mut PluginInitializationState, object_kind: &'static str, value_name: &'static str, - handler: ValueGetterCallback, + handler: CallbackPtr, ) { let mut state = Box::from_raw(state); @@ -251,7 +256,7 @@ unsafe extern "C" fn setting_getter( state: *mut PluginInitializationState, object_kind: &'static str, setting_name: &'static str, - handler: SettingGetterCallback, + handler: CallbackPtr, ) { let mut state = Box::from_raw(state); diff --git a/giterated-plugin/src/lib.rs b/giterated-plugin/src/lib.rs index e86dcec..ab541f1 100644 --- a/giterated-plugin/src/lib.rs +++ b/giterated-plugin/src/lib.rs @@ -4,6 +4,7 @@ pub mod callback; pub mod future; pub mod handle; pub mod new_stack; +pub mod state; pub mod vtable; #[macro_use] @@ -14,17 +15,17 @@ 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}; -pub use vtable::{AnyFailure, AnyObject, AnyOperation, AnySuccess, NewAnySetting, NewAnyValue}; -use vtable::{HostVTable, InitializationVTable}; +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: &InitializationVTable), + 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, @@ -32,148 +33,8 @@ pub struct GiteratedPluginApi { load_type_metadata: unsafe extern "C" fn(metadata: *mut ()), } -#[repr(C)] -pub struct FFIBox(*mut T); - -impl FFIBox { - pub fn from_box(src: Box) -> Self { - Self(Box::into_raw(src)) - } - - pub fn untyped(self) -> FFIBox<()> { - FFIBox(self.0 as *mut ()) - } - - pub unsafe fn retype(self) -> FFIBox { - FFIBox(self.0 as *mut N) - } - - pub unsafe fn into_box(self) -> Box { - Box::from_raw(self.0) - } - - pub unsafe fn transmute_ref(&self) -> &N { - unsafe { (self.0 as *const N).as_ref() }.unwrap() - } -} - -impl ToString for FFIBox { - fn to_string(&self) -> String { - let slice: Box<[u8]> = unsafe { Box::from_raw(self.0.clone() as *mut _) }; - - let string = unsafe { std::str::from_boxed_utf8_unchecked(slice) }; - - String::from(string) - } -} - -impl AsRef for FFIBox { - fn as_ref(&self) -> &T { - unsafe { self.0.as_ref() }.unwrap() - } -} - -impl std::ops::Deref for FFIBox { - type Target = T; - - fn deref(&self) -> &Self::Target { - unsafe { self.0.as_ref() }.unwrap() - } -} - -#[repr(transparent)] -pub struct FFI { - /// Can either be a pointer to `FFIData` or to `T` - /// depending on the ownership of the FFI reference. - inner: *const (), - _marker: PhantomData<(T, Ownership)>, +pub mod plugin { + pub use giterated_macros::plugin_init as init; } -#[repr(C)] -pub struct FFIData { - /// SAFETY: THIS VALUE COULD BE NULL. - drop_fn: *const extern "C" fn(*const FFIData), - drop_state: *const (), - - allocation: T, -} - -pub struct Owned; - -impl FfiOwnershipDrop for Owned {} - -pub struct StackOwned; - -impl FfiOwnershipDrop for StackOwned {} - -trait FfiOwnershipDrop {} - -pub struct PinnedRef; - -impl FfiOwnershipDrop for PinnedRef {} - -pub struct PinnedMut; - -impl FfiOwnershipDrop for PinnedMut {} - -impl FFI { - pub fn place_heap(value: T) -> FFI { - todo!() - } - - pub fn ref_guard<'a>(&'a self) -> StackPinnedGuard<'a, T> { - todo!() - } -} - -impl FFI { - pub fn place_stack<'a>(value: T) -> StackPinned<'a, T> { - todo!() - } -} - -pub struct StackPinned<'a, T> { - descriptor: FFIData, - _lifetime: PhantomData<&'a ()>, -} - -impl<'a, T> StackPinned<'a, T> { - pub unsafe fn grant_ref(&self) -> FFI { - todo!() - } -} - -pub struct StackPinnedGuard<'a, T> { - pinned_owned: &'a FFI, -} - -impl<'a, T> StackPinnedGuard<'a, T> { - pub unsafe fn grant_ref(&self) -> FFI { - todo!() - } -} - -impl Drop for FFI { - fn drop(&mut self) { - todo!() - } -} - -pub struct FFISlice { - len: usize, - slice: T, -} - -fn example() { - let stack_ffi_value = FFI::place_stack(()); - - let stack_ffi_ref = unsafe { stack_ffi_value.grant_ref() }; - - let foo = stack_ffi_ref; - - let heap_ffi_value = FFI::place_heap(()); - - let heap_ffi_ref_guard = heap_ffi_value.ref_guard(); - - let heap_ffi_ref = unsafe { heap_ffi_ref_guard.grant_ref() }; -} +pub use giterated_macros::plugin; diff --git a/giterated-plugin/src/new_stack/mod.rs b/giterated-plugin/src/new_stack/mod.rs index 2485e97..4f4f72f 100644 --- a/giterated-plugin/src/new_stack/mod.rs +++ b/giterated-plugin/src/new_stack/mod.rs @@ -4,6 +4,13 @@ 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}, @@ -19,11 +26,8 @@ use crate::{ ValueChangeCallback, ValueGetterCallback, }, future::RuntimeFuture, - handle::PluginHandle, - vtable::{ - IntoRuntimeVtable, ObjectVtable, OperationVTable, RuntimeVTable, SettingVtable, ValueVTable, - }, - AnyFailure, AnySuccess, + handle::{PluginHandle, PluginInitializationState, PluginInitializationTable}, + vtable::{IntoRuntimeVtable, RuntimeVTable}, }; use self::operation_walker::OperationHandlerRules; @@ -40,10 +44,10 @@ impl std::ops::Deref for State { #[derive(Default, Clone)] pub struct TypeMetadata { - pub objects: HashMap<&'static str, ObjectVtable>, - pub operations: HashMap, OperationVTable>, - pub settings: HashMap, SettingVtable>, - pub values: HashMap, ValueVTable>, + pub objects: HashMap<&'static str, &'static VTable>, + pub operations: HashMap, &'static VTable>, + pub settings: HashMap, &'static VTable>, + pub values: HashMap, &'static VTable>, } impl TypeMetadata { @@ -53,7 +57,7 @@ impl TypeMetadata { .as_ref() } - pub fn register_object(&mut self, object_kind: &'static str, vtable: ObjectVtable) { + 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); @@ -63,7 +67,7 @@ impl TypeMetadata { &mut self, object_kind: &'static str, operation_name: &'static str, - vtable: OperationVTable, + vtable: &'static VTable, ) { trace!( "Registering operation metadata for {}::{}", @@ -84,7 +88,7 @@ impl TypeMetadata { &mut self, object_kind: &'static str, setting_name: &'static str, - vtable: SettingVtable, + vtable: &'static VTable, ) { trace!("Registering setting {}::{}", object_kind, setting_name); @@ -101,7 +105,7 @@ impl TypeMetadata { &mut self, object_kind: &'static str, value_name: &'static str, - vtable: ValueVTable, + vtable: &'static VTable, ) { trace!("Registering value {}::{}", object_kind, value_name); @@ -217,12 +221,13 @@ pub struct FfiRuntimeMetadata { impl IntoRuntimeVtable for Runtime { unsafe extern "C" fn handle( _this: PluginState, - _object_kind: crate::FFIBox, - _operation_name: crate::FFIBox, - _object: crate::FFIBox, - _operation_payload: crate::FFIBox<[u8]>, - _operation_state: crate::FFIBox<[u8]>, - ) -> RuntimeFuture>> { + _object_kind: FfiSliceRef, + _operation_name: FfiSliceRef, + _object: FfiSliceRef, + _operation_payload: FfiSliceRef<[u8]>, + _operation_state: FfiSliceRef<[u8]>, + ) -> RuntimeFuture>> + { todo!() } @@ -230,8 +235,7 @@ impl IntoRuntimeVtable for Runtime { this: PluginState, object_str: &str, operation_state: *mut OperationState, - ) -> Result> - { + ) -> FfiResult> { let runtime_state = unsafe { RuntimeState::from_static() }; let type_metada = runtime_state @@ -241,21 +245,18 @@ impl IntoRuntimeVtable for Runtime { .unwrap_or_else(|| { let runtime = this.transmute_ref::(); - &runtime - .plugins - .first() - .unwrap() - .initialization - .type_metadata + &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); - } - } + // 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)) - Err(OperationError::Operation(ObjectRequestError::Invalid)) + todo!() } } @@ -278,17 +279,21 @@ impl Runtime { } } - pub fn insert_plugin(&mut self, plugin: PluginHandle) { + 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 &plugin.initialization.operation_handlers { + 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)) + .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) .is_some() { warn!("Warning! Insertion of handler for overwrote a previous handler.") @@ -297,14 +302,14 @@ impl Runtime { trace!("Insertion of operation handler successful") } - for (pair, callback) in &plugin.initialization.value_getters { + 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)) + .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) .is_some() { warn!("Warning! Insertion of handler for overwrote a previous handler.") @@ -313,14 +318,14 @@ impl Runtime { trace!("Insertion of operation handler successful") } - for (pair, callback) in &plugin.initialization.setting_getters { + 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)) + .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback)) .is_some() { warn!("Warning! Insertion of setting handler for overwrote a previous handler.") @@ -362,12 +367,18 @@ impl Runtime { #[derive(Default)] pub struct RuntimeHandlers { - operation_handlers: - HashMap, (RuntimeDomain, OperationHandlerCallback)>, - value_getters: HashMap, (RuntimeDomain, ValueGetterCallback)>, - setting_getters: HashMap, (RuntimeDomain, SettingGetterCallback)>, - value_change: HashMap, (RuntimeDomain, ValueChangeCallback)>, - setting_change: HashMap, (RuntimeDomain, SettingChangeCallback)>, + 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 {} @@ -377,7 +388,7 @@ impl RuntimeHandlers { pub fn operation_handler( &mut self, pair: ObjectOperationPair<'static>, - handler: OperationHandlerCallback, + handler: CallbackPtr, domain: RuntimeDomain, ) { trace!( @@ -400,7 +411,7 @@ impl RuntimeHandlers { pub fn value_getter( &mut self, pair: ObjectValuePair<'static>, - handler: ValueGetterCallback, + handler: CallbackPtr, domain: RuntimeDomain, ) { trace!( @@ -420,7 +431,7 @@ impl RuntimeHandlers { pub fn setting_getter( &mut self, pair: ObjectSettingPair<'static>, - handler: SettingGetterCallback, + handler: CallbackPtr, domain: RuntimeDomain, ) { trace!( @@ -441,7 +452,7 @@ impl RuntimeHandlers { pub fn value_change( &mut self, pair: ObjectValuePair<'static>, - handler: ValueChangeCallback, + handler: CallbackPtr, domain: RuntimeDomain, ) { trace!( @@ -459,7 +470,7 @@ impl RuntimeHandlers { pub fn setting_change( &mut self, pair: ObjectSettingPair<'static>, - handler: SettingChangeCallback, + handler: CallbackPtr, domain: RuntimeDomain, ) { trace!( @@ -500,10 +511,9 @@ impl RuntimeDomain { } } - pub fn object_vtable(&self, object_kind: &str) -> Option { + pub fn object_vtable(&self, object_kind: &str) -> Option<&'static VTable> { self.plugin - .initialization - .type_metadata + .domain_metadata .objects .get(object_kind) .copied() @@ -513,28 +523,33 @@ impl RuntimeDomain { &self, object_kind: &str, operation_name: &str, - ) -> Option { + ) -> Option<&'static VTable> { self.plugin - .initialization - .type_metadata + .domain_metadata .operations .get(&ObjectOperationPair::new(object_kind, operation_name)) .copied() } - pub fn setting_vtable(&self, object_kind: &str, setting_name: &str) -> Option { + pub fn setting_vtable( + &self, + object_kind: &str, + setting_name: &str, + ) -> Option<&'static VTable> { self.plugin - .initialization - .type_metadata + .domain_metadata .settings .get(&ObjectSettingPair::new(object_kind, setting_name)) .copied() } - pub fn value_vtable(&self, object_kind: &str, value_name: &str) -> Option { + pub fn value_vtable( + &self, + object_kind: &str, + value_name: &str, + ) -> Option<&'static VTable> { self.plugin - .initialization - .type_metadata + .domain_metadata .values .get(&ObjectValuePair::new(object_kind, value_name)) .copied() diff --git a/giterated-plugin/src/new_stack/operation_walker.rs b/giterated-plugin/src/new_stack/operation_walker.rs index af99230..e3fb91a 100644 --- a/giterated-plugin/src/new_stack/operation_walker.rs +++ b/giterated-plugin/src/new_stack/operation_walker.rs @@ -1,4 +1,5 @@ -use crate::{callback::RuntimeState, AnyFailure, AnySuccess, FFIBox}; +use crate::callback::RuntimeState; +use giterated_abi::{result::FfiError, value_ex::FfiValueUntyped}; use giterated_models::{ error::OperationError, operation::GiteratedOperation, settings::GetSetting, value::GetValue, }; @@ -49,7 +50,7 @@ impl<'o> OperationHandlerRules<'o> { runtime_state: &RuntimeState, object: &str, operation_payload: &[u8], - ) -> Result> { + ) -> Result> { // object_kind: `any` // operation_kind: `typed` if let Some(_handler) = self @@ -111,25 +112,27 @@ impl<'o> OperationHandlerRules<'o> { 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!(), - } + // 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."); } @@ -166,38 +169,42 @@ impl<'o> OperationHandlerRules<'o> { .ok_or_else(|| OperationError::Unhandled)?; trace!("Resolved setting vtable for {}", operation.setting_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) => { - 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(); - - return Ok(unsafe { - AnySuccess::from_raw( - FFIBox::from_box(Box::new(return_value)).untyped(), - vtable, - ) - }); - } - Err(_err) => todo!(), - } + 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."); } @@ -239,24 +246,26 @@ impl<'o> OperationHandlerRules<'o> { self.operation_name ); - 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; + 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 index dc6e4bf..1d92afd 100644 --- a/giterated-plugin/src/new_stack/runtime_handler.rs +++ b/giterated-plugin/src/new_stack/runtime_handler.rs @@ -1,7 +1,9 @@ +use giterated_abi::{ + value_ex::FfiValueUntyped, + vtable::{operation::Operation, VTable}, +}; use giterated_models::error::OperationError; -use crate::vtable::{AnyFailure, AnySuccess, OperationVTable}; - use super::PluginState; #[repr(C)] @@ -20,6 +22,6 @@ unsafe impl Sync for RuntimeHandleInner {} #[repr(C)] struct HandlerResult { - operation_vtable: OperationVTable, - result: Result>, + operation_vtable: VTable, + result: Result>, } diff --git a/giterated-plugin/src/state.rs b/giterated-plugin/src/state.rs new file mode 100644 index 0000000..f996944 --- /dev/null +++ b/giterated-plugin/src/state.rs @@ -0,0 +1,116 @@ +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 index f1204b2..099cae8 100644 --- a/giterated-plugin/src/vtable/host.rs +++ b/giterated-plugin/src/vtable/host.rs @@ -1,4 +1,8 @@ -use super::{ObjectVtable, OperationVTable, SettingVtable, ValueVTable}; +use giterated_abi::{ + callback::CallbackPtr, + vtable::{operation::Operation, Object, ObjectABI, Setting, VTable, Value}, +}; + use crate::{ callback::{OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback}, handle::PluginInitializationState, @@ -10,55 +14,59 @@ pub struct HostVTable {} #[repr(C)] #[derive(Clone, Copy)] -pub struct InitializationVTable { +pub struct Initialization { pub register_object: - unsafe extern "C" fn(*mut PluginInitializationState, &'static str, ObjectVtable), + unsafe extern "C" fn(*mut PluginInitializationState, &'static str, &'static VTable), pub register_operation: unsafe extern "C" fn( *mut PluginInitializationState, &'static str, &'static str, - OperationVTable, + &'static VTable, ), pub register_setting: unsafe extern "C" fn( *mut PluginInitializationState, &'static str, &'static str, - SettingVtable, + &'static VTable, ), pub register_value: unsafe extern "C" fn( *mut PluginInitializationState, &'static str, &'static str, - ValueVTable, + &'static VTable, ), pub operation_handler: unsafe extern "C" fn( *mut PluginInitializationState, &'static str, &'static str, - OperationHandlerCallback, + CallbackPtr, ), pub value_getter: unsafe extern "C" fn( *mut PluginInitializationState, &'static str, &'static str, - ValueGetterCallback, + CallbackPtr, ), pub setting_getter: unsafe extern "C" fn( *mut PluginInitializationState, &'static str, &'static str, - SettingGetterCallback, + CallbackPtr, ), } -impl Debug for InitializationVTable { +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 InitializationVTable {} -unsafe impl Send for InitializationVTable {} +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 index 32e36d0..f27c252 100644 --- a/giterated-plugin/src/vtable/mod.rs +++ b/giterated-plugin/src/vtable/mod.rs @@ -2,14 +2,6 @@ //! //! Docs here? :) mod runtime; -mod setting; pub use runtime::*; -pub use setting::*; -mod operation; -pub use operation::*; -mod object; -pub use object::*; -mod value; -pub use value::*; mod host; pub use host::*; diff --git a/giterated-plugin/src/vtable/object.rs b/giterated-plugin/src/vtable/object.rs deleted file mode 100644 index b07f28a..0000000 --- a/giterated-plugin/src/vtable/object.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std::{mem::transmute, str::FromStr}; - -use giterated_abi::vtable::IntoObjectVTable; -use giterated_models::object::GiteratedObject; - -use crate::FFIBox; - -// #[derive(Clone, Copy)] -// #[repr(C)] -// pub struct ObjectVtable { -// object_kind: *const u8, -// object_kind_len: usize, -// pub to_str: unsafe extern "C" fn(&AnyObject) -> FFIBox<[u8]>, -// pub from_str: unsafe extern "C" fn(&str) -> Result>, -// pub home_uri: unsafe extern "C" fn(&AnyObject) -> FFIBox, -// pub is_same: unsafe extern "C" fn(&AnyObject) -> bool, -// } - -// impl ObjectVtable { -// pub fn new() -> Self { -// let object_kind = T::object_kind().as_ptr(); -// let object_kind_len = T::object_kind().len(); - -// Self { -// to_str: T::to_str, -// from_str: T::from_str, -// home_uri: T::home_uri, -// is_same: T::is_same, -// object_kind, -// object_kind_len, -// } -// } - -// pub fn kind(&self) -> &'static str { -// let slice = unsafe { std::slice::from_raw_parts(self.object_kind, self.object_kind_len) }; - -// std::str::from_utf8(slice).unwrap() -// } -// } - -// pub trait IntoObjectVTable { -// fn object_kind() -> &'static str; -// unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<[u8]>; -// unsafe extern "C" fn from_str(src: &str) -> Result>; -// unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox; -// unsafe extern "C" fn is_same(other: &AnyObject) -> bool; -// } - -impl IntoObjectVTable for T { - unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<[u8]> { - let this: &Box = this.transmute_ref(); - - let result = this.to_string(); - - FFIBox::from_box(result.into_bytes().into_boxed_slice()) - } - - unsafe extern "C" fn from_str(src: &str) -> Result> { - let result = T::from_object_str(src) - .map_err(|err| FFIBox::from_box(err.to_string().into_boxed_str()))?; - - let any_object = AnyObject::new(result); - - Ok(any_object) - } - - unsafe extern "C" fn home_uri(_this: &AnyObject) -> FFIBox { - todo!() - } - - fn object_kind() -> &'static std::ffi::CStr { - ::object_name() - } - - // unsafe extern "C" fn is_same(_other: &AnyObject) -> bool { - // todo!() - // } -} - - -// impl AnyObject { -// pub fn new(inner: T) -> Self { -// Self { -// inner: FFIBox::from_box(Box::new(inner)).untyped(), -// vtable: ObjectVtable::new::(), -// } -// } - -// pub fn vtable(&self) -> ObjectVtable { -// self.vtable -// } - -// pub fn object_kind(&self) -> &str { -// unsafe { -// std::str::from_utf8_unchecked(std::slice::from_raw_parts( -// self.vtable.object_kind, -// self.vtable.object_kind_len, -// )) -// } -// } - -// pub fn home_uri(&self) -> String { -// unsafe { (self.vtable.home_uri)(self).to_string() } -// } - -// pub fn is_same(&self, other: &AnyObject) -> bool { -// unsafe { (self.vtable.is_same)(other) } -// } - -// pub unsafe fn cast(self) -> T { -// assert_eq!(self.object_kind(), T::object_kind()); - -// info!("{}", self.to_string()); - -// T::from_object_str(&self.to_string()).unwrap() -// } -// } - -// impl ToString for AnyObject { -// fn to_string(&self) -> String { -// let slice: Box<[u8]> = unsafe { Box::from_raw((self.vtable.to_str)(&self).0 as *mut _) }; - -// let string = unsafe { std::str::from_boxed_utf8_unchecked(slice) }; - -// String::from(string) -// } -// } - -impl AnyObject { - pub unsafe fn transmute_owned(&mut self) -> Box { - Box::from_raw(self.inner.0 as *mut T) - } - - pub unsafe fn transmute_ref(&self) -> &T { - let ptr: *const T = transmute(self.inner.0); - - ptr.as_ref().unwrap() - } -} diff --git a/giterated-plugin/src/vtable/operation.rs b/giterated-plugin/src/vtable/operation.rs deleted file mode 100644 index 910f9a2..0000000 --- a/giterated-plugin/src/vtable/operation.rs +++ /dev/null @@ -1,199 +0,0 @@ -use std::mem::transmute; - -use giterated_models::{object::GiteratedObject, operation::GiteratedOperation}; - -use crate::FFIBox; - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct OperationVTable { - operation_kind: *const u8, - operation_kind_len: usize, - pub serialize: unsafe extern "C" fn(&AnyOperation) -> Result, ()>, - pub deserialize: unsafe extern "C" fn(&[u8]) -> Result, - pub is_same: unsafe extern "C" fn(&AnyOperation) -> bool, - pub serialize_success: unsafe extern "C" fn(()) -> Result, ()>, - pub serialize_failure: unsafe extern "C" fn(()) -> Result, ()>, - pub deserialize_success: unsafe extern "C" fn(&[u8]) -> Result, - pub deserialize_failure: unsafe extern "C" fn(&[u8]) -> Result, -} - -impl OperationVTable { - pub fn new>() -> Self { - let operation_kind = T::operation_kind().as_ptr(); - let operation_kind_len = T::operation_kind().len(); - - Self { - serialize: T::serialize, - deserialize: T::deserialize, - is_same: T::is_same, - serialize_success: T::serialize_success, - serialize_failure: T::serialize_failure, - deserialize_success: T::deserialize_success, - deserialize_failure: T::deserialize_failure, - operation_kind, - operation_kind_len, - } - } - - pub fn kind(&self) -> &'static str { - let slice = - unsafe { std::slice::from_raw_parts(self.operation_kind, self.operation_kind_len) }; - - std::str::from_utf8(slice).unwrap() - } -} - -#[repr(C)] -pub struct AnyOperation { - /// A pointer to the plugin-local object type. We are not capable of - /// knowing what this type is, we use the provided vtable. - inner: FFIBox<()>, - vtable: OperationVTable, -} - -impl AnyOperation { - pub fn new>(_operation: D) -> Self { - todo!() - } - - pub unsafe fn transmute_owned(&mut self) -> Box { - Box::from_raw(self.inner.0 as *mut T) - } - - pub unsafe fn transmute_ref(&self) -> &T { - let ptr: *const T = transmute(self.inner.0); - - ptr.as_ref().unwrap() - } - - pub fn vtable(&self) -> OperationVTable { - self.vtable - } - - pub fn operation_kind(&self) -> &str { - unsafe { - std::str::from_utf8_unchecked(std::slice::from_raw_parts( - self.vtable.operation_kind, - self.vtable.operation_kind_len, - )) - } - } - - pub fn serialize(&self) -> Result, anyhow::Error> { - todo!() - } - - pub fn deserialize(_source: &[u8], _vtable: OperationVTable) -> Result { - todo!() - } - - pub fn is_same(&self, _other: &AnyOperation) -> bool { - todo!() - } -} - -#[repr(C)] -pub struct AnySuccess { - inner: FFIBox<()>, - vtable: OperationVTable, -} - -impl AnySuccess { - pub unsafe fn inner(&self) -> &T { - self.inner.transmute_ref() - } - - pub unsafe fn from_raw(inner: FFIBox<()>, vtable: OperationVTable) -> Self { - Self { inner, vtable } - } - - pub fn serialize(&self) -> Result, anyhow::Error> { - todo!() - } - - pub fn deserialize_from_operation( - _source: &[u8], - _vtable: OperationVTable, - ) -> Result { - todo!() - } -} - -unsafe impl Send for AnySuccess {} -unsafe impl Sync for AnySuccess {} - -impl std::fmt::Debug for AnySuccess { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AnySuccess").finish() - } -} - -#[repr(C)] -pub struct AnyFailure { - inner: FFIBox<()>, - vtable: OperationVTable, -} - -unsafe impl Send for AnyFailure {} -unsafe impl Sync for AnyFailure {} - -impl std::fmt::Debug for AnyFailure { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AnyFailure").finish() - } -} - -pub trait IntoOperationVTable { - fn operation_kind() -> &'static str; - unsafe extern "C" fn serialize(this: &AnyOperation) -> Result, ()>; - unsafe extern "C" fn deserialize(src: &[u8]) -> Result; - unsafe extern "C" fn is_same(this: &AnyOperation) -> bool; - unsafe extern "C" fn serialize_success(success: ()) -> Result, ()>; - unsafe extern "C" fn serialize_failure(failure: ()) -> Result, ()>; - unsafe extern "C" fn deserialize_success(src: &[u8]) -> Result; - unsafe extern "C" fn deserialize_failure(src: &[u8]) -> Result; -} - -impl IntoOperationVTable for D -where - D: GiteratedOperation, - O: GiteratedObject, -{ - unsafe extern "C" fn serialize(_this: &AnyOperation) -> Result, ()> { - todo!() - } - - unsafe extern "C" fn deserialize(src: &[u8]) -> Result { - let deserialized: D = serde_json::from_slice(src).unwrap(); - - Ok(AnyOperation { - inner: FFIBox::from_box(Box::new(deserialized)).untyped(), - vtable: OperationVTable::new::(), - }) - } - - unsafe extern "C" fn is_same(_this: &AnyOperation) -> bool { - todo!() - } - - unsafe extern "C" fn serialize_success(_success: ()) -> Result, ()> { - todo!() - } - - unsafe extern "C" fn serialize_failure(_failure: ()) -> Result, ()> { - todo!() - } - - unsafe extern "C" fn deserialize_success(_src: &[u8]) -> Result { - todo!() - } - - unsafe extern "C" fn deserialize_failure(_src: &[u8]) -> Result { - todo!() - } - - fn operation_kind() -> &'static str { - >::operation_name() - } -} diff --git a/giterated-plugin/src/vtable/runtime.rs b/giterated-plugin/src/vtable/runtime.rs index 915d2c0..1592e03 100644 --- a/giterated-plugin/src/vtable/runtime.rs +++ b/giterated-plugin/src/vtable/runtime.rs @@ -1,3 +1,9 @@ +use giterated_abi::{ + result::{FfiError, FfiResult}, + value_ex::FfiValueUntyped, + vtable::Object, + FfiSliceRef, +}; use giterated_models::{ error::OperationError, object::ObjectRequestError, operation::OperationState, }; @@ -5,7 +11,6 @@ use giterated_models::{ use crate::{ future::RuntimeFuture, new_stack::{PluginState, TypeMetadata}, - AnyFailure, AnyObject, AnySuccess, FFIBox, }; #[derive(Clone, Copy)] @@ -14,20 +19,20 @@ pub struct RuntimeVTable { pub(crate) type_metadata: *const TypeMetadata, pub(crate) handle_fn: unsafe extern "C" fn( PluginState, - FFIBox, - FFIBox, - FFIBox, - FFIBox<[u8]>, - FFIBox<[u8]>, + FfiSliceRef, + FfiSliceRef, + FfiSliceRef, + FfiSliceRef<[u8]>, + FfiSliceRef<[u8]>, ) -> RuntimeFuture< - Result>, + FfiResult>, >, pub(crate) get_object: unsafe extern "C" fn( PluginState, &str, *mut OperationState, - ) -> Result>, + ) -> FfiResult>, } unsafe impl Send for RuntimeVTable {} @@ -36,16 +41,16 @@ unsafe impl Sync for RuntimeVTable {} pub trait IntoRuntimeVtable { unsafe extern "C" fn handle( this: PluginState, - object_kind: FFIBox, - operation_name: FFIBox, - object: FFIBox, - operation_payload: FFIBox<[u8]>, - operation_state: FFIBox<[u8]>, - ) -> RuntimeFuture>>; + 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, - ) -> Result>; + ) -> FfiResult>; } diff --git a/giterated-plugin/src/vtable/setting.rs b/giterated-plugin/src/vtable/setting.rs deleted file mode 100644 index 38e20ad..0000000 --- a/giterated-plugin/src/vtable/setting.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::mem::transmute; - -use giterated_models::{ - instance::Instance, - settings::{GetSetting, Setting}, -}; - -use crate::{AnySuccess, FFIBox}; - -use super::OperationVTable; - -#[repr(C)] -pub struct NewAnySetting { - /// A pointer to the plugin-local object type. We are not capable of - /// knowing what this type is, we use the provided vtable. - inner: FFIBox<()>, - pub vtable: SettingVtable, -} - -impl NewAnySetting { - pub fn new(value: V) -> Self { - Self { - inner: FFIBox::from_box(Box::new(value)).untyped(), - vtable: SettingVtable::new::(), - } - } - - pub unsafe fn transmute_owned(self) -> Box { - Box::from_raw(self.inner.0 as *mut T) - } - - pub unsafe fn transmute_ref(&self) -> &T { - let ptr: *const T = transmute(self.inner.0); - - ptr.as_ref().unwrap() - } -} - -impl From for AnySuccess { - fn from(val: NewAnySetting) -> Self { - unsafe { AnySuccess::from_raw(val.inner, (val.vtable.get_setting_vtable)()) } - } -} - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct SettingVtable { - pub get_setting_vtable: unsafe extern "C" fn() -> OperationVTable, - - pub deserialize: unsafe extern "C" fn(&[u8]) -> Result<(), ()>, - pub serialize: unsafe extern "C" fn(NewAnySetting) -> Result, ()>, -} - -impl SettingVtable { - pub fn new() -> Self { - Self { - get_setting_vtable: T::get_setting_vtable, - deserialize: T::deserialize, - serialize: T::serialize, - } - } -} - -pub trait IntoSettingVTable { - unsafe extern "C" fn get_setting_vtable() -> OperationVTable; - unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()>; - unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()>; -} - -impl IntoSettingVTable for S -where - S: Setting, -{ - unsafe extern "C" fn deserialize(_src: &[u8]) -> Result<(), ()> { - todo!() - } - - unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()> { - let setting = this.transmute_owned::(); - - let serialized = serde_json::to_vec(&setting).unwrap(); - - let serialized = serialized.into_boxed_slice(); - - Ok(FFIBox::from_box(serialized)) - } - - unsafe extern "C" fn get_setting_vtable() -> OperationVTable { - OperationVTable::new::() - } -} diff --git a/giterated-plugin/src/vtable/value.rs b/giterated-plugin/src/vtable/value.rs deleted file mode 100644 index 27cd514..0000000 --- a/giterated-plugin/src/vtable/value.rs +++ /dev/null @@ -1,89 +0,0 @@ -use giterated_models::{ - object::GiteratedObject, - value::{GetValue, GiteratedObjectValue}, -}; - -use crate::{AnySuccess, FFIBox}; - -use super::OperationVTable; - -#[repr(C)] -pub struct NewAnyValue { - /// A pointer to the plugin-local object type. We are not capable of - /// knowing what this type is, we use the provided vtable. - inner: FFIBox<()>, - vtable: ValueVTable, -} - -unsafe impl Send for NewAnyValue {} -unsafe impl Sync for NewAnyValue {} - -impl NewAnyValue { - pub fn new + Send + Sync>(value: V) -> Self { - NewAnyValue { - inner: FFIBox::from_box(Box::new(value)).untyped(), - vtable: ValueVTable::new::(), - } - } -} - -impl From for AnySuccess { - fn from(val: NewAnyValue) -> Self { - unsafe { AnySuccess::from_raw(val.inner, (val.vtable.get_value_vtable)()) } - } -} - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct ValueVTable { - pub get_value_vtable: unsafe extern "C" fn() -> OperationVTable, - - pub deserialize: unsafe extern "C" fn(&[u8]) -> Result, - pub serialize: unsafe extern "C" fn(NewAnyValue) -> Result, ()>, -} - -impl ValueVTable { - pub fn new>() -> Self { - Self { - get_value_vtable: T::get_value_vtable, - deserialize: T::deserialize, - serialize: T::serialize, - } - } -} - -pub trait IntoValueVTable { - unsafe extern "C" fn get_value_vtable() -> OperationVTable; - unsafe extern "C" fn deserialize(src: &[u8]) -> Result; - unsafe extern "C" fn serialize(this: NewAnyValue) -> Result, ()>; -} - -impl IntoValueVTable for V -where - O: GiteratedObject, - V: GiteratedObjectValue, -{ - unsafe extern "C" fn get_value_vtable() -> OperationVTable { - OperationVTable::new::() - } - - unsafe extern "C" fn deserialize(src: &[u8]) -> Result { - let _guard = trace_span!( - "deserialize value", - object = O::object_name(), - value = V::value_name() - ); - - trace!("Deserializing"); - let deserialized: V = serde_json::from_slice(src).unwrap(); - - Ok(NewAnyValue { - inner: FFIBox::from_box(Box::new(deserialized)).untyped(), - vtable: ValueVTable::new::(), - }) - } - - unsafe extern "C" fn serialize(_this: NewAnyValue) -> Result, ()> { - todo!() - } -} diff --git a/giterated-runtime/Cargo.toml b/giterated-runtime/Cargo.toml new file mode 100644 index 0000000..fe826cb --- /dev/null +++ b/giterated-runtime/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "giterated-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/src/lib.rs b/giterated-runtime/src/lib.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/giterated-runtime/src/lib.rs diff --git a/plugins/example-plugin/src/lib.rs b/plugins/example-plugin/src/lib.rs index 1895ac6..fad47e2 100644 --- a/plugins/example-plugin/src/lib.rs +++ b/plugins/example-plugin/src/lib.rs @@ -1,116 +1,46 @@ -use std::{mem::forget, sync::OnceLock}; +use anyhow::Error; +use giterated_models::{error::OperationError, object::{ObjectRequest, ObjectRequestError, ObjectResponse}, user::{DisplayName, User}}; +use giterated_plugin::{new_stack::State, plugin}; + +plugin!( + name: "Example Plugin", + version: "0.0.1", + author: "Amber Kowalski", + // Experimental syntax for requesting specific plugin features + features: ["tracing", "tokio"], + description: "An example plugin to demonstrate the development process of Giterated plugins." +); + +/// Some kind of global state for the plugin +struct PluginState; + +/// The plugin's initialization function. Ran when the plugin is loaded, used to +/// build the plugin's stack. +#[plugin::init] +pub fn init(builder: &mut PluginStackBuilder) -> Result<(), Error> { + builder.insert_state(State); + + builder + .object::() + .object::(); -use giterated_models::{ - error::OperationError, - instance::Instance, - object::{ObjectRequest, ObjectRequestError, ObjectResponse}, - user::{DisplayName, User}, -}; -use giterated_plugin::{ - handle::PluginInitializationState, - new_stack::{FFIPluginMeta, PluginState}, - vtable::{HostVTable, InitializationVTable}, -}; -use giterated_plugin_sys::PluginStackBuilder; -use tracing::{info, trace_span, Level}; - -static INIT_VTABLE: OnceLock = OnceLock::new(); - -#[no_mangle] -pub extern "C" fn plugin_meta() -> FFIPluginMeta { - const PLUGIN_NAME: &str = "Example Plugin"; - const PLUGIN_VERSION: &str = "1.0.0"; - - FFIPluginMeta { - name: PLUGIN_NAME.as_ptr(), - name_len: PLUGIN_NAME.len(), - version: PLUGIN_VERSION.as_ptr(), - version_len: PLUGIN_VERSION.len(), - } -} - -#[no_mangle] -pub extern "C" fn load_host_vtable(_vtable: &HostVTable) { - println!("Loading vtable"); -} - -#[no_mangle] -pub extern "C" fn load_initialization_vtable(init_vtable: &InitializationVTable) { - INIT_VTABLE.set(*init_vtable).unwrap(); - println!("Loaded initialization vtable"); -} - -#[no_mangle] -pub extern "C" fn load_type_metadata(metadata: *mut ()) { - unsafe { giterated_static_runtime::initialize_type_metadata(metadata) } - println!("Initialized type metadata for plugin"); -} - -#[no_mangle] -pub extern "C" fn initialize() -> PluginState { - tracing_subscriber::fmt() - .pretty() - .with_thread_names(true) - .with_max_level(Level::TRACE) - .init(); - - println!("Building runtime"); - let runtime = tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .unwrap(); - - let _guard = runtime.enter(); - - forget(_guard); - - PluginState { - inner: Box::into_raw(Box::new(())), - } -} - -#[no_mangle] -pub extern "C" fn initialize_registration( - state: *mut PluginInitializationState, -) -> *mut PluginInitializationState { - let _guard: tracing::span::EnteredSpan = trace_span!("initialize_registration").entered(); - let init_vtable = INIT_VTABLE.get().unwrap(); - let mut builder = PluginStackBuilder::new((), state, init_vtable); - - builder.object::().object::(); - builder.operation(handler); builder.value(value_getter); builder.setting_getter(setting_getter); - state + Ok(()) } async fn handler( - _state: (), - object: Instance, + object: User, operation: ObjectRequest, + state_extractor: State ) -> Result> { - info!("handling operation!"); - - info!("Try get object {} from instance {}", operation.0, object); - - Ok(ObjectResponse(operation.0)) -} - -async fn value_getter( - _state: (), - _object: User, -) -> Result> { - info!("OwO, value gotten!"); - - Ok(DisplayName(String::from("heya!"))) + todo!() } async fn setting_getter( - _state: (), - _object: User, -) -> Result> { - info!("OwO, setting gotten!"); - - Ok(DisplayName(String::from("heya! (but from a setting)"))) -} + object: User, + state_extractor: State +) -> Result> { + todo!() +} \ No newline at end of file diff --git a/plugins/example-plugin/src/main.rs b/plugins/example-plugin/src/main.rs index 294a417..aa2a8ac 100644 --- a/plugins/example-plugin/src/main.rs +++ b/plugins/example-plugin/src/main.rs @@ -24,7 +24,7 @@ async fn main() -> Result<(), anyhow::Error> { info!("2"); - runtime.insert_plugin(handle); + // runtime.insert_plugin(handle); info!("3"); diff --git a/plugins/example-plugin/src/newlib.rs b/plugins/example-plugin/src/newlib.rs new file mode 100644 index 0000000..89a3c2a --- /dev/null +++ b/plugins/example-plugin/src/newlib.rs @@ -0,0 +1,179 @@ +plugin!( + name: "Example Plugin", + version: "0.0.1", + author: "Amber Kowalski", + // Experimental syntax for requesting specific plugin features + features: ["tracing", "tokio"], + description: "An example plugin to demonstrate the development process of Giterated plugins." +); + +/// Some kind of global state for the plugin +struct PluginState; + +/// The plugin's initialization function. Ran when the plugin is loaded, used to +/// build the plugin's stack. +#[plugin::init] +pub fn init(builder: &mut PluginStackBuilder) -> Result<(), Error> { + builder.insert_state(State); + + builder + .object::() + .object::(); + + builder.value(value_getter); + builder.setting_getter(setting_getter); + + Ok(()) +} + +async fn handler( + object: User, + operation: ObjectRequest, + state_extractor: State +) -> Result> { + todo!() +} + +async fn setting_getter( + object: User, + state_extractor: State +) -> Result> { + todo!() +} + +fn emit_statics() -> &'static str { + r#" + static INIT_VTABLE: OnceLock = OnceLock::new(); + "# +} + +pub struct PluginConstants { + plugin_name: String, + plugin_version: String, + plugin_author: String +} + +fn emit_constants(constants: PluginConstants) -> &'static str { + r#" + const PLUGIN_NAME: &'static str = {constants.plugin_name}; + const PLUGIN_VERSION: &'static str = {constants.plugin_version}; + const PLUGIN_AUTHOR: &'static str = {constants.plugin_author}; + "# +} + +// use std::{mem::forget, sync::OnceLock}; + +// use giterated_models::{ +// error::OperationError, +// instance::Instance, +// object::{ObjectRequest, ObjectRequestError, ObjectResponse}, +// user::{DisplayName, User}, +// }; +// use giterated_plugin::{ +// handle::PluginInitializationState, +// new_stack::{FFIPluginMeta, PluginState}, +// vtable::{HostVTable}, +// }; +// use giterated_plugin_sys::PluginStackBuilder; +// use tracing::{info, trace_span, Level}; + +// static INIT_VTABLE: OnceLock = OnceLock::new(); + +// #[no_mangle] +// pub extern "C" fn plugin_meta() -> FFIPluginMeta { +// const PLUGIN_NAME: &str = "Example Plugin"; +// const PLUGIN_VERSION: &str = "1.0.0"; + +// FFIPluginMeta { +// name: PLUGIN_NAME.as_ptr(), +// name_len: PLUGIN_NAME.len(), +// version: PLUGIN_VERSION.as_ptr(), +// version_len: PLUGIN_VERSION.len(), +// } +// } + +// #[no_mangle] +// pub extern "C" fn load_host_vtable(_vtable: &HostVTable) { +// println!("Loading vtable"); +// } + +// #[no_mangle] +// pub extern "C" fn load_initialization_vtable(init_vtable: &InitializationVTable) { +// INIT_VTABLE.set(*init_vtable).unwrap(); +// println!("Loaded initialization vtable"); +// } + +// #[no_mangle] +// pub extern "C" fn load_type_metadata(metadata: *mut ()) { +// unsafe { giterated_static_runtime::initialize_type_metadata(metadata) } +// println!("Initialized type metadata for plugin"); +// } + +// #[no_mangle] +// pub extern "C" fn initialize() -> PluginState { +// tracing_subscriber::fmt() +// .pretty() +// .with_thread_names(true) +// .with_max_level(Level::TRACE) +// .init(); + +// println!("Building runtime"); +// let runtime = tokio::runtime::Builder::new_multi_thread() +// .enable_all() +// .build() +// .unwrap(); + +// let _guard = runtime.enter(); + +// forget(_guard); + +// PluginState { +// inner: Box::into_raw(Box::new(())), +// } +// } + +// #[no_mangle] +// pub extern "C" fn initialize_registration( +// state: *mut PluginInitializationState, +// ) -> *mut PluginInitializationState { +// let _guard: tracing::span::EnteredSpan = trace_span!("initialize_registration").entered(); +// let init_vtable = INIT_VTABLE.get().unwrap(); +// let mut builder = PluginStackBuilder::new((), state, init_vtable); + +// builder.object::().object::(); +// builder.operation(handler); +// builder.value(value_getter); +// builder.setting_getter(setting_getter); + +// state +// } + +// async fn handler( +// _state: (), +// object: Instance, +// operation: ObjectRequest, +// ) -> Result> { +// info!("handling operation!"); + +// info!("Try get object {} from instance {}", operation.0, object); + +// Ok(ObjectResponse(operation.0)) +// } + +// async fn value_getter( +// _state: (), +// _object: User, +// ) -> Result> { +// info!("OwO, value gotten!"); + +// Ok(DisplayName(String::from("heya!"))) +// } + +// async fn setting_getter( +// _state: (), +// _object: User, +// ) -> Result> { +// info!("OwO, setting gotten!"); + +// Ok(DisplayName(String::from("heya! (but from a setting)"))) +// }