JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

MOre pre vtable changes

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨9cfa135

Showing ⁨⁨17⁩ changed files⁩ with ⁨⁨387⁩ insertions⁩ and ⁨⁨176⁩ deletions⁩

.vscode/launch.json

View file
@@ -44,6 +44,24 @@
44 44 {
45 45 "type": "lldb",
46 46 "request": "launch",
47 "name": "Debug executable 'example-plugin'",
48 "cargo": {
49 "args": [
50 "build",
51 "--bin=example-plugin",
52 "--package=example-plugin"
53 ],
54 "filter": {
55 "name": "example-plugin",
56 "kind": "bin"
57 }
58 },
59 "args": [],
60 "cwd": "${workspaceFolder}"
61 },
62 {
63 "type": "lldb",
64 "request": "launch",
47 65 "name": "Debug unit tests in executable 'giterated-daemon'",
48 66 "cargo": {
49 67 "args": [

Cargo.lock

View file
@@ -686,6 +686,10 @@ dependencies = [
686 686 ]
687 687
688 688 [[package]]
689 name = "giterated-abi"
690 version = "0.1.0"
691
692 [[package]]
689 693 name = "giterated-backend"
690 694 version = "0.1.0"
691 695 dependencies = [
@@ -789,6 +793,7 @@ dependencies = [
789 793 "async-trait",
790 794 "dlopen2",
791 795 "futures-util",
796 "giterated-abi",
792 797 "giterated-models",
793 798 "giterated-static-runtime",
794 799 "semver",

Cargo.toml

View file
@@ -1,5 +1,5 @@
1 1 [workspace]
2 members = [
2 members = [ "giterated-abi",
3 3 "giterated-daemon",
4 4 "giterated-models",
5 5 "giterated-plugin",
@@ -9,4 +9,4 @@ members = [
9 9 "plugins/giterated-backend",
10 10 "plugins/giterated-issues",
11 11 "plugins/giterated-protocol"
12 ]
12 \ No newline at end of file
12 ]

giterated-models/src/instance/mod.rs

View file
@@ -42,7 +42,7 @@ impl GiteratedObject for Instance {
42 42 }
43 43
44 44 fn from_object_str(object_str: &str) -> Result<Self, anyhow::Error> {
45 Ok(Instance::from_str(object_str).unwrap())
45 Ok(Instance::from_str(object_str)?)
46 46 }
47 47
48 48 fn home_uri(&self) -> String {

giterated-models/src/object/operations.rs

View file
@@ -26,6 +26,8 @@ impl GiteratedOperation<Instance> for ObjectRequest {
26 26 pub enum ObjectRequestError {
27 27 #[error("error decoding the object")]
28 28 Deserialization(String),
29 #[error("invalid object type")]
30 Invalid,
29 31 }
30 32
31 33 #[derive(Clone, Debug, Serialize, Deserialize)]

giterated-plugin/Cargo.toml

View file
@@ -12,6 +12,7 @@ thiserror = "1"
12 12 tracing = "0.1"
13 13 giterated-models = { path = "../giterated-models" }
14 14 giterated-static-runtime = { path = "giterated-static-runtime" }
15 giterated-abi = { path = "../giterated-abi" }
15 16 semver = "*"
16 17 serde_json = "1.0"
17 18 async-trait = "0.1"

giterated-plugin/giterated-static-runtime/src/lib.rs

View file
@@ -14,3 +14,13 @@ pub unsafe fn initialize_runtime(runtime_pointer: *mut ()) {
14 14 pub unsafe fn get_runtime_reference() -> NonNull<()> {
15 15 GITERATED_RUNTIME.assume_init_read().0
16 16 }
17
18 static mut GITERATED_TYPE_METADATA: MaybeUninit<RuntimePointer> = MaybeUninit::zeroed();
19
20 pub unsafe fn initialize_type_metadata(runtime_pointer: *mut ()) {
21 GITERATED_TYPE_METADATA.write(RuntimePointer(NonNull::new(runtime_pointer).unwrap()));
22 }
23
24 pub unsafe fn get_type_metadata_reference() -> NonNull<()> {
25 GITERATED_TYPE_METADATA.assume_init_read().0
26 }

giterated-plugin/src/callback/mod.rs

View file
@@ -14,7 +14,11 @@ pub use value::*;
14 14 mod setting;
15 15 pub use setting::*;
16 16
17 use crate::{vtable::RuntimeVTable, AnyObject, AnyOperation};
17 use crate::{
18 new_stack::{PluginState, Runtime},
19 vtable::RuntimeVTable,
20 AnyObject, AnyOperation,
21 };
18 22
19 23 /// A container for a callback pointer, used to provide an internal callback function or
20 24 /// state to a plugin when performing a callback.
@@ -32,16 +36,21 @@ impl CallbackPtr {
32 36 #[repr(C)]
33 37 pub struct RuntimeState {
34 38 pub vtable: RuntimeVTable,
35 pub operation_state: OperationState,
36 39 }
37 40
38 41 impl RuntimeState {
39 42 pub unsafe fn from_static() -> Self {
40 43 let runtime = giterated_static_runtime::get_runtime_reference();
41 44
42 let runtime = runtime.cast::<Box<RuntimeState>>().as_ref();
45 let runtime = runtime.cast::<Box<Runtime>>().as_ref();
46
47 runtime.state()
48 }
49
50 pub unsafe fn runtime_state() -> PluginState {
51 let runtime = giterated_static_runtime::get_runtime_reference();
43 52
44 *runtime.clone()
53 PluginState::from_raw_ptr(giterated_static_runtime::get_runtime_reference().as_ptr())
45 54 }
46 55 }
47 56
@@ -68,9 +77,21 @@ impl ObjectBackend for RuntimeState {
68 77
69 78 async fn get_object<O: GiteratedObject + Debug + 'static>(
70 79 &self,
71 _object_str: &str,
72 _operation_state: &OperationState,
80 object_str: &str,
81 operation_state: &OperationState,
73 82 ) -> Result<Object<O, Self>, OperationError<ObjectRequestError>> {
74 todo!()
83 let object = unsafe {
84 (self.vtable.get_object)(
85 Self::runtime_state(),
86 object_str,
87 &mut operation_state.clone(),
88 )
89 }?;
90
91 let object = unsafe { object.cast::<O>() };
92
93 panic!("object casted");
94
95 Ok(unsafe { Object::new_unchecked(object, self.clone()) })
75 96 }
76 97 }

giterated-plugin/src/future.rs

View file
@@ -1,67 +1,31 @@
1 1 use futures_util::future::BoxFuture;
2 2 use futures_util::FutureExt;
3 use giterated_abi::{FfiFuture, FfiValue, FfiValueMut, RuntimeFuturePoll};
3 4 use std::{
4 5 cell::UnsafeCell,
5 6 future::Future,
6 7 marker::PhantomData,
8 mem::transmute,
7 9 task::{Context, RawWaker, RawWakerVTable, Waker},
8 10 };
9 11
10 12 use crate::{callback::RuntimeState, new_stack::PluginState, FFIBox};
11 13
12 /// Future type for futures within the Runtime.
13 ///
14 /// Allows for plugins to spawn futures on the runtime.
15 #[derive(Clone)]
16 #[repr(C)]
17 pub struct RuntimeFuture<Output> {
18 /// The plugin's poll function, provided with the poll state for the future.
19 poll_fn: unsafe extern "C" fn(*const RuntimeFuture<()>, PluginState) -> RuntimeFuturePoll,
20 /// The function to wake the future, should only be called when the future is ready to be polled.
21 wake_fn: Option<unsafe extern "C" fn(*const RuntimeFuture<()>, PluginState)>,
22
23 /// The inner value that the owning plugin can use to poll the future
24 poll_state: PluginState,
25 /// The waker that the plugin uses for notification of the future's completion
26 waker_state: Option<PluginState>,
27
28 /// Whether its safe for the plugin to poll this future, panic if we think
29 /// we're supposed to poll and this is not set to `true`.
30 can_poll: bool,
31
32 _output_marker: PhantomData<Output>,
33 }
34
35 unsafe impl<Output> Send for RuntimeFuture<Output> where Output: Send {}
36 unsafe impl<Output> Sync for RuntimeFuture<Output> where Output: Sync {}
37
38 14 #[repr(C)]
39 15 pub struct RuntimeWakerCallback {
40 16 callback: PluginState,
41 17 waker_func: unsafe extern "C" fn(PluginState),
42 18 }
43 19
44 #[repr(C)]
45 pub enum RuntimeFuturePoll {
46 Ready(FFIBox<()>),
47 Pending,
48 }
49
50 20 pub struct WakerState {
51 21 waker: Waker,
52 22 }
53 23
54 impl<Output> RuntimeFuture<Output> {
55 pub(crate) unsafe fn poll(&mut self) -> RuntimeFuturePoll {
56 todo!()
57 }
58 }
59
60 24 unsafe extern "C" fn wake(_waker: PluginState) {}
61 25
62 26 pub struct LocalRuntimeFuture<Output> {
63 27 inner: BoxFuture<'static, Output>,
64 runtime_future: UnsafeCell<RuntimeFuture<Output>>,
28 runtime_future: UnsafeCell<FfiFuture<Output>>,
65 29 }
66 30
67 31 unsafe impl<Output> Send for LocalRuntimeFuture<Output> where Output: Send {}
@@ -70,7 +34,7 @@ unsafe impl<Output> Sync for LocalRuntimeFuture<Output> where Output: Sync {}
70 34 impl<Output> LocalRuntimeFuture<Output> {
71 35 pub fn finalize(self) {}
72 36
73 pub fn into_runtime(&self) -> RuntimeFuture<Output> {
37 pub fn into_runtime(&self) -> FfiFuture<Output> {
74 38 todo!()
75 39 }
76 40 }
@@ -93,25 +57,19 @@ impl RuntimeFuturesExt for RuntimeState {
93 57 FFIBox::from_box(Box::new(result)).untyped()
94 58 };
95 59
96 let runtime_future = RuntimeFuture {
97 poll_fn: poll_local,
98 wake_fn: None,
99 poll_state: PluginState::from(type_eraser.boxed()),
100 waker_state: None,
101 can_poll: true,
102 _output_marker: PhantomData,
103 };
60 let runtime_future = unsafe { FfiFuture::from_raw(poll_local, type_eraser.boxed()) };
104 61
105 runtime_future
62 RuntimeFuture(runtime_future)
106 63 }
107 64 }
108 65
109 66 unsafe extern "C" fn poll_local(
110 _future: *const RuntimeFuture<()>,
111 mut future_state: PluginState,
67 _future: FfiValueMut<FfiFuture<()>>,
68 mut future_state: FfiValueMut<()>,
112 69 ) -> RuntimeFuturePoll {
113 let mut future: Box<BoxFuture<'static, FFIBox<()>>> = future_state.transmute_owned();
114 let runtime_future = future.as_ref();
70 let mut future_state: FfiValueMut<BoxFuture<'static, FfiValue<()>>> = transmute(future_state);
71
72 let runtime_future = future_state.as_ref();
115 73
116 74 let raw_waker = RawWaker::new(
117 75 Box::into_raw(Box::new(runtime_future)) as *const (),
@@ -121,13 +79,7 @@ unsafe extern "C" fn poll_local(
121 79 let waker = unsafe { Waker::from_raw(raw_waker) };
122 80
123 81 // SAFETY: Pretty sure this has to be static lol
124 let poll_result = future.poll_unpin(&mut Context::from_waker(&waker));
125
126 #[allow(unused_assignments)]
127 {
128 // This is meant to communicate with the compiler the lifecycle of the object
129 future_state = PluginState::from_raw(future);
130 }
82 let poll_result = future_state.poll_unpin(&mut Context::from_waker(&waker));
131 83
132 84 match poll_result {
133 85 std::task::Poll::Ready(result) => RuntimeFuturePoll::Ready(result),
@@ -162,6 +114,9 @@ mod runtime_waker_vtable {
162 114 }
163 115 }
164 116
117 #[repr(transparent)]
118 pub struct RuntimeFuture<Output>(FfiFuture<Output>);
119
165 120 /// Allows for a remote future to be polled on the target.
166 121 ///
167 122 /// The target can be the host or a plugin, but the future should only be polled by one
@@ -179,25 +134,19 @@ impl<Output: Unpin> Future for RuntimeFuture<Output> {
179 134
180 135 let waker_state = PluginState::from(waker_state);
181 136
182 self.waker_state = Some(waker_state);
183 self.wake_fn = Some(wake_local);
137 unsafe { self.0.write_waker(wake_local, waker_state) };
184 138
185 match unsafe {
186 (self.poll_fn)(
187 &*self as *const RuntimeFuture<_> as *const RuntimeFuture<()>,
188 self.poll_state,
189 )
190 } {
139 match unsafe { self.0.poll() } {
191 140 RuntimeFuturePoll::Ready(result) => {
192 let result: Output = unsafe { *result.retype::<Output>().into_box() };
141 let result: FfiValue<Output> = unsafe { transmute(result) };
193 142
194 std::task::Poll::Ready(result)
143 std::task::Poll::Ready(result.take())
195 144 }
196 145 RuntimeFuturePoll::Pending => std::task::Poll::Pending,
197 146 }
198 147 }
199 148 }
200 149
201 unsafe extern "C" fn wake_local(_future: *const RuntimeFuture<()>, _waker_state: PluginState) {
150 unsafe extern "C" fn wake_local(future: FfiValueMut<FfiFuture<()>>, state: FfiValueMut<()>) {
202 151 todo!()
203 152 }

giterated-plugin/src/handle.rs

View file
@@ -2,6 +2,7 @@ use std::{collections::HashMap, marker::PhantomData, sync::Arc};
2 2
3 3 use anyhow::Error;
4 4 use dlopen2::wrapper::Container;
5 use giterated_models::operation::OperationState;
5 6 use semver::Version;
6 7 use tracing::{debug, trace};
7 8
@@ -40,6 +41,10 @@ impl PluginHandle {
40 41
41 42 let initalization = Self::initialize_registration(&mut handle)?;
42 43
44 let type_metadata = Box::new(initalization.type_metadata.clone());
45
46 unsafe { handle.load_type_metadata(unsafe { Box::into_raw(type_metadata).cast() }) };
47
43 48 trace!(
44 49 "Loaded plugin {} (Version: {})",
45 50 metadata.name,

giterated-plugin/src/lib.rs

View file
@@ -9,6 +9,8 @@ pub mod vtable;
9 9 #[macro_use]
10 10 extern crate tracing;
11 11
12 use std::{marker::PhantomData, mem::forget};
13
12 14 use callback::RuntimeState;
13 15 use dlopen2::wrapper::WrapperApi;
14 16
@@ -27,6 +29,7 @@ pub struct GiteratedPluginApi {
27 29 initialize_registration: unsafe extern "C" fn(
28 30 init_state: *mut PluginInitializationState,
29 31 ) -> *mut PluginInitializationState,
32 load_type_metadata: unsafe extern "C" fn(metadata: *mut ()),
30 33 }
31 34
32 35 #[repr(C)]
@@ -56,7 +59,11 @@ impl<T: ?Sized> FFIBox<T> {
56 59
57 60 impl ToString for FFIBox<str> {
58 61 fn to_string(&self) -> String {
59 todo!()
62 let slice: Box<[u8]> = unsafe { Box::from_raw(self.0.clone() as *mut _) };
63
64 let string = unsafe { std::str::from_boxed_utf8_unchecked(slice) };
65
66 String::from(string)
60 67 }
61 68 }
62 69
@@ -73,3 +80,100 @@ impl<T: ?Sized> std::ops::Deref for FFIBox<T> {
73 80 unsafe { self.0.as_ref() }.unwrap()
74 81 }
75 82 }
83
84 #[repr(transparent)]
85 pub struct FFI<T, Ownership: FfiOwnershipDrop> {
86 /// Can either be a pointer to `FFIData<T>` or to `T`
87 /// depending on the ownership of the FFI reference.
88 inner: *const (),
89 _marker: PhantomData<(T, Ownership)>,
90 }
91
92 #[repr(C)]
93 pub struct FFIData<T> {
94 /// SAFETY: THIS VALUE COULD BE NULL.
95 drop_fn: *const extern "C" fn(*const FFIData<T>),
96 drop_state: *const (),
97
98 allocation: T,
99 }
100
101 pub struct Owned;
102
103 impl FfiOwnershipDrop for Owned {}
104
105 pub struct StackOwned;
106
107 impl FfiOwnershipDrop for StackOwned {}
108
109 trait FfiOwnershipDrop {}
110
111 pub struct PinnedRef;
112
113 impl FfiOwnershipDrop for PinnedRef {}
114
115 pub struct PinnedMut;
116
117 impl FfiOwnershipDrop for PinnedMut {}
118
119 impl<T> FFI<T, Owned> {
120 pub fn place_heap(value: T) -> FFI<T, Owned> {
121 todo!()
122 }
123
124 pub fn ref_guard<'a>(&'a self) -> StackPinnedGuard<'a, T> {
125 todo!()
126 }
127 }
128
129 impl<T> FFI<T, StackOwned> {
130 pub fn place_stack<'a>(value: T) -> StackPinned<'a, T> {
131 todo!()
132 }
133 }
134
135 pub struct StackPinned<'a, T> {
136 descriptor: FFIData<T>,
137 _lifetime: PhantomData<&'a ()>,
138 }
139
140 impl<'a, T> StackPinned<'a, T> {
141 pub unsafe fn grant_ref(&self) -> FFI<T, PinnedRef> {
142 todo!()
143 }
144 }
145
146 pub struct StackPinnedGuard<'a, T> {
147 pinned_owned: &'a FFI<T, Owned>,
148 }
149
150 impl<'a, T> StackPinnedGuard<'a, T> {
151 pub unsafe fn grant_ref(&self) -> FFI<T, PinnedRef> {
152 todo!()
153 }
154 }
155
156 impl<T, O: FfiOwnershipDrop> Drop for FFI<T, O> {
157 fn drop(&mut self) {
158 todo!()
159 }
160 }
161
162 pub struct FFISlice<T: ?Sized> {
163 len: usize,
164 slice: T,
165 }
166
167 fn example() {
168 let stack_ffi_value = FFI::place_stack(());
169
170 let stack_ffi_ref = unsafe { stack_ffi_value.grant_ref() };
171
172 let foo = stack_ffi_ref;
173
174 let heap_ffi_value = FFI::place_heap(());
175
176 let heap_ffi_ref_guard = heap_ffi_value.ref_guard();
177
178 let heap_ffi_ref = unsafe { heap_ffi_ref_guard.grant_ref() };
179 }

giterated-plugin/src/new_stack/mod.rs

View file
@@ -6,7 +6,7 @@ use std::{collections::HashMap, fmt::Debug, mem::transmute, ptr::null_mut, sync:
6 6
7 7 use giterated_models::{
8 8 error::OperationError,
9 object::GiteratedObject,
9 object::{GiteratedObject, ObjectRequestError},
10 10 operation::{GiteratedOperation, OperationState},
11 11 };
12 12 use semver::Version;
@@ -38,7 +38,7 @@ impl<S> std::ops::Deref for State<S> {
38 38 }
39 39 }
40 40
41 #[derive(Default)]
41 #[derive(Default, Clone)]
42 42 pub struct TypeMetadata {
43 43 pub objects: HashMap<&'static str, ObjectVtable>,
44 44 pub operations: HashMap<ObjectOperationPair<'static>, OperationVTable>,
@@ -47,6 +47,12 @@ pub struct TypeMetadata {
47 47 }
48 48
49 49 impl TypeMetadata {
50 pub unsafe fn from_static() -> &'static Self {
51 giterated_static_runtime::get_type_metadata_reference()
52 .cast::<TypeMetadata>()
53 .as_ref()
54 }
55
50 56 pub fn register_object(&mut self, object_kind: &'static str, vtable: ObjectVtable) {
51 57 trace!("Registering type metadata for {}", object_kind);
52 58
@@ -182,22 +188,32 @@ impl PluginState {
182 188 }
183 189 }
184 190
185 pub unsafe fn from_raw<S>(raw: Box<S>) -> Self {
191 pub unsafe fn from_box<S>(raw: Box<S>) -> Self {
186 192 Self {
187 193 inner: Box::into_raw(raw) as *mut _,
188 194 }
189 195 }
190 196
197 pub unsafe fn from_raw_ptr(raw: *const ()) -> Self {
198 Self {
199 inner: raw as *mut (),
200 }
201 }
202
191 203 pub fn null() -> Self {
192 204 Self { inner: null_mut() }
193 205 }
194 206 }
195 207
196 208 pub struct Runtime {
197 plugins: Vec<(PluginMeta, PluginHandle)>,
209 plugins: Vec<PluginHandle>,
198 210 handlers: RuntimeHandlers,
199 211 }
200 212
213 pub struct FfiRuntimeMetadata {
214 runtime: PluginState,
215 }
216
201 217 impl IntoRuntimeVtable for Runtime {
202 218 unsafe extern "C" fn handle(
203 219 _this: PluginState,
@@ -209,6 +225,38 @@ impl IntoRuntimeVtable for Runtime {
209 225 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
210 226 todo!()
211 227 }
228
229 unsafe extern "C" fn get_object(
230 this: PluginState,
231 object_str: &str,
232 operation_state: *mut OperationState,
233 ) -> Result<crate::AnyObject, OperationError<giterated_models::object::ObjectRequestError>>
234 {
235 let runtime_state = unsafe { RuntimeState::from_static() };
236
237 let type_metada = runtime_state
238 .vtable
239 .type_metadata
240 .as_ref()
241 .unwrap_or_else(|| {
242 let runtime = this.transmute_ref::<Runtime>();
243
244 &runtime
245 .plugins
246 .first()
247 .unwrap()
248 .initialization
249 .type_metadata
250 });
251
252 for (object_type, object_vtable) in &type_metada.objects {
253 if let Ok(object) = (object_vtable.from_str)(object_str) {
254 return Ok(object);
255 }
256 }
257
258 Err(OperationError::Operation(ObjectRequestError::Invalid))
259 }
212 260 }
213 261
214 262 impl Runtime {
@@ -219,13 +267,14 @@ impl Runtime {
219 267 })
220 268 }
221 269
222 pub fn state(self: &Box<Self>, operation_state: &OperationState) -> RuntimeState {
270 pub fn state(self: &Box<Self>) -> RuntimeState {
223 271 RuntimeState {
224 272 vtable: RuntimeVTable {
225 273 runtime: PluginState::from(self),
226 274 handle_fn: <Runtime as IntoRuntimeVtable>::handle,
275 get_object: <Runtime as IntoRuntimeVtable>::get_object,
276 type_metadata: unsafe { TypeMetadata::from_static() },
227 277 },
228 operation_state: operation_state.clone(),
229 278 }
230 279 }
231 280
@@ -279,6 +328,8 @@ impl Runtime {
279 328
280 329 trace!("Insertion of setting handler successful")
281 330 }
331
332 self.plugins.push(plugin);
282 333 }
283 334
284 335 pub fn init(self: Box<Self>) {

giterated-plugin/src/vtable/object.rs

View file
@@ -1,61 +1,63 @@
1 1 use std::{mem::transmute, str::FromStr};
2 2
3 use giterated_abi::vtable::IntoObjectVTable;
3 4 use giterated_models::object::GiteratedObject;
4 5
5 6 use crate::FFIBox;
6 7
7 #[derive(Clone, Copy)]
8 #[repr(C)]
9 pub struct ObjectVtable {
10 object_kind: *const u8,
11 object_kind_len: usize,
12 pub to_str: unsafe extern "C" fn(&AnyObject) -> FFIBox<str>,
13 pub from_str: unsafe extern "C" fn(&str) -> Result<AnyObject, FFIBox<str>>,
14 pub home_uri: unsafe extern "C" fn(&AnyObject) -> FFIBox<str>,
15 pub is_same: unsafe extern "C" fn(&AnyObject) -> bool,
16 }
17
18 impl ObjectVtable {
19 pub fn new<T: IntoObjectVTable>() -> Self {
20 let object_kind = T::object_kind().as_ptr();
21 let object_kind_len = T::object_kind().len();
22
23 Self {
24 to_str: T::to_str,
25 from_str: T::from_str,
26 home_uri: T::home_uri,
27 is_same: T::is_same,
28 object_kind,
29 object_kind_len,
30 }
31 }
32
33 pub fn kind(&self) -> &'static str {
34 let slice = unsafe { std::slice::from_raw_parts(self.object_kind, self.object_kind_len) };
35
36 std::str::from_utf8(slice).unwrap()
37 }
38 }
39
40 pub trait IntoObjectVTable {
41 fn object_kind() -> &'static str;
42 unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<str>;
43 unsafe extern "C" fn from_str(src: &str) -> Result<AnyObject, FFIBox<str>>;
44 unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox<str>;
45 unsafe extern "C" fn is_same(other: &AnyObject) -> bool;
46 }
8 // #[derive(Clone, Copy)]
9 // #[repr(C)]
10 // pub struct ObjectVtable {
11 // object_kind: *const u8,
12 // object_kind_len: usize,
13 // pub to_str: unsafe extern "C" fn(&AnyObject) -> FFIBox<[u8]>,
14 // pub from_str: unsafe extern "C" fn(&str) -> Result<AnyObject, FFIBox<str>>,
15 // pub home_uri: unsafe extern "C" fn(&AnyObject) -> FFIBox<str>,
16 // pub is_same: unsafe extern "C" fn(&AnyObject) -> bool,
17 // }
18
19 // impl ObjectVtable {
20 // pub fn new<T: IntoObjectVTable>() -> Self {
21 // let object_kind = T::object_kind().as_ptr();
22 // let object_kind_len = T::object_kind().len();
23
24 // Self {
25 // to_str: T::to_str,
26 // from_str: T::from_str,
27 // home_uri: T::home_uri,
28 // is_same: T::is_same,
29 // object_kind,
30 // object_kind_len,
31 // }
32 // }
33
34 // pub fn kind(&self) -> &'static str {
35 // let slice = unsafe { std::slice::from_raw_parts(self.object_kind, self.object_kind_len) };
36
37 // std::str::from_utf8(slice).unwrap()
38 // }
39 // }
40
41 // pub trait IntoObjectVTable {
42 // fn object_kind() -> &'static str;
43 // unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<[u8]>;
44 // unsafe extern "C" fn from_str(src: &str) -> Result<AnyObject, FFIBox<str>>;
45 // unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox<str>;
46 // unsafe extern "C" fn is_same(other: &AnyObject) -> bool;
47 // }
47 48
48 49 impl<T: GiteratedObject + 'static> IntoObjectVTable for T {
49 unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<str> {
50 unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<[u8]> {
50 51 let this: &Box<T> = this.transmute_ref();
51 52
52 53 let result = this.to_string();
53 54
54 FFIBox::from_box(result.into_boxed_str())
55 FFIBox::from_box(result.into_bytes().into_boxed_slice())
55 56 }
56 57
57 58 unsafe extern "C" fn from_str(src: &str) -> Result<AnyObject, FFIBox<str>> {
58 let result = T::from_object_str(src).unwrap();
59 let result = T::from_object_str(src)
60 .map_err(|err| FFIBox::from_box(err.to_string().into_boxed_str()))?;
59 61
60 62 let any_object = AnyObject::new(result);
61 63
@@ -66,58 +68,63 @@ impl<T: GiteratedObject + 'static> IntoObjectVTable for T {
66 68 todo!()
67 69 }
68 70
69 unsafe extern "C" fn is_same(_other: &AnyObject) -> bool {
70 todo!()
71 }
72
73 fn object_kind() -> &'static str {
71 fn object_kind() -> &'static std::ffi::CStr {
74 72 <T as GiteratedObject>::object_name()
75 73 }
74
75 // unsafe extern "C" fn is_same(_other: &AnyObject) -> bool {
76 // todo!()
77 // }
76 78 }
77 79
78 #[repr(C)]
79 pub struct AnyObject {
80 /// A pointer to the plugin-local object type. We are not capable of
81 /// knowing what this type is, we use the provided vtable.
82 inner: FFIBox<()>,
83 vtable: ObjectVtable,
84 }
85 80
86 impl AnyObject {
87 pub fn new<T: IntoObjectVTable>(inner: T) -> Self {
88 Self {
89 inner: FFIBox::from_box(Box::new(inner)).untyped(),
90 vtable: ObjectVtable::new::<T>(),
91 }
92 }
81 // impl AnyObject {
82 // pub fn new<T: IntoObjectVTable>(inner: T) -> Self {
83 // Self {
84 // inner: FFIBox::from_box(Box::new(inner)).untyped(),
85 // vtable: ObjectVtable::new::<T>(),
86 // }
87 // }
93 88
94 pub fn vtable(&self) -> ObjectVtable {
95 self.vtable
96 }
89 // pub fn vtable(&self) -> ObjectVtable {
90 // self.vtable
91 // }
97 92
98 pub fn object_kind(&self) -> &str {
99 unsafe {
100 std::str::from_utf8_unchecked(std::slice::from_raw_parts(
101 self.vtable.object_kind,
102 self.vtable.object_kind_len,
103 ))
104 }
105 }
93 // pub fn object_kind(&self) -> &str {
94 // unsafe {
95 // std::str::from_utf8_unchecked(std::slice::from_raw_parts(
96 // self.vtable.object_kind,
97 // self.vtable.object_kind_len,
98 // ))
99 // }
100 // }
106 101
107 pub fn home_uri(&self) -> String {
108 unsafe { (self.vtable.home_uri)(self).to_string() }
109 }
102 // pub fn home_uri(&self) -> String {
103 // unsafe { (self.vtable.home_uri)(self).to_string() }
104 // }
110 105
111 pub fn is_same(&self, other: &AnyObject) -> bool {
112 unsafe { (self.vtable.is_same)(other) }
113 }
114 }
106 // pub fn is_same(&self, other: &AnyObject) -> bool {
107 // unsafe { (self.vtable.is_same)(other) }
108 // }
115 109
116 impl ToString for AnyObject {
117 fn to_string(&self) -> String {
118 unsafe { (self.vtable.to_str)(self).to_string() }
119 }
120 }
110 // pub unsafe fn cast<T: IntoObjectVTable + GiteratedObject>(self) -> T {
111 // assert_eq!(self.object_kind(), T::object_kind());
112
113 // info!("{}", self.to_string());
114
115 // T::from_object_str(&self.to_string()).unwrap()
116 // }
117 // }
118
119 // impl ToString for AnyObject {
120 // fn to_string(&self) -> String {
121 // let slice: Box<[u8]> = unsafe { Box::from_raw((self.vtable.to_str)(&self).0 as *mut _) };
122
123 // let string = unsafe { std::str::from_boxed_utf8_unchecked(slice) };
124
125 // String::from(string)
126 // }
127 // }
121 128
122 129 impl AnyObject {
123 130 pub unsafe fn transmute_owned<T>(&mut self) -> Box<T> {

giterated-plugin/src/vtable/runtime.rs

View file
@@ -1,10 +1,17 @@
1 use giterated_models::error::OperationError;
1 use giterated_models::{
2 error::OperationError, object::ObjectRequestError, operation::OperationState,
3 };
2 4
3 use crate::{future::RuntimeFuture, new_stack::PluginState, AnyFailure, AnySuccess, FFIBox};
5 use crate::{
6 future::RuntimeFuture,
7 new_stack::{PluginState, TypeMetadata},
8 AnyFailure, AnyObject, AnySuccess, FFIBox,
9 };
4 10
5 11 #[derive(Clone, Copy)]
6 12 pub struct RuntimeVTable {
7 13 pub(crate) runtime: PluginState,
14 pub(crate) type_metadata: *const TypeMetadata,
8 15 pub(crate) handle_fn: unsafe extern "C" fn(
9 16 PluginState,
10 17 FFIBox<str>,
@@ -15,8 +22,17 @@ pub struct RuntimeVTable {
15 22 ) -> RuntimeFuture<
16 23 Result<AnySuccess, OperationError<AnyFailure>>,
17 24 >,
25 pub(crate) get_object:
26 unsafe extern "C" fn(
27 PluginState,
28 &str,
29 *mut OperationState,
30 ) -> Result<AnyObject, OperationError<ObjectRequestError>>,
18 31 }
19 32
33 unsafe impl Send for RuntimeVTable {}
34 unsafe impl Sync for RuntimeVTable {}
35
20 36 pub trait IntoRuntimeVtable {
21 37 unsafe extern "C" fn handle(
22 38 this: PluginState,
@@ -26,4 +42,10 @@ pub trait IntoRuntimeVtable {
26 42 operation_payload: FFIBox<[u8]>,
27 43 operation_state: FFIBox<[u8]>,
28 44 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>>;
45
46 unsafe extern "C" fn get_object(
47 this: PluginState,
48 object_str: &str,
49 operation_state: *mut OperationState,
50 ) -> Result<AnyObject, OperationError<ObjectRequestError>>;
29 51 }

plugins/example-plugin/src/lib.rs

View file
@@ -41,6 +41,12 @@ pub extern "C" fn load_initialization_vtable(init_vtable: &InitializationVTable)
41 41 }
42 42
43 43 #[no_mangle]
44 pub extern "C" fn load_type_metadata(metadata: *mut ()) {
45 unsafe { giterated_static_runtime::initialize_type_metadata(metadata) }
46 println!("Initialized type metadata for plugin");
47 }
48
49 #[no_mangle]
44 50 pub extern "C" fn initialize() -> PluginState {
45 51 tracing_subscriber::fmt()
46 52 .pretty()

plugins/example-plugin/src/main.rs

View file
@@ -18,12 +18,20 @@ async fn main() -> Result<(), anyhow::Error> {
18 18
19 19 let handle = PluginHandle::from_dylib("example_plugin_dylib.dll").unwrap();
20 20
21 info!("1");
22
21 23 let mut runtime = Runtime::new();
22 24
25 info!("2");
26
23 27 runtime.insert_plugin(handle);
24 28
29 info!("3");
30
25 31 runtime.init();
26 32
33 info!("4");
34
27 35 let runtime = unsafe { RuntimeState::from_static() };
28 36
29 37 let _object_request = ObjectRequest(String::from("foobar"));

plugins/giterated-protocol/src/handlers.rs

View file
@@ -131,7 +131,9 @@ pub async fn try_handle_with_remote(
131 131 // operation.kind().operation_name
132 132 // );
133 133
134 let object = NetworkedObject(unsafe { (object_meta.to_str)(&object).as_ref().to_string() });
134 // let object = NetworkedObject(unsafe { (object_meta.to_str)(object).as_ref().to_string() });
135
136 let object = todo!();
135 137
136 138 let payload = unsafe { (operation_meta.serialize)(&operation) }.unwrap();
137 139 let payload = Vec::from(payload.as_ref());