diff --git a/.vscode/launch.json b/.vscode/launch.json index d1072db..c10eccf 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -44,6 +44,24 @@ { "type": "lldb", "request": "launch", + "name": "Debug executable 'example-plugin'", + "cargo": { + "args": [ + "build", + "--bin=example-plugin", + "--package=example-plugin" + ], + "filter": { + "name": "example-plugin", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", "name": "Debug unit tests in executable 'giterated-daemon'", "cargo": { "args": [ diff --git a/Cargo.lock b/Cargo.lock index 01e2105..9738986 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -686,6 +686,10 @@ dependencies = [ ] [[package]] +name = "giterated-abi" +version = "0.1.0" + +[[package]] name = "giterated-backend" version = "0.1.0" dependencies = [ @@ -789,6 +793,7 @@ dependencies = [ "async-trait", "dlopen2", "futures-util", + "giterated-abi", "giterated-models", "giterated-static-runtime", "semver", diff --git a/Cargo.toml b/Cargo.toml index c6ebdf2..f6248a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = [ +members = [ "giterated-abi", "giterated-daemon", "giterated-models", "giterated-plugin", @@ -9,4 +9,4 @@ members = [ "plugins/giterated-backend", "plugins/giterated-issues", "plugins/giterated-protocol" -] \ No newline at end of file +] diff --git a/giterated-models/src/instance/mod.rs b/giterated-models/src/instance/mod.rs index 0a414cb..d14186f 100644 --- a/giterated-models/src/instance/mod.rs +++ b/giterated-models/src/instance/mod.rs @@ -42,7 +42,7 @@ impl GiteratedObject for Instance { } fn from_object_str(object_str: &str) -> Result { - Ok(Instance::from_str(object_str).unwrap()) + Ok(Instance::from_str(object_str)?) } fn home_uri(&self) -> String { diff --git a/giterated-models/src/object/operations.rs b/giterated-models/src/object/operations.rs index 7ec3479..c3394ed 100644 --- a/giterated-models/src/object/operations.rs +++ b/giterated-models/src/object/operations.rs @@ -26,6 +26,8 @@ impl GiteratedOperation for ObjectRequest { pub enum ObjectRequestError { #[error("error decoding the object")] Deserialization(String), + #[error("invalid object type")] + Invalid, } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/giterated-plugin/Cargo.toml b/giterated-plugin/Cargo.toml index 4549b46..f05c3a9 100644 --- a/giterated-plugin/Cargo.toml +++ b/giterated-plugin/Cargo.toml @@ -12,6 +12,7 @@ thiserror = "1" tracing = "0.1" giterated-models = { path = "../giterated-models" } giterated-static-runtime = { path = "giterated-static-runtime" } +giterated-abi = { path = "../giterated-abi" } semver = "*" serde_json = "1.0" async-trait = "0.1" diff --git a/giterated-plugin/giterated-static-runtime/src/lib.rs b/giterated-plugin/giterated-static-runtime/src/lib.rs index 8f8df02..1fd008b 100644 --- a/giterated-plugin/giterated-static-runtime/src/lib.rs +++ b/giterated-plugin/giterated-static-runtime/src/lib.rs @@ -14,3 +14,13 @@ pub unsafe fn initialize_runtime(runtime_pointer: *mut ()) { pub unsafe fn get_runtime_reference() -> NonNull<()> { GITERATED_RUNTIME.assume_init_read().0 } + +static mut GITERATED_TYPE_METADATA: MaybeUninit = MaybeUninit::zeroed(); + +pub unsafe fn initialize_type_metadata(runtime_pointer: *mut ()) { + GITERATED_TYPE_METADATA.write(RuntimePointer(NonNull::new(runtime_pointer).unwrap())); +} + +pub unsafe fn get_type_metadata_reference() -> NonNull<()> { + GITERATED_TYPE_METADATA.assume_init_read().0 +} diff --git a/giterated-plugin/src/callback/mod.rs b/giterated-plugin/src/callback/mod.rs index 1689dba..375df1e 100644 --- a/giterated-plugin/src/callback/mod.rs +++ b/giterated-plugin/src/callback/mod.rs @@ -14,7 +14,11 @@ pub use value::*; mod setting; pub use setting::*; -use crate::{vtable::RuntimeVTable, AnyObject, AnyOperation}; +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. @@ -32,16 +36,21 @@ impl CallbackPtr { #[repr(C)] pub struct RuntimeState { pub vtable: RuntimeVTable, - pub operation_state: OperationState, } impl RuntimeState { pub unsafe fn from_static() -> Self { let runtime = giterated_static_runtime::get_runtime_reference(); - let runtime = runtime.cast::>().as_ref(); + let runtime = runtime.cast::>().as_ref(); + + runtime.state() + } + + pub unsafe fn runtime_state() -> PluginState { + let runtime = giterated_static_runtime::get_runtime_reference(); - *runtime.clone() + PluginState::from_raw_ptr(giterated_static_runtime::get_runtime_reference().as_ptr()) } } @@ -68,9 +77,21 @@ impl ObjectBackend for RuntimeState { async fn get_object( &self, - _object_str: &str, - _operation_state: &OperationState, + object_str: &str, + operation_state: &OperationState, ) -> Result, OperationError> { - todo!() + 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()) }) } } diff --git a/giterated-plugin/src/future.rs b/giterated-plugin/src/future.rs index 19bdbd7..69d50b1 100644 --- a/giterated-plugin/src/future.rs +++ b/giterated-plugin/src/future.rs @@ -1,67 +1,31 @@ use futures_util::future::BoxFuture; use futures_util::FutureExt; +use giterated_abi::{FfiFuture, FfiValue, FfiValueMut, RuntimeFuturePoll}; use std::{ cell::UnsafeCell, future::Future, marker::PhantomData, + mem::transmute, task::{Context, RawWaker, RawWakerVTable, Waker}, }; use crate::{callback::RuntimeState, new_stack::PluginState, FFIBox}; -/// Future type for futures within the Runtime. -/// -/// Allows for plugins to spawn futures on the runtime. -#[derive(Clone)] -#[repr(C)] -pub struct RuntimeFuture { - /// The plugin's poll function, provided with the poll state for the future. - poll_fn: unsafe extern "C" fn(*const RuntimeFuture<()>, PluginState) -> RuntimeFuturePoll, - /// The function to wake the future, should only be called when the future is ready to be polled. - wake_fn: Option, PluginState)>, - - /// The inner value that the owning plugin can use to poll the future - poll_state: PluginState, - /// The waker that the plugin uses for notification of the future's completion - waker_state: Option, - - /// Whether its safe for the plugin to poll this future, panic if we think - /// we're supposed to poll and this is not set to `true`. - can_poll: bool, - - _output_marker: PhantomData, -} - -unsafe impl Send for RuntimeFuture where Output: Send {} -unsafe impl Sync for RuntimeFuture where Output: Sync {} - #[repr(C)] pub struct RuntimeWakerCallback { callback: PluginState, waker_func: unsafe extern "C" fn(PluginState), } -#[repr(C)] -pub enum RuntimeFuturePoll { - Ready(FFIBox<()>), - Pending, -} - pub struct WakerState { waker: Waker, } -impl RuntimeFuture { - pub(crate) unsafe fn poll(&mut self) -> RuntimeFuturePoll { - todo!() - } -} - unsafe extern "C" fn wake(_waker: PluginState) {} pub struct LocalRuntimeFuture { inner: BoxFuture<'static, Output>, - runtime_future: UnsafeCell>, + runtime_future: UnsafeCell>, } unsafe impl Send for LocalRuntimeFuture where Output: Send {} @@ -70,7 +34,7 @@ unsafe impl Sync for LocalRuntimeFuture where Output: Sync {} impl LocalRuntimeFuture { pub fn finalize(self) {} - pub fn into_runtime(&self) -> RuntimeFuture { + pub fn into_runtime(&self) -> FfiFuture { todo!() } } @@ -93,25 +57,19 @@ impl RuntimeFuturesExt for RuntimeState { FFIBox::from_box(Box::new(result)).untyped() }; - let runtime_future = RuntimeFuture { - poll_fn: poll_local, - wake_fn: None, - poll_state: PluginState::from(type_eraser.boxed()), - waker_state: None, - can_poll: true, - _output_marker: PhantomData, - }; + let runtime_future = unsafe { FfiFuture::from_raw(poll_local, type_eraser.boxed()) }; - runtime_future + RuntimeFuture(runtime_future) } } unsafe extern "C" fn poll_local( - _future: *const RuntimeFuture<()>, - mut future_state: PluginState, + _future: FfiValueMut>, + mut future_state: FfiValueMut<()>, ) -> RuntimeFuturePoll { - let mut future: Box>> = future_state.transmute_owned(); - let runtime_future = future.as_ref(); + let mut future_state: FfiValueMut>> = transmute(future_state); + + let runtime_future = future_state.as_ref(); let raw_waker = RawWaker::new( Box::into_raw(Box::new(runtime_future)) as *const (), @@ -121,13 +79,7 @@ unsafe extern "C" fn poll_local( let waker = unsafe { Waker::from_raw(raw_waker) }; // SAFETY: Pretty sure this has to be static lol - let poll_result = future.poll_unpin(&mut Context::from_waker(&waker)); - - #[allow(unused_assignments)] - { - // This is meant to communicate with the compiler the lifecycle of the object - future_state = PluginState::from_raw(future); - } + let poll_result = future_state.poll_unpin(&mut Context::from_waker(&waker)); match poll_result { std::task::Poll::Ready(result) => RuntimeFuturePoll::Ready(result), @@ -162,6 +114,9 @@ mod runtime_waker_vtable { } } +#[repr(transparent)] +pub struct RuntimeFuture(FfiFuture); + /// Allows for a remote future to be polled on the target. /// /// The target can be the host or a plugin, but the future should only be polled by one @@ -179,25 +134,19 @@ impl Future for RuntimeFuture { let waker_state = PluginState::from(waker_state); - self.waker_state = Some(waker_state); - self.wake_fn = Some(wake_local); + unsafe { self.0.write_waker(wake_local, waker_state) }; - match unsafe { - (self.poll_fn)( - &*self as *const RuntimeFuture<_> as *const RuntimeFuture<()>, - self.poll_state, - ) - } { + match unsafe { self.0.poll() } { RuntimeFuturePoll::Ready(result) => { - let result: Output = unsafe { *result.retype::().into_box() }; + let result: FfiValue = unsafe { transmute(result) }; - std::task::Poll::Ready(result) + std::task::Poll::Ready(result.take()) } RuntimeFuturePoll::Pending => std::task::Poll::Pending, } } } -unsafe extern "C" fn wake_local(_future: *const RuntimeFuture<()>, _waker_state: PluginState) { +unsafe extern "C" fn wake_local(future: FfiValueMut>, state: FfiValueMut<()>) { todo!() } diff --git a/giterated-plugin/src/handle.rs b/giterated-plugin/src/handle.rs index b0bedae..374e531 100644 --- a/giterated-plugin/src/handle.rs +++ b/giterated-plugin/src/handle.rs @@ -2,6 +2,7 @@ use std::{collections::HashMap, marker::PhantomData, sync::Arc}; use anyhow::Error; use dlopen2::wrapper::Container; +use giterated_models::operation::OperationState; use semver::Version; use tracing::{debug, trace}; @@ -40,6 +41,10 @@ impl PluginHandle { let initalization = Self::initialize_registration(&mut handle)?; + let type_metadata = Box::new(initalization.type_metadata.clone()); + + unsafe { handle.load_type_metadata(unsafe { Box::into_raw(type_metadata).cast() }) }; + trace!( "Loaded plugin {} (Version: {})", metadata.name, diff --git a/giterated-plugin/src/lib.rs b/giterated-plugin/src/lib.rs index 754b986..e86dcec 100644 --- a/giterated-plugin/src/lib.rs +++ b/giterated-plugin/src/lib.rs @@ -9,6 +9,8 @@ pub mod vtable; #[macro_use] extern crate tracing; +use std::{marker::PhantomData, mem::forget}; + use callback::RuntimeState; use dlopen2::wrapper::WrapperApi; @@ -27,6 +29,7 @@ pub struct GiteratedPluginApi { initialize_registration: unsafe extern "C" fn( init_state: *mut PluginInitializationState, ) -> *mut PluginInitializationState, + load_type_metadata: unsafe extern "C" fn(metadata: *mut ()), } #[repr(C)] @@ -56,7 +59,11 @@ impl FFIBox { impl ToString for FFIBox { fn to_string(&self) -> String { - todo!() + 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) } } @@ -73,3 +80,100 @@ impl std::ops::Deref for FFIBox { 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)>, +} + +#[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() }; +} diff --git a/giterated-plugin/src/new_stack/mod.rs b/giterated-plugin/src/new_stack/mod.rs index efce8d1..2485e97 100644 --- a/giterated-plugin/src/new_stack/mod.rs +++ b/giterated-plugin/src/new_stack/mod.rs @@ -6,7 +6,7 @@ use std::{collections::HashMap, fmt::Debug, mem::transmute, ptr::null_mut, sync: use giterated_models::{ error::OperationError, - object::GiteratedObject, + object::{GiteratedObject, ObjectRequestError}, operation::{GiteratedOperation, OperationState}, }; use semver::Version; @@ -38,7 +38,7 @@ impl std::ops::Deref for State { } } -#[derive(Default)] +#[derive(Default, Clone)] pub struct TypeMetadata { pub objects: HashMap<&'static str, ObjectVtable>, pub operations: HashMap, OperationVTable>, @@ -47,6 +47,12 @@ pub struct TypeMetadata { } impl TypeMetadata { + pub unsafe fn from_static() -> &'static Self { + giterated_static_runtime::get_type_metadata_reference() + .cast::() + .as_ref() + } + pub fn register_object(&mut self, object_kind: &'static str, vtable: ObjectVtable) { trace!("Registering type metadata for {}", object_kind); @@ -182,22 +188,32 @@ impl PluginState { } } - pub unsafe fn from_raw(raw: Box) -> Self { + pub unsafe fn from_box(raw: Box) -> Self { Self { inner: Box::into_raw(raw) as *mut _, } } + pub unsafe fn from_raw_ptr(raw: *const ()) -> Self { + Self { + inner: raw as *mut (), + } + } + pub fn null() -> Self { Self { inner: null_mut() } } } pub struct Runtime { - plugins: Vec<(PluginMeta, PluginHandle)>, + plugins: Vec, handlers: RuntimeHandlers, } +pub struct FfiRuntimeMetadata { + runtime: PluginState, +} + impl IntoRuntimeVtable for Runtime { unsafe extern "C" fn handle( _this: PluginState, @@ -209,6 +225,38 @@ impl IntoRuntimeVtable for Runtime { ) -> RuntimeFuture>> { todo!() } + + unsafe extern "C" fn get_object( + this: PluginState, + object_str: &str, + operation_state: *mut OperationState, + ) -> Result> + { + let runtime_state = unsafe { RuntimeState::from_static() }; + + let type_metada = runtime_state + .vtable + .type_metadata + .as_ref() + .unwrap_or_else(|| { + let runtime = this.transmute_ref::(); + + &runtime + .plugins + .first() + .unwrap() + .initialization + .type_metadata + }); + + for (object_type, object_vtable) in &type_metada.objects { + if let Ok(object) = (object_vtable.from_str)(object_str) { + return Ok(object); + } + } + + Err(OperationError::Operation(ObjectRequestError::Invalid)) + } } impl Runtime { @@ -219,13 +267,14 @@ impl Runtime { }) } - pub fn state(self: &Box, operation_state: &OperationState) -> RuntimeState { + pub fn state(self: &Box) -> RuntimeState { RuntimeState { vtable: RuntimeVTable { runtime: PluginState::from(self), handle_fn: ::handle, + get_object: ::get_object, + type_metadata: unsafe { TypeMetadata::from_static() }, }, - operation_state: operation_state.clone(), } } @@ -279,6 +328,8 @@ impl Runtime { trace!("Insertion of setting handler successful") } + + self.plugins.push(plugin); } pub fn init(self: Box) { diff --git a/giterated-plugin/src/vtable/object.rs b/giterated-plugin/src/vtable/object.rs index a04d897..b07f28a 100644 --- a/giterated-plugin/src/vtable/object.rs +++ b/giterated-plugin/src/vtable/object.rs @@ -1,61 +1,63 @@ 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, - 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; - 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; -} +// #[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 { + 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_boxed_str()) + 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).unwrap(); + 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); @@ -66,58 +68,63 @@ impl IntoObjectVTable for T { todo!() } - unsafe extern "C" fn is_same(_other: &AnyObject) -> bool { - todo!() - } - - fn object_kind() -> &'static str { + fn object_kind() -> &'static std::ffi::CStr { ::object_name() } + + // unsafe extern "C" fn is_same(_other: &AnyObject) -> bool { + // todo!() + // } } -#[repr(C)] -pub struct AnyObject { - /// 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: ObjectVtable, -} -impl AnyObject { - pub fn new(inner: T) -> Self { - Self { - inner: FFIBox::from_box(Box::new(inner)).untyped(), - vtable: ObjectVtable::new::(), - } - } +// 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 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 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 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 fn is_same(&self, other: &AnyObject) -> bool { +// unsafe { (self.vtable.is_same)(other) } +// } -impl ToString for AnyObject { - fn to_string(&self) -> String { - unsafe { (self.vtable.to_str)(self).to_string() } - } -} +// 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 { diff --git a/giterated-plugin/src/vtable/runtime.rs b/giterated-plugin/src/vtable/runtime.rs index 5315a88..915d2c0 100644 --- a/giterated-plugin/src/vtable/runtime.rs +++ b/giterated-plugin/src/vtable/runtime.rs @@ -1,10 +1,17 @@ -use giterated_models::error::OperationError; +use giterated_models::{ + error::OperationError, object::ObjectRequestError, operation::OperationState, +}; -use crate::{future::RuntimeFuture, new_stack::PluginState, AnyFailure, AnySuccess, FFIBox}; +use crate::{ + future::RuntimeFuture, + new_stack::{PluginState, TypeMetadata}, + AnyFailure, AnyObject, AnySuccess, FFIBox, +}; #[derive(Clone, Copy)] pub struct RuntimeVTable { pub(crate) runtime: PluginState, + pub(crate) type_metadata: *const TypeMetadata, pub(crate) handle_fn: unsafe extern "C" fn( PluginState, FFIBox, @@ -15,8 +22,17 @@ pub struct RuntimeVTable { ) -> RuntimeFuture< Result>, >, + pub(crate) get_object: + unsafe extern "C" fn( + PluginState, + &str, + *mut OperationState, + ) -> Result>, } +unsafe impl Send for RuntimeVTable {} +unsafe impl Sync for RuntimeVTable {} + pub trait IntoRuntimeVtable { unsafe extern "C" fn handle( this: PluginState, @@ -26,4 +42,10 @@ pub trait IntoRuntimeVtable { operation_payload: FFIBox<[u8]>, operation_state: FFIBox<[u8]>, ) -> RuntimeFuture>>; + + unsafe extern "C" fn get_object( + this: PluginState, + object_str: &str, + operation_state: *mut OperationState, + ) -> Result>; } diff --git a/plugins/example-plugin/src/lib.rs b/plugins/example-plugin/src/lib.rs index 53e7156..1895ac6 100644 --- a/plugins/example-plugin/src/lib.rs +++ b/plugins/example-plugin/src/lib.rs @@ -41,6 +41,12 @@ pub extern "C" fn load_initialization_vtable(init_vtable: &InitializationVTable) } #[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() diff --git a/plugins/example-plugin/src/main.rs b/plugins/example-plugin/src/main.rs index 4cf6f4a..294a417 100644 --- a/plugins/example-plugin/src/main.rs +++ b/plugins/example-plugin/src/main.rs @@ -18,12 +18,20 @@ async fn main() -> Result<(), anyhow::Error> { let handle = PluginHandle::from_dylib("example_plugin_dylib.dll").unwrap(); + info!("1"); + let mut runtime = Runtime::new(); + info!("2"); + runtime.insert_plugin(handle); + info!("3"); + runtime.init(); + info!("4"); + let runtime = unsafe { RuntimeState::from_static() }; let _object_request = ObjectRequest(String::from("foobar")); diff --git a/plugins/giterated-protocol/src/handlers.rs b/plugins/giterated-protocol/src/handlers.rs index 07f02d5..27f4921 100644 --- a/plugins/giterated-protocol/src/handlers.rs +++ b/plugins/giterated-protocol/src/handlers.rs @@ -131,7 +131,9 @@ pub async fn try_handle_with_remote( // operation.kind().operation_name // ); - let object = NetworkedObject(unsafe { (object_meta.to_str)(&object).as_ref().to_string() }); + // let object = NetworkedObject(unsafe { (object_meta.to_str)(object).as_ref().to_string() }); + + let object = todo!(); let payload = unsafe { (operation_meta.serialize)(&operation) }.unwrap(); let payload = Vec::from(payload.as_ref());