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

ambee/giterated

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

More progress :)

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨92c3f32

Showing ⁨⁨45⁩ changed files⁩ with ⁨⁨1034⁩ insertions⁩ and ⁨⁨495⁩ deletions⁩

Cargo.lock

View file
@@ -489,7 +489,9 @@ dependencies = [
489 489 "giterated-models",
490 490 "giterated-plugin",
491 491 "giterated-plugin-sys",
492 "giterated-static-runtime",
492 493 "serde_json",
494 "tokio",
493 495 "tracing",
494 496 "tracing-subscriber",
495 497 ]
@@ -559,9 +561,9 @@ dependencies = [
559 561
560 562 [[package]]
561 563 name = "futures-core"
562 version = "0.3.29"
564 version = "0.3.30"
563 565 source = "registry+https://github.com/rust-lang/crates.io-index"
564 checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
566 checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
565 567
566 568 [[package]]
567 569 name = "futures-executor"
@@ -587,15 +589,15 @@ dependencies = [
587 589
588 590 [[package]]
589 591 name = "futures-io"
590 version = "0.3.29"
592 version = "0.3.30"
591 593 source = "registry+https://github.com/rust-lang/crates.io-index"
592 checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
594 checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
593 595
594 596 [[package]]
595 597 name = "futures-macro"
596 version = "0.3.29"
598 version = "0.3.30"
597 599 source = "registry+https://github.com/rust-lang/crates.io-index"
598 checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
600 checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
599 601 dependencies = [
600 602 "proc-macro2",
601 603 "quote",
@@ -604,21 +606,21 @@ dependencies = [
604 606
605 607 [[package]]
606 608 name = "futures-sink"
607 version = "0.3.29"
609 version = "0.3.30"
608 610 source = "registry+https://github.com/rust-lang/crates.io-index"
609 checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
611 checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
610 612
611 613 [[package]]
612 614 name = "futures-task"
613 version = "0.3.29"
615 version = "0.3.30"
614 616 source = "registry+https://github.com/rust-lang/crates.io-index"
615 checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
617 checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
616 618
617 619 [[package]]
618 620 name = "futures-util"
619 version = "0.3.29"
621 version = "0.3.30"
620 622 source = "registry+https://github.com/rust-lang/crates.io-index"
621 checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
623 checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
622 624 dependencies = [
623 625 "futures-core",
624 626 "futures-io",
@@ -786,11 +788,14 @@ dependencies = [
786 788 "anyhow",
787 789 "async-trait",
788 790 "dlopen2",
791 "futures-util",
789 792 "giterated-models",
793 "giterated-static-runtime",
790 794 "semver",
791 795 "serde",
792 796 "serde_json",
793 797 "thiserror",
798 "tokio",
794 799 "tracing",
795 800 ]
796 801
@@ -827,6 +832,10 @@ dependencies = [
827 832 ]
828 833
829 834 [[package]]
835 name = "giterated-static-runtime"
836 version = "0.1.0"
837
838 [[package]]
830 839 name = "h2"
831 840 version = "0.3.21"
832 841 source = "registry+https://github.com/rust-lang/crates.io-index"

Cargo.toml

View file
@@ -4,6 +4,7 @@ members = [
4 4 "giterated-models",
5 5 "giterated-plugin",
6 6 "giterated-plugin/giterated-plugin-sys",
7 "giterated-plugin/giterated-static-runtime",
7 8 "plugins/example-plugin",
8 9 "plugins/giterated-backend",
9 10 "plugins/giterated-issues",

giterated-daemon/src/client.rs

View file
@@ -5,8 +5,9 @@ use giterated_models::{
5 5 error::{IntoInternalError, OperationError},
6 6 instance::Instance,
7 7 object_backend::ObjectBackend,
8 operation::OperationState,
8 9 };
9 use giterated_plugin::new_stack::{handle::RuntimeHandle, OperationState, Runtime};
10 use giterated_plugin::new_stack::{handle::RuntimeHandle, Runtime};
10 11 use giterated_protocol::{
11 12 handlers::{NetworkedObject, NetworkedOperation},
12 13 AuthenticatedPayload,
@@ -17,7 +18,7 @@ use tokio_tungstenite::{tungstenite::Message, WebSocketStream};
17 18 pub async fn client_wrapper(
18 19 _our_instance: Instance,
19 20 mut socket: WebSocketStream<TcpStream>,
20 _runtime: Arc<Runtime>,
21 _runtime: Arc<Box<Runtime>>,
21 22 ) {
22 23 loop {
23 24 let message = socket.next().await;
@@ -30,19 +31,15 @@ pub async fn client_wrapper(
30 31 let message = message.unwrap();
31 32
32 33 let payload = match message {
33 Ok(message) => {
34 let payload = match message {
35 Message::Binary(payload) => payload,
36 Message::Ping(_) => {
37 let _ = socket.send(Message::Pong(vec![])).await;
38 continue;
39 }
40 Message::Close(_) => return,
41 _ => continue,
42 };
43
44 payload
45 }
34 Ok(message) => match message {
35 Message::Binary(payload) => payload,
36 Message::Ping(_) => {
37 let _ = socket.send(Message::Pong(vec![])).await;
38 continue;
39 }
40 Message::Close(_) => return,
41 _ => continue,
42 },
46 43 Err(err) => {
47 44 // Connection error
48 45 warn!("A connection error has occured: {:?}", err);

giterated-daemon/src/main.rs

View file
@@ -10,7 +10,7 @@ use tokio::{
10 10 fs::File,
11 11 io::{AsyncRead, AsyncReadExt, AsyncWrite},
12 12 net::{TcpListener, TcpStream},
13 sync::{Mutex, OnceCell},
13 sync::Mutex,
14 14 };
15 15 use tokio_tungstenite::{accept_async, WebSocketStream};
16 16 use tokio_util::task::LocalPoolHandle;
@@ -42,14 +42,14 @@ async fn main() -> Result<(), Error> {
42 42 sqlx::migrate!().run(&db_pool).await?;
43 43 info!("Connected");
44 44
45 let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter {
45 let _token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter {
46 46 config: config.clone(),
47 47 instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
48 48 }));
49 49
50 50 info!("Connected");
51 51
52 let mut runtime = Runtime::new();
52 let runtime = Runtime::new();
53 53
54 54 let runtime = Arc::new(runtime);
55 55

giterated-models/src/ffi.rs

View file
@@ -0,0 +1,13 @@
1 pub trait ToFfi {
2 fn to_ffi_bytes(&self) -> Vec<u8>;
3 }
4
5 pub trait FromFfi: Sized {
6 fn from_ffi_bytes(bytes: &[u8]) -> Option<Self>;
7 }
8
9 pub trait FfiLabel {
10 fn prefix(&self) -> &'static str;
11
12 fn type_label(&self) -> &'static str;
13 }

giterated-models/src/instance/mod.rs

View file
@@ -8,7 +8,6 @@ mod values;
8 8
9 9 pub use operations::*;
10 10 use url::Url;
11 pub use values::*;
12 11
13 12 use crate::object::GiteratedObject;
14 13

giterated-models/src/instance/operations.rs

View file
@@ -6,7 +6,7 @@ use crate::{
6 6 error::{InstanceError, OperationError},
7 7 object::Object,
8 8 object_backend::ObjectBackend,
9 operation::GiteratedOperation,
9 operation::{GiteratedOperation, OperationState},
10 10 repository::{Repository, RepositoryVisibility},
11 11 user::{Password, User},
12 12 };
@@ -104,13 +104,13 @@ impl GiteratedOperation<Instance> for RepositoryCreateRequest {
104 104 type Failure = InstanceError;
105 105 }
106 106
107 impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S, Instance, B> {
107 impl<B: ObjectBackend + std::fmt::Debug> Object<Instance, B> {
108 108 pub async fn register_account(
109 109 &mut self,
110 110 email: Option<&str>,
111 111 username: &str,
112 112 password: &Secret<Password>,
113 operation_state: &S,
113 operation_state: &OperationState,
114 114 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
115 115 self.request::<RegisterAccountRequest>(
116 116 RegisterAccountRequest {
@@ -127,7 +127,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
127 127 &mut self,
128 128 username: &str,
129 129 password: &Secret<Password>,
130 operation_state: &S,
130 operation_state: &OperationState,
131 131 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
132 132 self.request::<AuthenticationTokenRequest>(
133 133 AuthenticationTokenRequest {
@@ -145,7 +145,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
145 145 instance: &Instance,
146 146 username: &str,
147 147 password: &Secret<Password>,
148 operation_state: &S,
148 operation_state: &OperationState,
149 149 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
150 150 self.request::<AuthenticationTokenRequest>(
151 151 AuthenticationTokenRequest {
@@ -161,7 +161,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
161 161 pub async fn token_extension(
162 162 &mut self,
163 163 token: &UserAuthenticationToken,
164 operation_state: &S,
164 operation_state: &OperationState,
165 165 ) -> Result<Option<UserAuthenticationToken>, OperationError<InstanceError>> {
166 166 self.request::<TokenExtensionRequest>(
167 167 TokenExtensionRequest {
@@ -179,7 +179,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
179 179 visibility: &RepositoryVisibility,
180 180 default_branch: &str,
181 181 owner: &User,
182 operation_state: &S,
182 operation_state: &OperationState,
183 183 ) -> Result<Repository, OperationError<InstanceError>> {
184 184 self.request::<RepositoryCreateRequest>(
185 185 RepositoryCreateRequest {

giterated-models/src/lib.rs

View file
@@ -1,6 +1,7 @@
1 1 pub mod authenticated;
2 2 pub mod discovery;
3 3 pub mod error;
4 pub mod ffi;
4 5 pub mod handshake;
5 6 pub mod instance;
6 7 pub mod message;

giterated-models/src/object.rs

View file
@@ -1,6 +1,5 @@
1 1 use std::{
2 2 fmt::{Debug, Display},
3 marker::PhantomData,
4 3 str::FromStr,
5 4 };
6 5
@@ -9,7 +8,7 @@ use anyhow::Error;
9 8 use crate::{
10 9 error::{GetValueError, OperationError},
11 10 object_backend::ObjectBackend,
12 operation::GiteratedOperation,
11 operation::{GiteratedOperation, OperationState},
13 12 settings::{GetSetting, GetSettingError, SetSetting, SetSettingError, Setting},
14 13 value::{GetValue, GiteratedObjectValue},
15 14 };
@@ -18,38 +17,26 @@ mod operations;
18 17 pub use operations::*;
19 18
20 19 #[derive(Debug, Clone)]
21 pub struct Object<
22 'b,
23 S: Clone + Send + Sync,
24 O: GiteratedObject,
25 B: ObjectBackend<S> + 'b + Send + Clone,
26 > {
20 pub struct Object<O: GiteratedObject, B: ObjectBackend + Send + Clone> {
27 21 pub(crate) inner: O,
28 22 pub(crate) backend: B,
29 pub(crate) _marker: PhantomData<&'b S>,
30 23 }
31 24
32 impl<'b, S: Clone + Send + Sync, B: ObjectBackend<S> + Send + Sync + Clone, O: GiteratedObject>
33 Object<'b, S, O, B>
34 {
25 impl<B: ObjectBackend + Send + Sync + Clone, O: GiteratedObject> Object<O, B> {
35 26 pub fn object(&self) -> &O {
36 27 &self.inner
37 28 }
38 29
39 pub unsafe fn new_unchecked(object: O, backend: B) -> Object<'b, S, O, B> {
30 pub unsafe fn new_unchecked(object: O, backend: B) -> Object<O, B> {
40 31 Object {
41 32 inner: object,
42 33 backend,
43 _marker: PhantomData,
44 34 }
45 35 }
46 36 }
47 37
48 impl<
49 S: Clone + Send + Sync,
50 O: GiteratedObject + Display,
51 B: ObjectBackend<S> + Send + Sync + Clone,
52 > Display for Object<'_, S, O, B>
38 impl<O: GiteratedObject + Display, B: ObjectBackend + Send + Sync + Clone> Display
39 for Object<O, B>
53 40 {
54 41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 42 self.inner.fmt(f)
@@ -63,16 +50,10 @@ pub trait GiteratedObject: Send + Display + FromStr + Sync + Clone {
63 50 fn from_object_str(object_str: &str) -> Result<Self, Error>;
64 51 }
65 52
66 impl<
67 'b,
68 I: Clone + Send + Sync,
69 O: GiteratedObject + Clone + Debug + 'static,
70 B: ObjectBackend<I>,
71 > Object<'b, I, O, B>
72 {
53 impl<O: GiteratedObject + Clone + Debug + 'static, B: ObjectBackend> Object<O, B> {
73 54 pub async fn get<V: GiteratedObjectValue<Object = O> + Send + Debug + 'static>(
74 55 &mut self,
75 operation_state: &I,
56 operation_state: &OperationState,
76 57 ) -> Result<V, OperationError<GetValueError>> {
77 58 let result = self
78 59 .request(
@@ -88,7 +69,7 @@ impl<
88 69
89 70 pub async fn get_setting<S: Setting + Send + Clone + Debug>(
90 71 &mut self,
91 operation_state: &I,
72 operation_state: &OperationState,
92 73 ) -> Result<S, OperationError<GetSettingError>> {
93 74 self.request(
94 75 GetSetting {
@@ -103,7 +84,7 @@ impl<
103 84 pub async fn set_setting<S: Setting + Send + Clone + Debug>(
104 85 &mut self,
105 86 setting: S,
106 operation_state: &I,
87 operation_state: &OperationState,
107 88 ) -> Result<(), OperationError<SetSettingError>> {
108 89 self.request(
109 90 SetSetting {
@@ -118,7 +99,7 @@ impl<
118 99 pub async fn request<R: GiteratedOperation<O> + Debug + 'static>(
119 100 &mut self,
120 101 request: R,
121 operation_state: &I,
102 operation_state: &OperationState,
122 103 ) -> Result<R::Success, OperationError<R::Failure>>
123 104 where
124 105 R::Success: Clone,

giterated-models/src/object/operations.rs

View file
@@ -9,7 +9,7 @@ use super::GiteratedObject;
9 9 #[derive(Debug, Serialize, Deserialize, Clone)]
10 10 pub struct ObjectRequest(pub String);
11 11
12 #[derive(Serialize, Deserialize, Clone)]
12 #[derive(Serialize, Deserialize, Clone, Debug)]
13 13 pub struct ObjectResponse(pub String);
14 14
15 15 impl GiteratedOperation<Instance> for ObjectRequest {

giterated-models/src/object_backend.rs

View file
@@ -1,19 +1,19 @@
1 1 use crate::{
2 2 error::OperationError,
3 3 object::{GiteratedObject, Object, ObjectRequestError},
4 operation::GiteratedOperation,
4 operation::{GiteratedOperation, OperationState},
5 5 };
6 6
7 7 use std::fmt::Debug;
8 8
9 9 #[async_trait::async_trait(?Send)]
10 pub trait ObjectBackend<S: Clone + Send + Sync>: Sized + Clone + Send {
10 pub trait ObjectBackend: Sized + Clone + Send {
11 11 async fn object_operation<O, D>(
12 12 &self,
13 13 object: O,
14 14 operation: &str,
15 15 payload: D,
16 operation_state: &S,
16 operation_state: &OperationState,
17 17 ) -> Result<D::Success, OperationError<D::Failure>>
18 18 where
19 19 O: GiteratedObject + Debug + 'static,
@@ -24,6 +24,6 @@ pub trait ObjectBackend<S: Clone + Send + Sync>: Sized + Clone + Send {
24 24 async fn get_object<O: GiteratedObject + Debug + 'static>(
25 25 &self,
26 26 object_str: &str,
27 operation_state: &S,
28 ) -> Result<Object<S, O, Self>, OperationError<ObjectRequestError>>;
27 operation_state: &OperationState,
28 ) -> Result<Object<O, Self>, OperationError<ObjectRequestError>>;
29 29 }

giterated-models/src/operation.rs

View file
@@ -1,8 +1,8 @@
1 use std::{any::type_name, fmt::Debug};
1 use std::{any::type_name, collections::HashMap, fmt::Debug};
2 2
3 3 use serde::{de::DeserializeOwned, Deserialize, Serialize};
4 4
5 use crate::object::GiteratedObject;
5 use crate::{ffi::FfiLabel, object::GiteratedObject};
6 6
7 7 pub trait GiteratedOperation<O: GiteratedObject>:
8 8 Send + Sync + Serialize + DeserializeOwned
@@ -26,7 +26,17 @@ impl<O: GiteratedObject> GiteratedOperation<O> for NetworkAnyOperation {
26 26 type Failure = Vec<u8>;
27 27 }
28 28
29 /// The internal state of an operation, used to provide authentication information
30 /// and the ability to make giterated calls within handlers.
31 #[derive(Clone)]
32 pub struct GiteratedOperationState<S: Clone + Send + Sync>(pub S);
29 #[derive(Clone, Debug, Default)]
30 pub struct OperationState {
31 states: HashMap<String, Vec<u8>>,
32 }
33
34 impl FfiLabel for OperationState {
35 fn prefix(&self) -> &'static str {
36 "dev.giterated"
37 }
38
39 fn type_label(&self) -> &'static str {
40 "operation_state"
41 }
42 }

giterated-models/src/repository/operations.rs

View file
@@ -4,7 +4,7 @@ use crate::{
4 4 error::{OperationError, RepositoryError},
5 5 object::Object,
6 6 object_backend::ObjectBackend,
7 operation::GiteratedOperation,
7 operation::{GiteratedOperation, OperationState},
8 8 };
9 9
10 10 use super::{
@@ -271,13 +271,13 @@ impl GiteratedOperation<Repository> for RepositoryBranchesRequest {
271 271 type Failure = RepositoryError;
272 272 }
273 273
274 impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S, Repository, B> {
274 impl<B: ObjectBackend + std::fmt::Debug> Object<Repository, B> {
275 275 pub async fn info(
276 276 &mut self,
277 277 extra_metadata: bool,
278 278 rev: Option<String>,
279 279 path: Option<String>,
280 operation_state: &S,
280 operation_state: &OperationState,
281 281 ) -> Result<RepositoryView, OperationError<RepositoryError>> {
282 282 self.request::<RepositoryInfoRequest>(
283 283 RepositoryInfoRequest {
@@ -293,7 +293,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
293 293 pub async fn file_from_id(
294 294 &mut self,
295 295 id: String,
296 operation_state: &S,
296 operation_state: &OperationState,
297 297 ) -> Result<RepositoryFile, OperationError<RepositoryError>> {
298 298 self.request::<RepositoryFileFromIdRequest>(
299 299 RepositoryFileFromIdRequest(id),
@@ -306,7 +306,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
306 306 &mut self,
307 307 rev: Option<String>,
308 308 path: String,
309 operation_state: &S,
309 operation_state: &OperationState,
310 310 ) -> Result<(RepositoryFile, String), OperationError<RepositoryError>> {
311 311 self.request::<RepositoryFileFromPathRequest>(
312 312 RepositoryFileFromPathRequest { rev, path },
@@ -319,7 +319,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
319 319 &mut self,
320 320 start_commit: String,
321 321 path: String,
322 operation_state: &S,
322 operation_state: &OperationState,
323 323 ) -> Result<Commit, OperationError<RepositoryError>> {
324 324 self.request::<RepositoryLastCommitOfFileRequest>(
325 325 RepositoryLastCommitOfFileRequest { start_commit, path },
@@ -331,7 +331,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
331 331 pub async fn commit_by_id(
332 332 &mut self,
333 333 id: String,
334 operation_state: &S,
334 operation_state: &OperationState,
335 335 ) -> Result<Commit, OperationError<RepositoryError>> {
336 336 self.request::<RepositoryCommitFromIdRequest>(
337 337 RepositoryCommitFromIdRequest(id),
@@ -344,7 +344,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
344 344 &mut self,
345 345 old_id: String,
346 346 new_id: String,
347 operation_state: &S,
347 operation_state: &OperationState,
348 348 ) -> Result<RepositoryDiff, OperationError<RepositoryError>> {
349 349 self.request::<RepositoryDiffRequest>(
350 350 RepositoryDiffRequest { old_id, new_id },
@@ -357,7 +357,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
357 357 &mut self,
358 358 old_id: String,
359 359 new_id: String,
360 operation_state: &S,
360 operation_state: &OperationState,
361 361 ) -> Result<String, OperationError<RepositoryError>> {
362 362 self.request::<RepositoryDiffPatchRequest>(
363 363 RepositoryDiffPatchRequest { old_id, new_id },
@@ -369,7 +369,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
369 369 pub async fn commit_before(
370 370 &mut self,
371 371 id: String,
372 operation_state: &S,
372 operation_state: &OperationState,
373 373 ) -> Result<Commit, OperationError<RepositoryError>> {
374 374 self.request::<RepositoryCommitBeforeRequest>(
375 375 RepositoryCommitBeforeRequest(id),
@@ -381,7 +381,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
381 381 pub async fn statistics(
382 382 &mut self,
383 383 rev: Option<String>,
384 operation_state: &S,
384 operation_state: &OperationState,
385 385 ) -> Result<RepositoryStatistics, OperationError<RepositoryError>> {
386 386 self.request::<RepositoryStatisticsRequest>(
387 387 RepositoryStatisticsRequest { rev },
@@ -392,7 +392,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
392 392
393 393 pub async fn branches(
394 394 &mut self,
395 operation_state: &S,
395 operation_state: &OperationState,
396 396 ) -> Result<Vec<RepositoryBranch>, OperationError<RepositoryError>> {
397 397 self.request::<RepositoryBranchesRequest>(RepositoryBranchesRequest, operation_state)
398 398 .await
@@ -405,7 +405,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
405 405
406 406 pub async fn issue_labels(
407 407 &mut self,
408 operation_state: &S,
408 operation_state: &OperationState,
409 409 ) -> Result<Vec<IssueLabel>, OperationError<RepositoryError>> {
410 410 self.request::<RepositoryIssueLabelsRequest>(RepositoryIssueLabelsRequest, operation_state)
411 411 .await
@@ -413,7 +413,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
413 413
414 414 pub async fn issues(
415 415 &mut self,
416 operation_state: &S,
416 operation_state: &OperationState,
417 417 ) -> Result<Vec<RepositoryIssue>, OperationError<RepositoryError>> {
418 418 self.request::<RepositoryIssuesRequest>(RepositoryIssuesRequest, operation_state)
419 419 .await
@@ -424,7 +424,7 @@ impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S
424 424 extra_metadata: bool,
425 425 rev: Option<&str>,
426 426 path: Option<&str>,
427 operation_state: &S,
427 operation_state: &OperationState,
428 428 ) -> Result<Vec<RepositoryTreeEntry>, OperationError<RepositoryError>> {
429 429 self.request::<RepositoryFileInspectRequest>(
430 430 RepositoryFileInspectRequest {

giterated-models/src/user/mod.rs

View file
@@ -10,7 +10,7 @@ use std::{
10 10 pub use operations::*;
11 11 use secrecy::{CloneableSecret, DebugSecret, SerializableSecret, Zeroize};
12 12 use serde::{Deserialize, Serialize};
13 pub use settings::*;
13
14 14 pub use values::*;
15 15
16 16 use crate::{instance::Instance, object::GiteratedObject};

giterated-models/src/user/operations.rs

View file
@@ -5,7 +5,7 @@ use crate::{
5 5 instance::Instance,
6 6 object::Object,
7 7 object_backend::ObjectBackend,
8 operation::GiteratedOperation,
8 operation::{GiteratedOperation, OperationState},
9 9 repository::RepositorySummary,
10 10 };
11 11
@@ -22,11 +22,11 @@ impl GiteratedOperation<User> for UserRepositoriesRequest {
22 22 type Failure = UserError;
23 23 }
24 24
25 impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S, User, B> {
25 impl<B: ObjectBackend + std::fmt::Debug> Object<User, B> {
26 26 pub async fn repositories(
27 27 &mut self,
28 28 instance: &Instance,
29 operation_state: &S,
29 operation_state: &OperationState,
30 30 ) -> Result<Vec<RepositorySummary>, OperationError<UserError>> {
31 31 self.request::<UserRepositoriesRequest>(
32 32 UserRepositoriesRequest {

giterated-plugin/Cargo.toml

View file
@@ -11,7 +11,10 @@ anyhow = "1"
11 11 thiserror = "1"
12 12 tracing = "0.1"
13 13 giterated-models = { path = "../giterated-models" }
14 giterated-static-runtime = { path = "giterated-static-runtime" }
14 15 semver = "*"
15 16 serde_json = "1.0"
16 17 async-trait = "0.1"
17 serde = "*"
17 \ No newline at end of file
18 serde = "*"
19 futures-util = "0.3.30"
20 tokio = { version = "1.32", features = [ "full" ] }

giterated-plugin/giterated-plugin-sys/src/lib.rs

View file
@@ -1,7 +1,5 @@
1 1 mod local_runtime;
2 2
3 use std::marker::PhantomData;
4
5 3 use giterated_models::{
6 4 object::GiteratedObject, operation::GiteratedOperation, settings::Setting,
7 5 value::GiteratedObjectValue,
@@ -9,7 +7,8 @@ use giterated_models::{
9 7 use giterated_plugin::{
10 8 callback::{
11 9 CallbackPtr, IntoPluginOperationHandler, IntoPluginSettingGetter, IntoPluginSettingSetter,
12 IntoPluginValueGetter, OperationHandlerCallback, ValueGetterCallback,
10 IntoPluginValueGetter, OperationHandlerCallback, SettingGetterCallback,
11 ValueGetterCallback,
13 12 },
14 13 handle::PluginInitializationState,
15 14 new_stack::PluginState,
@@ -190,28 +189,36 @@ impl<'init, S> PluginStackBuilder<'init, S> {
190 189 // self
191 190 // }
192 191
193 // pub fn setting_getter<O, OS, T>(&mut self, handler: T) -> &mut Self
194 // where
195 // O: GiteratedObject + IntoObjectVTable,
196 // OS: Setting + IntoSettingVTable,
197 // T: IntoPluginSettingGetter<S, O, OS>,
198 // {
199 // let _guard = trace_span!("register setting_getter handler").entered();
192 pub fn setting_getter<O, OS, T>(&mut self, handler: T) -> &mut Self
193 where
194 O: GiteratedObject + IntoObjectVTable,
195 OS: Setting + IntoSettingVTable,
196 T: IntoPluginSettingGetter<S, O, OS>,
197 {
198 let _guard = trace_span!("register setting_getter handler").entered();
200 199
201 // unsafe {
202 // (self.vtable.setting_getter)(
203 // self.init_state,
204 // O::object_name(),
205 // OS::name(),
206 // SettingGetterCallback::new::<S, O, OS, T>(handler),
207 // )
208 // }
200 unsafe {
201 (self.vtable.setting_getter)(
202 self.init_state,
203 O::object_name(),
204 OS::name(),
205 SettingGetterCallback::new::<S, O, OS, T>(handler),
206 )
207 }
209 208
210 // self.object::<O>();
211 // // self.setting::<O, OS>();
209 self.object::<O>();
212 210
213 // self
214 // }
211 unsafe {
212 (self.vtable.register_setting)(
213 self.init_state,
214 O::object_name(),
215 OS::name(),
216 SettingVtable::new::<OS>(),
217 )
218 };
219
220 self
221 }
215 222 }
216 223
217 224 pub trait ValueSettingExt<PS> {
@@ -252,15 +259,17 @@ where
252 259 HG: IntoPluginSettingGetter<S, O, VS>,
253 260 {
254 261 unsafe extern "C" fn get_value(
255 callback: CallbackPtr,
256 state: &PluginState,
257 object: AnyObject,
262 _callback: CallbackPtr,
263 _state: &PluginState,
264 _object: AnyObject,
258 265 ) -> Result<NewAnyValue, ()> {
259 let result = HG::get_setting(callback, state, object)?;
266 // let result = HG::get_setting(callback, state, object)?;
267
268 // let setting = *result.transmute_owned::<VS>();
260 269
261 let setting = *result.transmute_owned::<VS>();
270 todo!();
262 271
263 Ok(NewAnyValue::new(setting))
272 // Ok(NewAnyValue::new(setting))
264 273 }
265 274
266 275 fn callback_ptr(&self) -> CallbackPtr {

giterated-plugin/giterated-static-runtime/Cargo.toml

View file
@@ -0,0 +1,8 @@
1 [package]
2 name = "giterated-static-runtime"
3 version = "0.1.0"
4 edition = "2021"
5
6 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
8 [dependencies]

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

View file
@@ -0,0 +1,16 @@
1 use std::{mem::MaybeUninit, ptr::NonNull};
2
3 struct RuntimePointer(NonNull<()>);
4
5 unsafe impl Send for RuntimePointer {}
6 unsafe impl Sync for RuntimePointer {}
7
8 static mut GITERATED_RUNTIME: MaybeUninit<RuntimePointer> = MaybeUninit::zeroed();
9
10 pub unsafe fn initialize_runtime(runtime_pointer: *mut ()) {
11 GITERATED_RUNTIME.write(RuntimePointer(NonNull::new(runtime_pointer).unwrap()));
12 }
13
14 pub unsafe fn get_runtime_reference() -> NonNull<()> {
15 GITERATED_RUNTIME.assume_init_read().0
16 }

giterated-plugin/src/callback/mod.rs

View file
@@ -1,5 +1,12 @@
1 1 mod operation;
2 use std::sync::Arc;
2
3 use giterated_models::{
4 error::OperationError,
5 object::{GiteratedObject, Object, ObjectRequestError},
6 object_backend::ObjectBackend,
7 operation::{GiteratedOperation, OperationState},
8 };
9 use std::fmt::Debug;
3 10
4 11 pub use operation::*;
5 12 mod value;
@@ -7,10 +14,7 @@ pub use value::*;
7 14 mod setting;
8 15 pub use setting::*;
9 16
10 use crate::{
11 new_stack::{PluginState, Runtime},
12 vtable::RuntimeVTable,
13 };
17 use crate::{vtable::RuntimeVTable, AnyObject, AnyOperation};
14 18
15 19 /// A container for a callback pointer, used to provide an internal callback function or
16 20 /// state to a plugin when performing a callback.
@@ -24,8 +28,49 @@ impl CallbackPtr {
24 28 }
25 29 }
26 30
31 #[derive(Clone)]
27 32 #[repr(C)]
28 33 pub struct RuntimeState {
29 34 pub vtable: RuntimeVTable,
30 pub operation_state: PluginState,
35 pub operation_state: OperationState,
36 }
37
38 impl RuntimeState {
39 pub unsafe fn from_static() -> Self {
40 let runtime = giterated_static_runtime::get_runtime_reference();
41
42 let runtime = runtime.cast::<Box<RuntimeState>>().as_ref();
43
44 *runtime.clone()
45 }
46 }
47
48 #[async_trait::async_trait(?Send)]
49 impl ObjectBackend for RuntimeState {
50 async fn object_operation<O, D>(
51 &self,
52 object: O,
53 _operation: &str,
54 payload: D,
55 _operation_state: &OperationState,
56 ) -> Result<D::Success, OperationError<D::Failure>>
57 where
58 O: GiteratedObject + Debug + 'static,
59 D: GiteratedOperation<O> + Debug + 'static,
60 D::Success: Clone,
61 D::Failure: Clone,
62 {
63 let _object = AnyObject::new(object);
64 let _operation = AnyOperation::new(payload);
65
66 todo!()
67 }
68
69 async fn get_object<O: GiteratedObject + Debug + 'static>(
70 &self,
71 _object_str: &str,
72 _operation_state: &OperationState,
73 ) -> Result<Object<O, Self>, OperationError<ObjectRequestError>> {
74 todo!()
75 }
31 76 }

giterated-plugin/src/callback/operation.rs

View file
@@ -1,14 +1,17 @@
1 1 use giterated_models::{
2 error::OperationError, object::GiteratedObject, operation::GiteratedOperation,
3 value::GiteratedObjectValue,
2 error::OperationError,
3 object::GiteratedObject,
4 operation::{GiteratedOperation, OperationState},
4 5 };
5 6
6 7 use crate::{
7 new_stack::{handle::RuntimeHandle, OperationState, PluginState, Runtime, State},
8 AnyObject, AnyOperation,
8 future::{RuntimeFuture, RuntimeFuturesExt},
9 new_stack::{handle::RuntimeHandle, PluginState},
10 vtable::OperationVTable,
11 AnyFailure, AnyObject, AnyOperation, AnySuccess, FFIBox,
9 12 };
10 13
11 use std::{any::type_name, fmt::Debug, future::Future, sync::Arc};
14 use std::{any::type_name, fmt::Debug, future::Future};
12 15
13 16 use super::{CallbackPtr, RuntimeState};
14 17
@@ -21,7 +24,8 @@ pub struct OperationHandlerCallback {
21 24 &PluginState,
22 25 object: AnyObject,
23 26 operation: AnyOperation,
24 ),
27 )
28 -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>>,
25 29 }
26 30
27 31 impl OperationHandlerCallback {
@@ -48,17 +52,17 @@ pub trait IntoPluginOperationHandler<S, O: GiteratedObject, D: GiteratedOperatio
48 52 state: &PluginState,
49 53 object: AnyObject,
50 54 operation: AnyOperation,
51 );
55 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>>;
52 56 fn callback_ptr(&self) -> CallbackPtr;
53 57 }
54 58
55 59 impl<F, S, O, D, Fut> IntoPluginOperationHandler<S, O, D, ()> for F
56 60 where
57 Fut: Future<Output = Result<D::Success, OperationError<D::Failure>>>,
58 F: Fn(S, O, D) -> Fut,
59 S: Clone + Debug,
60 O: Debug + GiteratedObject,
61 D: Debug + GiteratedOperation<O>,
61 Fut: Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send + Sync,
62 F: Fn(S, O, D) -> Fut + Send + Sync + 'static,
63 S: Clone + Debug + Send + Sync + 'static,
64 O: Debug + GiteratedObject + 'static,
65 D: Debug + GiteratedOperation<O> + 'static,
62 66 {
63 67 unsafe extern "C" fn handle(
64 68 callback: CallbackPtr,
@@ -66,7 +70,7 @@ where
66 70 state: &PluginState,
67 71 mut object: AnyObject,
68 72 mut operation: AnyOperation,
69 ) {
73 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
70 74 let _guard = trace_span!(
71 75 "operation handler",
72 76 object = type_name::<O>(),
@@ -83,9 +87,24 @@ where
83 87 let callback: *const F = std::mem::transmute(callback.0);
84 88 let callback = callback.as_ref().unwrap();
85 89
86 // callback(state.clone(), *object, *operation)
87
88 todo!()
90 let state = state.clone();
91 runtime_state.spawn_future(async move {
92 let result = callback(state, *object, *operation).await;
93
94 match result {
95 Ok(success) => unsafe {
96 Ok(AnySuccess::from_raw(
97 FFIBox::from_box(Box::new(success)).untyped(),
98 OperationVTable::new::<O, D>(),
99 ))
100 },
101 Err(err) => match err {
102 OperationError::Operation(_) => todo!(),
103 OperationError::Internal(_) => todo!(),
104 OperationError::Unhandled => todo!(),
105 },
106 }
107 })
89 108 }
90 109
91 110 fn callback_ptr(&self) -> CallbackPtr {
@@ -102,12 +121,12 @@ where
102 121 D: Debug + GiteratedOperation<O>,
103 122 {
104 123 unsafe extern "C" fn handle(
105 callback_ptr: CallbackPtr,
106 runtime_state: &RuntimeState,
107 state: &PluginState,
108 object: AnyObject,
109 operation: AnyOperation,
110 ) {
124 _callback_ptr: CallbackPtr,
125 _runtime_state: &RuntimeState,
126 _state: &PluginState,
127 _object: AnyObject,
128 _operation: AnyOperation,
129 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
111 130 todo!()
112 131 }
113 132
@@ -125,12 +144,12 @@ where
125 144 D: Debug + GiteratedOperation<O>,
126 145 {
127 146 unsafe extern "C" fn handle(
128 callback_ptr: CallbackPtr,
129 runtime_state: &RuntimeState,
130 state: &PluginState,
131 object: AnyObject,
132 operation: AnyOperation,
133 ) {
147 _callback_ptr: CallbackPtr,
148 _runtime_state: &RuntimeState,
149 _state: &PluginState,
150 _object: AnyObject,
151 _operation: AnyOperation,
152 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
134 153 todo!()
135 154 }
136 155
@@ -150,10 +169,10 @@ pub trait FromOperationState<O, D>: Sized {
150 169
151 170 impl<O, D> FromOperationState<O, D> for RuntimeHandle {
152 171 fn from_operation_state(
153 operation_state: &OperationState,
172 _operation_state: &OperationState,
154 173 runtime_state: &RuntimeState,
155 object: &O,
156 operation: &D,
174 _object: &O,
175 _operation: &D,
157 176 ) -> Result<Self, OperationError<anyhow::Error>> {
158 177 Ok(unsafe { RuntimeHandle::from_vtable(runtime_state.vtable) })
159 178 }
@@ -172,14 +191,3 @@ where
172 191 Ok(T::from_operation_state(operation_state, runtime_state, object, operation).ok())
173 192 }
174 193 }
175
176 impl<O, D, OS: Clone> FromOperationState<O, D> for State<OS> {
177 fn from_operation_state(
178 operation_state: &OperationState,
179 runtime_state: &RuntimeState,
180 object: &O,
181 operation: &D,
182 ) -> Result<Self, OperationError<anyhow::Error>> {
183 Ok(unsafe { State(runtime_state.operation_state.transmute_ref::<OS>().clone()) })
184 }
185 }

giterated-plugin/src/callback/setting.rs

View file
@@ -6,18 +6,23 @@ use giterated_models::{
6 6 settings::{AnySetting, Setting},
7 7 };
8 8
9 use crate::{new_stack::PluginState, AnyObject, NewAnySetting};
9 use crate::{
10 future::{RuntimeFuture, RuntimeFuturesExt},
11 new_stack::PluginState,
12 AnyObject, NewAnySetting,
13 };
10 14
11 use super::CallbackPtr;
15 use super::{CallbackPtr, RuntimeState};
12 16
13 17 #[derive(Clone, Copy)]
14 18 pub struct SettingGetterCallback {
15 19 pub callback_ptr: CallbackPtr,
16 20 pub func: unsafe extern "C" fn(
17 21 CallbackPtr,
22 runtime_state: &RuntimeState,
18 23 &PluginState,
19 24 object: AnyObject,
20 ) -> Result<NewAnySetting, ()>,
25 ) -> RuntimeFuture<Result<NewAnySetting, ()>>,
21 26 }
22 27
23 28 impl SettingGetterCallback {
@@ -32,9 +37,10 @@ impl SettingGetterCallback {
32 37 pub trait IntoPluginSettingGetter<S, O, OS> {
33 38 unsafe extern "C" fn get_setting(
34 39 callback_ptr: CallbackPtr,
40 runtime_state: &RuntimeState,
35 41 state: &PluginState,
36 42 object: AnyObject,
37 ) -> Result<NewAnySetting, ()>;
43 ) -> RuntimeFuture<Result<NewAnySetting, ()>>;
38 44
39 45 fn callback_ptr(&self) -> CallbackPtr {
40 46 unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) }
@@ -43,17 +49,18 @@ pub trait IntoPluginSettingGetter<S, O, OS> {
43 49
44 50 impl<F, S, O, OS, Fut> IntoPluginSettingGetter<S, O, OS> for F
45 51 where
46 Fut: Future<Output = Result<OS, OperationError<anyhow::Error>>>,
47 S: Clone,
48 O: GiteratedObject,
49 OS: Setting,
50 F: Fn(S, O) -> Fut,
52 Fut: Future<Output = Result<OS, OperationError<anyhow::Error>>> + Send + Sync + 'static,
53 S: Clone + Send + Sync + 'static,
54 O: GiteratedObject + Send + Sync + 'static,
55 OS: Setting + Send + Sync + 'static,
56 F: Fn(S, O) -> Fut + Send + Sync + 'static,
51 57 {
52 58 unsafe extern "C" fn get_setting(
53 59 callback: CallbackPtr,
60 runtime_state: &RuntimeState,
54 61 state: &PluginState,
55 62 mut object: AnyObject,
56 ) -> Result<NewAnySetting, ()> {
63 ) -> RuntimeFuture<Result<NewAnySetting, ()>> {
57 64 let _guard = trace_span!(
58 65 "get_setting handler",
59 66 object = O::object_name(),
@@ -68,14 +75,19 @@ where
68 75 let callback: *const F = std::mem::transmute(callback.0);
69 76 let callback = callback.as_ref().unwrap();
70 77
71 // let result = callback(state.clone(), *object);
72
73 // match result {
74 // Ok(setting) => Ok(NewAnySetting::new(setting)),
75 // Err(_) => todo!(),
76 // }
77
78 todo!()
78 let state = state.clone();
79 runtime_state.spawn_future(async move {
80 let result = callback(state, *object).await;
81
82 match result {
83 Ok(success) => unsafe { Ok(NewAnySetting::new(success)) },
84 Err(err) => match err {
85 OperationError::Operation(_) => todo!(),
86 OperationError::Internal(_) => todo!(),
87 OperationError::Unhandled => todo!(),
88 },
89 }
90 })
79 91 }
80 92 }
81 93
@@ -85,7 +97,7 @@ pub trait IntoPluginSettingSetter<S, O, OS> {
85 97 state: &PluginState,
86 98 object: AnyObject,
87 99 setting: AnySetting,
88 ) -> Result<(), ()>;
100 ) -> RuntimeFuture<Result<(), ()>>;
89 101
90 102 fn callback_ptr(&self) -> CallbackPtr {
91 103 unsafe { CallbackPtr::from_raw(self as *const _ as *const ()) }
@@ -104,21 +116,21 @@ where
104 116 callback: CallbackPtr,
105 117 state: &PluginState,
106 118 mut object: AnyObject,
107 setting: AnySetting,
108 ) -> Result<(), ()> {
119 _setting: AnySetting,
120 ) -> RuntimeFuture<Result<(), ()>> {
109 121 let _guard = trace_span!(
110 122 "get_setting handler",
111 123 object = O::object_name(),
112 124 setting = OS::name()
113 125 )
114 126 .entered();
115 let state = unsafe { state.transmute_ref::<S>() };
127 let _state = unsafe { state.transmute_ref::<S>() };
116 128
117 let object = unsafe { object.transmute_owned::<O>() };
129 let _object = unsafe { object.transmute_owned::<O>() };
118 130
119 131 // Cast the callback ptr to ourselves
120 132 let callback: *const F = std::mem::transmute(callback.0);
121 let callback = callback.as_ref().unwrap();
133 let _callback = callback.as_ref().unwrap();
122 134
123 135 // let result = callback(state.clone(), *object);
124 136
@@ -150,10 +162,10 @@ pub trait IntoSettingChangeCallback<S, O> {
150 162
151 163 impl<F, S, O> IntoSettingChangeCallback<S, O> for F {
152 164 unsafe extern "C" fn setting_changed(
153 state: &PluginState,
154 object: AnyObject,
155 setting_name: &str,
156 new_setting: NewAnySetting,
165 _state: &PluginState,
166 _object: AnyObject,
167 _setting_name: &str,
168 _new_setting: NewAnySetting,
157 169 ) {
158 170 todo!()
159 171 }

giterated-plugin/src/callback/value.rs

View file
@@ -1,24 +1,26 @@
1 1 use std::future::Future;
2 2
3 3 use giterated_models::{
4 error::OperationError, object::GiteratedObject, settings::Setting, value::GiteratedObjectValue,
4 error::OperationError, object::GiteratedObject, value::GiteratedObjectValue,
5 5 };
6 6
7 7 use crate::{
8 future::{RuntimeFuture, RuntimeFuturesExt},
8 9 new_stack::PluginState,
9 10 vtable::{AnyObject, NewAnyValue},
10 11 };
11 12
12 use super::CallbackPtr;
13 use super::{CallbackPtr, RuntimeState};
13 14
14 15 #[derive(Copy, Clone)]
15 16 pub struct ValueGetterCallback {
16 17 pub callback_ptr: CallbackPtr,
17 18 pub func: unsafe extern "C" fn(
18 19 CallbackPtr,
20 runtime_state: &RuntimeState,
19 21 &PluginState,
20 22 object: AnyObject,
21 ) -> Result<NewAnyValue, ()>,
23 ) -> RuntimeFuture<Result<NewAnyValue, ()>>,
22 24 }
23 25
24 26 impl ValueGetterCallback {
@@ -33,26 +35,28 @@ impl ValueGetterCallback {
33 35 pub trait IntoPluginValueGetter<S, O, V> {
34 36 unsafe extern "C" fn get_value(
35 37 callback: CallbackPtr,
38 runtime_state: &RuntimeState,
36 39 state: &PluginState,
37 40 object: AnyObject,
38 ) -> Result<NewAnyValue, ()>;
41 ) -> RuntimeFuture<Result<NewAnyValue, ()>>;
39 42
40 43 fn callback_ptr(&self) -> CallbackPtr;
41 44 }
42 45
43 46 impl<F, S, O, V, Fut> IntoPluginValueGetter<S, O, V> for F
44 47 where
45 Fut: Future<Output = Result<V, OperationError<anyhow::Error>>>,
46 S: Clone,
47 O: GiteratedObject,
48 V: GiteratedObjectValue<Object = O>,
49 F: Fn(S, O) -> Fut,
48 Fut: Future<Output = Result<V, OperationError<anyhow::Error>>> + Send + Sync,
49 S: Clone + Send + Sync + 'static,
50 O: GiteratedObject + 'static,
51 V: GiteratedObjectValue<Object = O> + Send + Sync + 'static,
52 F: Fn(S, O) -> Fut + Send + Sync + 'static,
50 53 {
51 54 unsafe extern "C" fn get_value(
52 55 callback: CallbackPtr,
56 runtime_state: &RuntimeState,
53 57 state: &PluginState,
54 58 mut object: AnyObject,
55 ) -> Result<NewAnyValue, ()> {
59 ) -> RuntimeFuture<Result<NewAnyValue, ()>> {
56 60 let _guard = trace_span!(
57 61 "get_value handler",
58 62 object = O::object_name(),
@@ -67,14 +71,19 @@ where
67 71 let callback: *const F = std::mem::transmute(callback.0);
68 72 let callback = callback.as_ref().unwrap();
69 73
70 let result = callback(state.clone(), *object);
71
72 // match result {
73 // Ok(value) => Ok(NewAnyValue::new(value)),
74 // Err(_) => todo!(),
75 // }
76
77 todo!()
74 let state = state.clone();
75 runtime_state.spawn_future(async move {
76 let result = callback(state, *object).await;
77
78 match result {
79 Ok(success) => unsafe { Ok(NewAnyValue::new(success)) },
80 Err(err) => match err {
81 OperationError::Operation(_) => todo!(),
82 OperationError::Internal(_) => todo!(),
83 OperationError::Unhandled => todo!(),
84 },
85 }
86 })
78 87 }
79 88
80 89 fn callback_ptr(&self) -> CallbackPtr {
@@ -88,7 +97,7 @@ pub struct ValueChangeCallback {
88 97 object: AnyObject,
89 98 value_name: &str,
90 99 new_value: NewAnyValue,
91 ),
100 ) -> RuntimeFuture<()>,
92 101 }
93 102
94 103 pub trait IntoValueChangeCallback<S, O> {
@@ -97,16 +106,16 @@ pub trait IntoValueChangeCallback<S, O> {
97 106 object: AnyObject,
98 107 value_name: &str,
99 108 new_value: NewAnyValue,
100 );
109 ) -> RuntimeFuture<()>;
101 110 }
102 111
103 112 impl<F, S, O> IntoValueChangeCallback<S, O> for F {
104 113 unsafe extern "C" fn value_changed(
105 state: &PluginState,
106 object: AnyObject,
107 value_name: &str,
108 new_value: NewAnyValue,
109 ) {
114 _state: &PluginState,
115 _object: AnyObject,
116 _value_name: &str,
117 _new_value: NewAnyValue,
118 ) -> RuntimeFuture<()> {
110 119 todo!()
111 120 }
112 121 }

giterated-plugin/src/future.rs

View file
@@ -0,0 +1,203 @@
1 use futures_util::future::BoxFuture;
2 use futures_util::FutureExt;
3 use std::{
4 cell::UnsafeCell,
5 future::Future,
6 marker::PhantomData,
7 task::{Context, RawWaker, RawWakerVTable, Waker},
8 };
9
10 use crate::{callback::RuntimeState, new_stack::PluginState, FFIBox};
11
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 #[repr(C)]
39 pub struct RuntimeWakerCallback {
40 callback: PluginState,
41 waker_func: unsafe extern "C" fn(PluginState),
42 }
43
44 #[repr(C)]
45 pub enum RuntimeFuturePoll {
46 Ready(FFIBox<()>),
47 Pending,
48 }
49
50 pub struct WakerState {
51 waker: Waker,
52 }
53
54 impl<Output> RuntimeFuture<Output> {
55 pub(crate) unsafe fn poll(&mut self) -> RuntimeFuturePoll {
56 todo!()
57 }
58 }
59
60 unsafe extern "C" fn wake(_waker: PluginState) {}
61
62 pub struct LocalRuntimeFuture<Output> {
63 inner: BoxFuture<'static, Output>,
64 runtime_future: UnsafeCell<RuntimeFuture<Output>>,
65 }
66
67 unsafe impl<Output> Send for LocalRuntimeFuture<Output> where Output: Send {}
68 unsafe impl<Output> Sync for LocalRuntimeFuture<Output> where Output: Sync {}
69
70 impl<Output> LocalRuntimeFuture<Output> {
71 pub fn finalize(self) {}
72
73 pub fn into_runtime(&self) -> RuntimeFuture<Output> {
74 todo!()
75 }
76 }
77
78 pub trait RuntimeFuturesExt {
79 fn spawn_future<Output, F: Future<Output = Output> + Send + Sync + 'static>(
80 &self,
81 future: F,
82 ) -> RuntimeFuture<Output>;
83 }
84
85 impl RuntimeFuturesExt for RuntimeState {
86 fn spawn_future<Output, F: Future<Output = Output> + Send + Sync + 'static>(
87 &self,
88 future: F,
89 ) -> RuntimeFuture<Output> {
90 let type_eraser = async move {
91 let result = future.await;
92
93 FFIBox::from_box(Box::new(result)).untyped()
94 };
95
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 };
104
105 runtime_future
106 }
107 }
108
109 unsafe extern "C" fn poll_local(
110 _future: *const RuntimeFuture<()>,
111 mut future_state: PluginState,
112 ) -> RuntimeFuturePoll {
113 let mut future: Box<BoxFuture<'static, FFIBox<()>>> = future_state.transmute_owned();
114 let runtime_future = future.as_ref();
115
116 let raw_waker = RawWaker::new(
117 Box::into_raw(Box::new(runtime_future)) as *const (),
118 &RUNTIME_FUTURE_WAKER_VTABLE,
119 );
120
121 let waker = unsafe { Waker::from_raw(raw_waker) };
122
123 // 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 }
131
132 match poll_result {
133 std::task::Poll::Ready(result) => RuntimeFuturePoll::Ready(result),
134 std::task::Poll::Pending => RuntimeFuturePoll::Pending,
135 }
136 }
137
138 pub static RUNTIME_FUTURE_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
139 runtime_waker_vtable::waker_clone,
140 runtime_waker_vtable::waker_wake,
141 runtime_waker_vtable::waker_wake_by_ref,
142 runtime_waker_vtable::waker_drop,
143 );
144
145 mod runtime_waker_vtable {
146 use std::task::RawWaker;
147
148 pub unsafe fn waker_clone(_data: *const ()) -> RawWaker {
149 todo!()
150 }
151
152 pub unsafe fn waker_wake(_data: *const ()) {
153 todo!()
154 }
155
156 pub unsafe fn waker_wake_by_ref(_data: *const ()) {
157 todo!()
158 }
159
160 pub unsafe fn waker_drop(_data: *const ()) {
161 // no-op
162 }
163 }
164
165 /// Allows for a remote future to be polled on the target.
166 ///
167 /// The target can be the host or a plugin, but the future should only be polled by one
168 /// source.
169 impl<Output: Unpin> Future for RuntimeFuture<Output> {
170 type Output = Output;
171
172 fn poll(
173 mut self: std::pin::Pin<&mut Self>,
174 cx: &mut Context<'_>,
175 ) -> std::task::Poll<Self::Output> {
176 let waker_state = WakerState {
177 waker: cx.waker().clone(),
178 };
179
180 let waker_state = PluginState::from(waker_state);
181
182 self.waker_state = Some(waker_state);
183 self.wake_fn = Some(wake_local);
184
185 match unsafe {
186 (self.poll_fn)(
187 &*self as *const RuntimeFuture<_> as *const RuntimeFuture<()>,
188 self.poll_state,
189 )
190 } {
191 RuntimeFuturePoll::Ready(result) => {
192 let result: Output = unsafe { *result.retype::<Output>().into_box() };
193
194 std::task::Poll::Ready(result)
195 }
196 RuntimeFuturePoll::Pending => std::task::Poll::Pending,
197 }
198 }
199 }
200
201 unsafe extern "C" fn wake_local(_future: *const RuntimeFuture<()>, _waker_state: PluginState) {
202 todo!()
203 }

giterated-plugin/src/handle.rs

View file
@@ -1,4 +1,4 @@
1 use std::{collections::HashMap, marker::PhantomData, path::Path, sync::Arc};
1 use std::{collections::HashMap, marker::PhantomData, sync::Arc};
2 2
3 3 use anyhow::Error;
4 4 use dlopen2::wrapper::Container;
@@ -6,10 +6,12 @@ use semver::Version;
6 6 use tracing::{debug, trace};
7 7
8 8 use crate::{
9 callback::{OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback},
9 callback::{
10 OperationHandlerCallback, RuntimeState, SettingGetterCallback, ValueGetterCallback,
11 },
10 12 new_stack::{
11 13 ObjectOperationPair, ObjectSettingPair, ObjectValuePair, PluginMeta, PluginState,
12 RuntimeHandlers, TypeMetadata,
14 TypeMetadata,
13 15 },
14 16 vtable::{InitializationVTable, ObjectVtable, OperationVTable, SettingVtable, ValueVTable},
15 17 GiteratedPluginApi,
@@ -31,7 +33,8 @@ impl PluginHandle {
31 33 let mut handle = unsafe { Container::load(path) }?;
32 34
33 35 // Initialize the raw handle
34 let init_state = Self::initialize_raw_handle(&mut handle)?;
36 let init_state =
37 Self::initialize_raw_handle(&mut handle, &unsafe { RuntimeState::from_static() })?;
35 38
36 39 let metadata = Self::get_meta(&mut handle)?;
37 40
@@ -94,10 +97,11 @@ impl PluginHandle {
94 97
95 98 fn initialize_raw_handle(
96 99 handle: &mut Container<GiteratedPluginApi>,
100 runtime_state: &RuntimeState,
97 101 ) -> Result<PluginState, CreationError> {
98 102 debug!("Initializing plugin handle...");
99 103
100 let state = unsafe { handle.initialize() };
104 let state = unsafe { handle.initialize(runtime_state) };
101 105
102 106 debug!("Plugin handle initialized!");
103 107

giterated-plugin/src/lib.rs

View file
@@ -1,4 +1,7 @@
1 #![allow(improper_ctypes_definitions)]
2
1 3 pub mod callback;
4 pub mod future;
2 5 pub mod handle;
3 6 pub mod new_stack;
4 7 pub mod vtable;
@@ -6,14 +9,9 @@ pub mod vtable;
6 9 #[macro_use]
7 10 extern crate tracing;
8 11
9 use std::{any::Any, fmt::Debug, mem::transmute, ptr::null_mut, sync::Arc};
10
11 use callback::{OperationHandlerCallback, SettingGetterCallback, ValueGetterCallback};
12 use callback::RuntimeState;
12 13 use dlopen2::wrapper::WrapperApi;
13 use giterated_models::{
14 object::GiteratedObject, operation::GiteratedOperation, settings::Setting,
15 value::GiteratedObjectValue,
16 };
14
17 15 use handle::PluginInitializationState;
18 16 use new_stack::{FFIPluginMeta, PluginState};
19 17
@@ -25,7 +23,7 @@ pub struct GiteratedPluginApi {
25 23 plugin_meta: unsafe extern "C" fn() -> FFIPluginMeta,
26 24 load_host_vtable: unsafe extern "C" fn(vtable: &HostVTable),
27 25 load_initialization_vtable: unsafe extern "C" fn(vtable: &InitializationVTable),
28 initialize: unsafe extern "C" fn() -> PluginState,
26 initialize: unsafe extern "C" fn(runtime_state: *const RuntimeState) -> PluginState,
29 27 initialize_registration: unsafe extern "C" fn(
30 28 init_state: *mut PluginInitializationState,
31 29 ) -> *mut PluginInitializationState,
@@ -42,11 +40,29 @@ impl<T: ?Sized> FFIBox<T> {
42 40 pub fn untyped(self) -> FFIBox<()> {
43 41 FFIBox(self.0 as *mut ())
44 42 }
43
44 pub unsafe fn retype<N>(self) -> FFIBox<N> {
45 FFIBox(self.0 as *mut N)
46 }
47
48 pub unsafe fn into_box(self) -> Box<T> {
49 Box::from_raw(self.0)
50 }
51
52 pub unsafe fn transmute_ref<N>(&self) -> &N {
53 unsafe { (self.0 as *const N).as_ref() }.unwrap()
54 }
55 }
56
57 impl ToString for FFIBox<str> {
58 fn to_string(&self) -> String {
59 todo!()
60 }
45 61 }
46 62
47 63 impl<T: ?Sized> AsRef<T> for FFIBox<T> {
48 64 fn as_ref(&self) -> &T {
49 todo!()
65 unsafe { self.0.as_ref() }.unwrap()
50 66 }
51 67 }
52 68

giterated-plugin/src/new_stack/handle.rs

View file
@@ -1,5 +1,3 @@
1 use std::marker::PhantomData;
2
3 1 use giterated_models::{
4 2 error::OperationError,
5 3 object::{GiteratedObject, Object, ObjectRequestError},
@@ -20,9 +18,9 @@ pub struct RuntimeHandle {
20 18 impl RuntimeHandle {
21 19 pub async fn handle_serialized(
22 20 &self,
23 object: &str,
24 operation_name: &str,
25 payload: &[u8],
21 _object: &str,
22 _operation_name: &str,
23 _payload: &[u8],
26 24 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
27 25 todo!()
28 26 }
@@ -35,13 +33,13 @@ impl RuntimeHandle {
35 33 }
36 34
37 35 #[async_trait::async_trait(?Send)]
38 impl ObjectBackend<OperationState> for RuntimeHandle {
36 impl ObjectBackend for RuntimeHandle {
39 37 async fn object_operation<O, D>(
40 38 &self,
41 object: O,
42 operation: &str,
43 payload: D,
44 operation_state: &OperationState,
39 _object: O,
40 _operation: &str,
41 _payload: D,
42 _operation_state: &OperationState,
45 43 ) -> Result<D::Success, OperationError<D::Failure>>
46 44 where
47 45 O: GiteratedObject + Debug + 'static,
@@ -54,9 +52,9 @@ impl ObjectBackend<OperationState> for RuntimeHandle {
54 52
55 53 async fn get_object<O: GiteratedObject + Debug + 'static>(
56 54 &self,
57 object_str: &str,
58 operation_state: &OperationState,
59 ) -> Result<Object<OperationState, O, Self>, OperationError<ObjectRequestError>> {
55 _object_str: &str,
56 _operation_state: &OperationState,
57 ) -> Result<Object<O, Self>, OperationError<ObjectRequestError>> {
60 58 todo!()
61 59 }
62 60 }

giterated-plugin/src/new_stack/mod.rs

View file
@@ -2,26 +2,28 @@ pub mod handle;
2 2 pub mod operation_walker;
3 3 pub mod runtime_handler;
4 4
5 use std::{
6 any::type_name, collections::HashMap, fmt::Debug, marker::PhantomData, mem::transmute,
7 ptr::null_mut, sync::Arc,
8 };
5 use std::{collections::HashMap, fmt::Debug, mem::transmute, ptr::null_mut, sync::Arc};
9 6
10 7 use giterated_models::{
11 error::OperationError, instance::Instance, object::GiteratedObject,
12 operation::GiteratedOperation,
8 error::OperationError,
9 object::GiteratedObject,
10 operation::{GiteratedOperation, OperationState},
13 11 };
14 12 use semver::Version;
15 use serde::Serialize;
16 use tracing::{debug, debug_span, field::DebugValue, span, trace, trace_span, warn, Level};
13
14 use tracing::{debug, debug_span, trace, trace_span, warn};
17 15
18 16 use crate::{
19 17 callback::{
20 OperationHandlerCallback, SettingChangeCallback, SettingGetterCallback,
18 OperationHandlerCallback, RuntimeState, SettingChangeCallback, SettingGetterCallback,
21 19 ValueChangeCallback, ValueGetterCallback,
22 20 },
23 handle::{PluginHandle, PluginInitializationState},
24 vtable::{ObjectVtable, OperationVTable, SettingVtable, ValueVTable},
21 future::RuntimeFuture,
22 handle::PluginHandle,
23 vtable::{
24 IntoRuntimeVtable, ObjectVtable, OperationVTable, RuntimeVTable, SettingVtable, ValueVTable,
25 },
26 AnyFailure, AnySuccess,
25 27 };
26 28
27 29 use self::operation_walker::OperationHandlerRules;
@@ -158,6 +160,9 @@ pub struct PluginState {
158 160 pub inner: *mut (),
159 161 }
160 162
163 unsafe impl Send for PluginState {}
164 unsafe impl Sync for PluginState {}
165
161 166 impl PluginState {
162 167 pub unsafe fn transmute_owned<T>(&mut self) -> Box<T> {
163 168 Box::from_raw(self.inner as *mut T)
@@ -171,6 +176,18 @@ impl PluginState {
171 176 }
172 177
173 178 impl PluginState {
179 pub fn from<S>(source: S) -> Self {
180 Self {
181 inner: Box::into_raw(Box::new(source)) as *mut _,
182 }
183 }
184
185 pub unsafe fn from_raw<S>(raw: Box<S>) -> Self {
186 Self {
187 inner: Box::into_raw(raw) as *mut _,
188 }
189 }
190
174 191 pub fn null() -> Self {
175 192 Self { inner: null_mut() }
176 193 }
@@ -181,15 +198,38 @@ pub struct Runtime {
181 198 handlers: RuntimeHandlers,
182 199 }
183 200
201 impl IntoRuntimeVtable for Runtime {
202 unsafe extern "C" fn handle(
203 _this: PluginState,
204 _object_kind: crate::FFIBox<str>,
205 _operation_name: crate::FFIBox<str>,
206 _object: crate::FFIBox<str>,
207 _operation_payload: crate::FFIBox<[u8]>,
208 _operation_state: crate::FFIBox<[u8]>,
209 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>> {
210 todo!()
211 }
212 }
213
184 214 impl Runtime {
185 pub fn new() -> Self {
186 Self {
215 pub fn new() -> Box<Self> {
216 Box::new(Self {
187 217 plugins: vec![],
188 218 handlers: RuntimeHandlers::default(),
219 })
220 }
221
222 pub fn state(self: &Box<Self>, operation_state: &OperationState) -> RuntimeState {
223 RuntimeState {
224 vtable: RuntimeVTable {
225 runtime: PluginState::from(self),
226 handle_fn: <Runtime as IntoRuntimeVtable>::handle,
227 },
228 operation_state: operation_state.clone(),
189 229 }
190 230 }
191 231
192 pub fn insert_plugin(&mut self, mut plugin: PluginHandle) {
232 pub fn insert_plugin(&mut self, plugin: PluginHandle) {
193 233 let _guard = debug_span!("inserting plugin", meta = debug(&plugin.meta)).entered();
194 234
195 235 for (pair, callback) in &plugin.initialization.operation_handlers {
@@ -241,24 +281,29 @@ impl Runtime {
241 281 }
242 282 }
243 283
244 pub fn handle(
245 &self,
246 object_kind: &str,
247 operation_name: &str,
248 object: &str,
249 operation_payload: &[u8],
250 ) -> Result<(), OperationError<()>> {
251 // let rules = self.handlers.handle_operation(object_kind, operation_name);
284 pub fn init(self: Box<Self>) {
285 unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) }
286 }
252 287
253 // rules.handle(object, operation_payload)
288 // pub async fn handle(
289 // &self,
290 // object_kind: &str,
291 // operation_name: &str,
292 // object: &str,
293 // operation_payload: &[u8],
294 // operation_state: &OperationState,
295 // ) -> Result<AnySuccess, OperationError<AnyFailure>> {
296 // let rules = self.handlers.handle_operation(object_kind, operation_name);
254 297
255 todo!()
256 }
298 // let state = self.state(operation_state);
299
300 // rules.handle(&state, object, operation_payload).await
301 // }
257 302
258 303 pub fn handle_typed<O: GiteratedObject, D: GiteratedOperation<O>>(
259 304 &self,
260 object: O,
261 operation: D,
305 _object: O,
306 _operation: D,
262 307 ) -> Result<D::Success, OperationError<D::Failure>> {
263 308 todo!()
264 309 }
@@ -480,37 +525,3 @@ impl RuntimePlugin {
480 525 }
481 526 }
482 527 }
483
484 pub enum HandlerError {
485 Failure(()),
486 Internal(()),
487 Unhandled,
488 }
489
490 pub trait StateId {
491 fn state_id(&self) -> &'static str;
492 }
493
494 pub unsafe trait FfiState: StateId {
495 fn into_ffi_state_bytes(self) -> Vec<u8>;
496
497 fn from_ffi_state_bytes(bytes: Vec<u8>) -> Self;
498 }
499
500 unsafe impl<T> FfiState for T
501 where
502 T: Serialize + StateId,
503 {
504 fn into_ffi_state_bytes(self) -> Vec<u8> {
505 todo!()
506 }
507
508 fn from_ffi_state_bytes(bytes: Vec<u8>) -> Self {
509 todo!()
510 }
511 }
512
513 #[derive(Clone, Debug)]
514 pub struct OperationState {
515 entries: HashMap<&'static str, Vec<u8>>,
516 }

giterated-plugin/src/new_stack/operation_walker.rs

View file
@@ -1,10 +1,14 @@
1 use crate::callback::RuntimeState;
2 use giterated_models::{operation::GiteratedOperation, settings::GetSetting, value::GetValue};
1 use crate::{callback::RuntimeState, AnyFailure, AnySuccess, FFIBox};
2 use giterated_models::{
3 error::OperationError, operation::GiteratedOperation, settings::GetSetting, value::GetValue,
4 };
5
6 use serde_json::Value;
3 7 use tracing::{debug_span, trace, trace_span};
4 8
5 use crate::new_stack::{ObjectOperationPair, PluginState};
9 use crate::new_stack::ObjectOperationPair;
6 10
7 use super::{HandlerError, ObjectSettingPair, ObjectValuePair, RuntimeHandlers};
11 use super::{ObjectSettingPair, ObjectValuePair, RuntimeHandlers};
8 12
9 13 /// A wrapper for operation handling that enforces handling rules.
10 14 ///
@@ -40,15 +44,15 @@ impl<'o> OperationHandlerRules<'o> {
40 44 }
41 45 }
42 46
43 pub fn handle(
47 pub async fn handle(
44 48 &self,
45 49 runtime_state: &RuntimeState,
46 50 object: &str,
47 51 operation_payload: &[u8],
48 ) -> Result<(), HandlerError> {
52 ) -> Result<AnySuccess, OperationError<AnyFailure>> {
49 53 // object_kind: `any`
50 54 // operation_kind: `typed`
51 if let Some(handler) = self
55 if let Some(_handler) = self
52 56 .handlers
53 57 .operation_handlers
54 58 .get(&ObjectOperationPair::new("any", self.operation_name))
@@ -58,7 +62,7 @@ impl<'o> OperationHandlerRules<'o> {
58 62
59 63 // object_kind: `typed`
60 64 // operation_kind: `any`
61 if let Some(handler) = self
65 if let Some(_handler) = self
62 66 .handlers
63 67 .operation_handlers
64 68 .get(&ObjectOperationPair::new(self.object_kind, "any"))
@@ -66,7 +70,7 @@ impl<'o> OperationHandlerRules<'o> {
66 70
67 71 // object_kind: `any`
68 72 // operation_kind: `any`
69 if let Some(handler) = self
73 if let Some(_handler) = self
70 74 .handlers
71 75 .operation_handlers
72 76 .get(&ObjectOperationPair::new("any", "any"))
@@ -95,12 +99,12 @@ impl<'o> OperationHandlerRules<'o> {
95 99
96 100 let object_vtable = domain
97 101 .object_vtable(self.object_kind)
98 .ok_or_else(|| HandlerError::Unhandled)?;
102 .ok_or_else(|| OperationError::Unhandled)?;
99 103 trace!("Resolved object vtable for {}", self.object_kind);
100 104
101 let value_vtable = domain
105 let _value_vtable = domain
102 106 .value_vtable(self.object_kind, &operation.value_name)
103 .ok_or_else(|| HandlerError::Unhandled)?;
107 .ok_or_else(|| OperationError::Unhandled)?;
104 108 trace!(
105 109 "Resolved value vtable for {}::{}",
106 110 self.object_kind,
@@ -108,16 +112,24 @@ impl<'o> OperationHandlerRules<'o> {
108 112 );
109 113
110 114 let object = unsafe { (object_vtable.from_str)(object) }
111 .map_err(|_| HandlerError::Internal(()))?;
115 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
112 116
113 117 let _guard = debug_span!("get_value handler");
114 118
115 let result =
116 unsafe { (callback.func)(callback.callback_ptr, &domain.plugin.state, object) };
117
118 // Todo deser
119
120 return Ok(());
119 let result = unsafe {
120 (callback.func)(
121 callback.callback_ptr,
122 runtime_state,
123 &domain.plugin.state,
124 object,
125 )
126 }
127 .await;
128
129 match result {
130 Ok(value) => return Ok(value.into()),
131 Err(_err) => todo!(),
132 }
121 133 } else {
122 134 trace!("Failed to resolve handler.");
123 135 }
@@ -146,25 +158,46 @@ impl<'o> OperationHandlerRules<'o> {
146 158
147 159 let object_vtable = domain
148 160 .object_vtable(self.object_kind)
149 .ok_or_else(|| HandlerError::Unhandled)?;
161 .ok_or_else(|| OperationError::Unhandled)?;
150 162 trace!("Resolved object vtable for {}", self.object_kind);
151 163
152 let setting_vtable = domain
164 let _setting_vtable = domain
153 165 .setting_vtable(self.object_kind, &operation.setting_name)
154 .ok_or_else(|| HandlerError::Unhandled)?;
166 .ok_or_else(|| OperationError::Unhandled)?;
155 167 trace!("Resolved setting vtable for {}", operation.setting_name);
156 168
157 169 let object = unsafe { (object_vtable.from_str)(object) }
158 .map_err(|_| HandlerError::Internal(()))?;
170 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
159 171
160 172 let _guard = debug_span!("get_value handler");
161 173
162 let result =
163 unsafe { (callback.func)(callback.callback_ptr, &domain.plugin.state, object) };
164
165 // Todo deser
166
167 return Ok(());
174 let result = unsafe {
175 (callback.func)(
176 callback.callback_ptr,
177 runtime_state,
178 &domain.plugin.state,
179 object,
180 )
181 }
182 .await;
183
184 match result {
185 Ok(value) => {
186 let vtable = unsafe { (value.vtable.get_setting_vtable)() };
187 let return_value: Value = serde_json::from_slice(unsafe {
188 (value.vtable.serialize)(value).unwrap().as_ref()
189 })
190 .unwrap();
191
192 return Ok(unsafe {
193 AnySuccess::from_raw(
194 FFIBox::from_box(Box::new(return_value)).untyped(),
195 vtable,
196 )
197 });
198 }
199 Err(_err) => todo!(),
200 }
168 201 } else {
169 202 trace!("Failed to resolve handler.");
170 203 }
@@ -173,12 +206,12 @@ impl<'o> OperationHandlerRules<'o> {
173 206 // ⚠️ Special Case ⚠️
174 207 // object_kind: `any`
175 208 // operation_kind: `SetSetting`
176 if self.operation_name == "set_setting" {}
209 self.operation_name == "set_setting";
177 210
178 211 // ⚠️ Special Case ⚠️
179 212 // object_kind: `any`
180 213 // operation_kind: `ObjectRequest`
181 if self.operation_name == "object_request" {}
214 self.operation_name == "object_request";
182 215
183 216 // object_kind: `typed`
184 217 // operation_kind: `typed`
@@ -194,12 +227,12 @@ impl<'o> OperationHandlerRules<'o> {
194 227
195 228 let object_vtable = domain
196 229 .object_vtable(self.object_kind)
197 .ok_or_else(|| HandlerError::Unhandled)?;
230 .ok_or_else(|| OperationError::Unhandled)?;
198 231 trace!("Resolved object vtable for {}", self.object_kind);
199 232
200 233 let operation_vtable = domain
201 234 .operation_vtable(self.object_kind, self.operation_name)
202 .ok_or_else(|| HandlerError::Unhandled)?;
235 .ok_or_else(|| OperationError::Unhandled)?;
203 236 trace!(
204 237 "Resolved operation vtable for {}::{}",
205 238 self.object_kind,
@@ -207,9 +240,9 @@ impl<'o> OperationHandlerRules<'o> {
207 240 );
208 241
209 242 let object = unsafe { (object_vtable.from_str)(object) }
210 .map_err(|_| HandlerError::Internal(()))?;
243 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
211 244 let operation = unsafe { (operation_vtable.deserialize)(operation_payload) }
212 .map_err(|_| HandlerError::Internal(()))?;
245 .map_err(|_| OperationError::Internal(anyhow::anyhow!("yikes!")))?;
213 246 trace!("Parsed operation data");
214 247
215 248 let _guard = debug_span!("calling handler").entered();
@@ -223,10 +256,9 @@ impl<'o> OperationHandlerRules<'o> {
223 256 )
224 257 };
225 258
226 // todo
227 return Ok(());
259 return result.await;
228 260 }
229 261
230 Err(HandlerError::Unhandled)
262 Err(OperationError::Unhandled)
231 263 }
232 264 }

giterated-plugin/src/new_stack/runtime_handler.rs

View file
@@ -1,16 +1,8 @@
1 use std::fmt::Debug;
2 use std::sync::Arc;
3
4 use giterated_models::{
5 error::OperationError,
6 object::{GiteratedObject, Object, ObjectRequestError},
7 object_backend::ObjectBackend,
8 operation::GiteratedOperation,
9 };
1 use giterated_models::error::OperationError;
10 2
11 3 use crate::vtable::{AnyFailure, AnySuccess, OperationVTable};
12 4
13 use super::{handle::RuntimeHandle, PluginState};
5 use super::PluginState;
14 6
15 7 #[repr(C)]
16 8 struct RuntimeHandleInner {

giterated-plugin/src/vtable/object.rs

View file
@@ -1,4 +1,4 @@
1 use std::mem::transmute;
1 use std::{mem::transmute, str::FromStr};
2 2
3 3 use giterated_models::object::GiteratedObject;
4 4
@@ -9,10 +9,10 @@ use crate::FFIBox;
9 9 pub struct ObjectVtable {
10 10 object_kind: *const u8,
11 11 object_kind_len: usize,
12 pub to_str: unsafe extern "C" fn(AnyObject) -> FFIBox<str>,
12 pub to_str: unsafe extern "C" fn(&AnyObject) -> FFIBox<str>,
13 13 pub from_str: unsafe extern "C" fn(&str) -> Result<AnyObject, FFIBox<str>>,
14 14 pub home_uri: unsafe extern "C" fn(&AnyObject) -> FFIBox<str>,
15 pub is_same: unsafe extern "C" fn(AnyObject) -> bool,
15 pub is_same: unsafe extern "C" fn(&AnyObject) -> bool,
16 16 }
17 17
18 18 impl ObjectVtable {
@@ -39,14 +39,14 @@ impl ObjectVtable {
39 39
40 40 pub trait IntoObjectVTable {
41 41 fn object_kind() -> &'static str;
42 unsafe extern "C" fn to_str(this: AnyObject) -> FFIBox<str>;
42 unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<str>;
43 43 unsafe extern "C" fn from_str(src: &str) -> Result<AnyObject, FFIBox<str>>;
44 44 unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox<str>;
45 unsafe extern "C" fn is_same(other: AnyObject) -> bool;
45 unsafe extern "C" fn is_same(other: &AnyObject) -> bool;
46 46 }
47 47
48 48 impl<T: GiteratedObject + 'static> IntoObjectVTable for T {
49 unsafe extern "C" fn to_str(mut this: AnyObject) -> FFIBox<str> {
49 unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<str> {
50 50 let this: &Box<T> = this.transmute_ref();
51 51
52 52 let result = this.to_string();
@@ -62,16 +62,16 @@ impl<T: GiteratedObject + 'static> IntoObjectVTable for T {
62 62 Ok(any_object)
63 63 }
64 64
65 unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox<str> {
65 unsafe extern "C" fn home_uri(_this: &AnyObject) -> FFIBox<str> {
66 66 todo!()
67 67 }
68 68
69 unsafe extern "C" fn is_same(other: AnyObject) -> bool {
69 unsafe extern "C" fn is_same(_other: &AnyObject) -> bool {
70 70 todo!()
71 71 }
72 72
73 73 fn object_kind() -> &'static str {
74 todo!()
74 <T as GiteratedObject>::object_name()
75 75 }
76 76 }
77 77
@@ -94,6 +94,29 @@ impl AnyObject {
94 94 pub fn vtable(&self) -> ObjectVtable {
95 95 self.vtable
96 96 }
97
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 }
106
107 pub fn home_uri(&self) -> String {
108 unsafe { (self.vtable.home_uri)(self).to_string() }
109 }
110
111 pub fn is_same(&self, other: &AnyObject) -> bool {
112 unsafe { (self.vtable.is_same)(other) }
113 }
114 }
115
116 impl ToString for AnyObject {
117 fn to_string(&self) -> String {
118 unsafe { (self.vtable.to_str)(self).to_string() }
119 }
97 120 }
98 121
99 122 impl AnyObject {

giterated-plugin/src/vtable/operation.rs

View file
@@ -4,8 +4,6 @@ use giterated_models::{object::GiteratedObject, operation::GiteratedOperation};
4 4
5 5 use crate::FFIBox;
6 6
7 use super::AnyObject;
8
9 7 #[derive(Clone, Copy)]
10 8 #[repr(C)]
11 9 pub struct OperationVTable {
@@ -13,7 +11,7 @@ pub struct OperationVTable {
13 11 operation_kind_len: usize,
14 12 pub serialize: unsafe extern "C" fn(&AnyOperation) -> Result<FFIBox<[u8]>, ()>,
15 13 pub deserialize: unsafe extern "C" fn(&[u8]) -> Result<AnyOperation, ()>,
16 pub is_same: unsafe extern "C" fn(AnyObject) -> bool,
14 pub is_same: unsafe extern "C" fn(&AnyOperation) -> bool,
17 15 pub serialize_success: unsafe extern "C" fn(()) -> Result<FFIBox<[u8]>, ()>,
18 16 pub serialize_failure: unsafe extern "C" fn(()) -> Result<FFIBox<[u8]>, ()>,
19 17 pub deserialize_success: unsafe extern "C" fn(&[u8]) -> Result<AnySuccess, ()>,
@@ -46,6 +44,7 @@ impl OperationVTable {
46 44 }
47 45 }
48 46
47 #[repr(C)]
49 48 pub struct AnyOperation {
50 49 /// A pointer to the plugin-local object type. We are not capable of
51 50 /// knowing what this type is, we use the provided vtable.
@@ -54,6 +53,10 @@ pub struct AnyOperation {
54 53 }
55 54
56 55 impl AnyOperation {
56 pub fn new<O: GiteratedObject, D: GiteratedOperation<O>>(_operation: D) -> Self {
57 todo!()
58 }
59
57 60 pub unsafe fn transmute_owned<T>(&mut self) -> Box<T> {
58 61 Box::from_raw(self.inner.0 as *mut T)
59 62 }
@@ -67,6 +70,27 @@ impl AnyOperation {
67 70 pub fn vtable(&self) -> OperationVTable {
68 71 self.vtable
69 72 }
73
74 pub fn operation_kind(&self) -> &str {
75 unsafe {
76 std::str::from_utf8_unchecked(std::slice::from_raw_parts(
77 self.vtable.operation_kind,
78 self.vtable.operation_kind_len,
79 ))
80 }
81 }
82
83 pub fn serialize(&self) -> Result<Vec<u8>, anyhow::Error> {
84 todo!()
85 }
86
87 pub fn deserialize(_source: &[u8], _vtable: OperationVTable) -> Result<Self, anyhow::Error> {
88 todo!()
89 }
90
91 pub fn is_same(&self, _other: &AnyOperation) -> bool {
92 todo!()
93 }
70 94 }
71 95
72 96 #[repr(C)]
@@ -75,17 +99,56 @@ pub struct AnySuccess {
75 99 vtable: OperationVTable,
76 100 }
77 101
102 impl AnySuccess {
103 pub unsafe fn inner<T: Send + Sync>(&self) -> &T {
104 self.inner.transmute_ref()
105 }
106
107 pub unsafe fn from_raw(inner: FFIBox<()>, vtable: OperationVTable) -> Self {
108 Self { inner, vtable }
109 }
110
111 pub fn serialize(&self) -> Result<Vec<u8>, anyhow::Error> {
112 todo!()
113 }
114
115 pub fn deserialize_from_operation(
116 _source: &[u8],
117 _vtable: OperationVTable,
118 ) -> Result<Self, anyhow::Error> {
119 todo!()
120 }
121 }
122
123 unsafe impl Send for AnySuccess {}
124 unsafe impl Sync for AnySuccess {}
125
126 impl std::fmt::Debug for AnySuccess {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 f.debug_struct("AnySuccess").finish()
129 }
130 }
131
78 132 #[repr(C)]
79 133 pub struct AnyFailure {
80 134 inner: FFIBox<()>,
81 135 vtable: OperationVTable,
82 136 }
83 137
138 unsafe impl Send for AnyFailure {}
139 unsafe impl Sync for AnyFailure {}
140
141 impl std::fmt::Debug for AnyFailure {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 f.debug_struct("AnyFailure").finish()
144 }
145 }
146
84 147 pub trait IntoOperationVTable<O> {
85 148 fn operation_kind() -> &'static str;
86 149 unsafe extern "C" fn serialize(this: &AnyOperation) -> Result<FFIBox<[u8]>, ()>;
87 150 unsafe extern "C" fn deserialize(src: &[u8]) -> Result<AnyOperation, ()>;
88 unsafe extern "C" fn is_same(this: AnyObject) -> bool;
151 unsafe extern "C" fn is_same(this: &AnyOperation) -> bool;
89 152 unsafe extern "C" fn serialize_success(success: ()) -> Result<FFIBox<[u8]>, ()>;
90 153 unsafe extern "C" fn serialize_failure(failure: ()) -> Result<FFIBox<[u8]>, ()>;
91 154 unsafe extern "C" fn deserialize_success(src: &[u8]) -> Result<AnySuccess, ()>;
@@ -97,7 +160,7 @@ where
97 160 D: GiteratedOperation<O>,
98 161 O: GiteratedObject,
99 162 {
100 unsafe extern "C" fn serialize(this: &AnyOperation) -> Result<FFIBox<[u8]>, ()> {
163 unsafe extern "C" fn serialize(_this: &AnyOperation) -> Result<FFIBox<[u8]>, ()> {
101 164 todo!()
102 165 }
103 166
@@ -110,27 +173,27 @@ where
110 173 })
111 174 }
112 175
113 unsafe extern "C" fn is_same(this: AnyObject) -> bool {
176 unsafe extern "C" fn is_same(_this: &AnyOperation) -> bool {
114 177 todo!()
115 178 }
116 179
117 unsafe extern "C" fn serialize_success(success: ()) -> Result<FFIBox<[u8]>, ()> {
180 unsafe extern "C" fn serialize_success(_success: ()) -> Result<FFIBox<[u8]>, ()> {
118 181 todo!()
119 182 }
120 183
121 unsafe extern "C" fn serialize_failure(failure: ()) -> Result<FFIBox<[u8]>, ()> {
184 unsafe extern "C" fn serialize_failure(_failure: ()) -> Result<FFIBox<[u8]>, ()> {
122 185 todo!()
123 186 }
124 187
125 unsafe extern "C" fn deserialize_success(src: &[u8]) -> Result<AnySuccess, ()> {
188 unsafe extern "C" fn deserialize_success(_src: &[u8]) -> Result<AnySuccess, ()> {
126 189 todo!()
127 190 }
128 191
129 unsafe extern "C" fn deserialize_failure(src: &[u8]) -> Result<AnyFailure, ()> {
192 unsafe extern "C" fn deserialize_failure(_src: &[u8]) -> Result<AnyFailure, ()> {
130 193 todo!()
131 194 }
132 195
133 196 fn operation_kind() -> &'static str {
134 todo!()
197 <D as GiteratedOperation<_>>::operation_name()
135 198 }
136 199 }

giterated-plugin/src/vtable/runtime.rs

View file
@@ -1,2 +1,29 @@
1 use giterated_models::error::OperationError;
2
3 use crate::{future::RuntimeFuture, new_stack::PluginState, AnyFailure, AnySuccess, FFIBox};
4
1 5 #[derive(Clone, Copy)]
2 pub struct RuntimeVTable {}
6 pub struct RuntimeVTable {
7 pub(crate) runtime: PluginState,
8 pub(crate) handle_fn: unsafe extern "C" fn(
9 PluginState,
10 FFIBox<str>,
11 FFIBox<str>,
12 FFIBox<str>,
13 FFIBox<[u8]>,
14 FFIBox<[u8]>,
15 ) -> RuntimeFuture<
16 Result<AnySuccess, OperationError<AnyFailure>>,
17 >,
18 }
19
20 pub trait IntoRuntimeVtable {
21 unsafe extern "C" fn handle(
22 this: PluginState,
23 object_kind: FFIBox<str>,
24 operation_name: FFIBox<str>,
25 object: FFIBox<str>,
26 operation_payload: FFIBox<[u8]>,
27 operation_state: FFIBox<[u8]>,
28 ) -> RuntimeFuture<Result<AnySuccess, OperationError<AnyFailure>>>;
29 }

giterated-plugin/src/vtable/setting.rs

View file
@@ -1,15 +1,20 @@
1 1 use std::mem::transmute;
2 2
3 use giterated_models::settings::Setting;
3 use giterated_models::{
4 instance::Instance,
5 settings::{GetSetting, Setting},
6 };
4 7
5 use crate::FFIBox;
8 use crate::{AnySuccess, FFIBox};
9
10 use super::OperationVTable;
6 11
7 12 #[repr(C)]
8 13 pub struct NewAnySetting {
9 14 /// A pointer to the plugin-local object type. We are not capable of
10 15 /// knowing what this type is, we use the provided vtable.
11 16 inner: FFIBox<()>,
12 vtable: SettingVtable,
17 pub vtable: SettingVtable,
13 18 }
14 19
15 20 impl NewAnySetting {
@@ -31,9 +36,17 @@ impl NewAnySetting {
31 36 }
32 37 }
33 38
39 impl From<NewAnySetting> for AnySuccess {
40 fn from(val: NewAnySetting) -> Self {
41 unsafe { AnySuccess::from_raw(val.inner, (val.vtable.get_setting_vtable)()) }
42 }
43 }
44
34 45 #[derive(Clone, Copy)]
35 46 #[repr(C)]
36 47 pub struct SettingVtable {
48 pub get_setting_vtable: unsafe extern "C" fn() -> OperationVTable,
49
37 50 pub deserialize: unsafe extern "C" fn(&[u8]) -> Result<(), ()>,
38 51 pub serialize: unsafe extern "C" fn(NewAnySetting) -> Result<FFIBox<[u8]>, ()>,
39 52 }
@@ -41,6 +54,7 @@ pub struct SettingVtable {
41 54 impl SettingVtable {
42 55 pub fn new<T: IntoSettingVTable>() -> Self {
43 56 Self {
57 get_setting_vtable: T::get_setting_vtable,
44 58 deserialize: T::deserialize,
45 59 serialize: T::serialize,
46 60 }
@@ -48,6 +62,7 @@ impl SettingVtable {
48 62 }
49 63
50 64 pub trait IntoSettingVTable {
65 unsafe extern "C" fn get_setting_vtable() -> OperationVTable;
51 66 unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()>;
52 67 unsafe extern "C" fn serialize(this: NewAnySetting) -> Result<FFIBox<[u8]>, ()>;
53 68 }
@@ -56,11 +71,21 @@ impl<S> IntoSettingVTable for S
56 71 where
57 72 S: Setting,
58 73 {
59 unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()> {
74 unsafe extern "C" fn deserialize(_src: &[u8]) -> Result<(), ()> {
60 75 todo!()
61 76 }
62 77
63 78 unsafe extern "C" fn serialize(this: NewAnySetting) -> Result<FFIBox<[u8]>, ()> {
64 todo!()
79 let setting = this.transmute_owned::<S>();
80
81 let serialized = serde_json::to_vec(&setting).unwrap();
82
83 let serialized = serialized.into_boxed_slice();
84
85 Ok(FFIBox::from_box(serialized))
86 }
87
88 unsafe extern "C" fn get_setting_vtable() -> OperationVTable {
89 OperationVTable::new::<Instance, GetSetting>()
65 90 }
66 91 }

giterated-plugin/src/vtable/value.rs

View file
@@ -1,6 +1,11 @@
1 use giterated_models::{object::GiteratedObject, value::GiteratedObjectValue};
1 use giterated_models::{
2 object::GiteratedObject,
3 value::{GetValue, GiteratedObjectValue},
4 };
2 5
3 use crate::FFIBox;
6 use crate::{AnySuccess, FFIBox};
7
8 use super::OperationVTable;
4 9
5 10 #[repr(C)]
6 11 pub struct NewAnyValue {
@@ -10,8 +15,11 @@ pub struct NewAnyValue {
10 15 vtable: ValueVTable,
11 16 }
12 17
18 unsafe impl Send for NewAnyValue {}
19 unsafe impl Sync for NewAnyValue {}
20
13 21 impl NewAnyValue {
14 pub fn new<O, V: IntoValueVTable<O>>(value: V) -> Self {
22 pub fn new<O, V: IntoValueVTable<O> + Send + Sync>(value: V) -> Self {
15 23 NewAnyValue {
16 24 inner: FFIBox::from_box(Box::new(value)).untyped(),
17 25 vtable: ValueVTable::new::<O, V>(),
@@ -19,9 +27,17 @@ impl NewAnyValue {
19 27 }
20 28 }
21 29
30 impl From<NewAnyValue> for AnySuccess {
31 fn from(val: NewAnyValue) -> Self {
32 unsafe { AnySuccess::from_raw(val.inner, (val.vtable.get_value_vtable)()) }
33 }
34 }
35
22 36 #[derive(Clone, Copy)]
23 37 #[repr(C)]
24 38 pub struct ValueVTable {
39 pub get_value_vtable: unsafe extern "C" fn() -> OperationVTable,
40
25 41 pub deserialize: unsafe extern "C" fn(&[u8]) -> Result<NewAnyValue, ()>,
26 42 pub serialize: unsafe extern "C" fn(NewAnyValue) -> Result<FFIBox<[u8]>, ()>,
27 43 }
@@ -29,6 +45,7 @@ pub struct ValueVTable {
29 45 impl ValueVTable {
30 46 pub fn new<O, T: IntoValueVTable<O>>() -> Self {
31 47 Self {
48 get_value_vtable: T::get_value_vtable,
32 49 deserialize: T::deserialize,
33 50 serialize: T::serialize,
34 51 }
@@ -36,6 +53,7 @@ impl ValueVTable {
36 53 }
37 54
38 55 pub trait IntoValueVTable<O> {
56 unsafe extern "C" fn get_value_vtable() -> OperationVTable;
39 57 unsafe extern "C" fn deserialize(src: &[u8]) -> Result<NewAnyValue, ()>;
40 58 unsafe extern "C" fn serialize(this: NewAnyValue) -> Result<FFIBox<[u8]>, ()>;
41 59 }
@@ -45,6 +63,10 @@ where
45 63 O: GiteratedObject,
46 64 V: GiteratedObjectValue<Object = O>,
47 65 {
66 unsafe extern "C" fn get_value_vtable() -> OperationVTable {
67 OperationVTable::new::<O, GetValue>()
68 }
69
48 70 unsafe extern "C" fn deserialize(src: &[u8]) -> Result<NewAnyValue, ()> {
49 71 let _guard = trace_span!(
50 72 "deserialize value",
@@ -61,7 +83,7 @@ where
61 83 })
62 84 }
63 85
64 unsafe extern "C" fn serialize(this: NewAnyValue) -> Result<FFIBox<[u8]>, ()> {
86 unsafe extern "C" fn serialize(_this: NewAnyValue) -> Result<FFIBox<[u8]>, ()> {
65 87 todo!()
66 88 }
67 89 }

plugins/example-plugin/Cargo.toml

View file
@@ -13,9 +13,11 @@ crate-type = ["dylib"]
13 13 [dependencies]
14 14 giterated-plugin = { path = "../../giterated-plugin" }
15 15 giterated-plugin-sys = { path = "../../giterated-plugin/giterated-plugin-sys" }
16 giterated-static-runtime = { path = "../../giterated-plugin/giterated-static-runtime" }
16 17 dlopen2 = "0.6"
17 18 tracing-subscriber = "0.3"
18 19 giterated-models = { path = "../../giterated-models" }
19 20 tracing = "0.1"
20 21 serde_json = "1.0"
21 22 anyhow = "1"
23 tokio = { version = "1.32", features = [ "full" ] }

plugins/example-plugin/src/lib.rs

View file
@@ -1,4 +1,4 @@
1 use std::sync::OnceLock;
1 use std::{mem::forget, sync::OnceLock};
2 2
3 3 use giterated_models::{
4 4 error::OperationError,
@@ -36,7 +36,7 @@ pub extern "C" fn load_host_vtable(_vtable: &HostVTable) {
36 36
37 37 #[no_mangle]
38 38 pub extern "C" fn load_initialization_vtable(init_vtable: &InitializationVTable) {
39 INIT_VTABLE.set(init_vtable.clone()).unwrap();
39 INIT_VTABLE.set(*init_vtable).unwrap();
40 40 println!("Loaded initialization vtable");
41 41 }
42 42
@@ -48,6 +48,16 @@ pub extern "C" fn initialize() -> PluginState {
48 48 .with_max_level(Level::TRACE)
49 49 .init();
50 50
51 println!("Building runtime");
52 let runtime = tokio::runtime::Builder::new_multi_thread()
53 .enable_all()
54 .build()
55 .unwrap();
56
57 let _guard = runtime.enter();
58
59 forget(_guard);
60
51 61 PluginState {
52 62 inner: Box::into_raw(Box::new(())),
53 63 }
@@ -64,32 +74,37 @@ pub extern "C" fn initialize_registration(
64 74 builder.object::<Instance>().object::<User>();
65 75 builder.operation(handler);
66 76 builder.value(value_getter);
67 // builder.setting_getter(setting_getter);
77 builder.setting_getter(setting_getter);
68 78
69 79 state
70 80 }
71 81
72 82 async fn handler(
73 state: (),
74 _object: Instance,
75 _operation: ObjectRequest,
83 _state: (),
84 object: Instance,
85 operation: ObjectRequest,
76 86 ) -> Result<ObjectResponse, OperationError<ObjectRequestError>> {
77 87 info!("handling operation!");
78 88
79 todo!()
89 info!("Try get object {} from instance {}", operation.0, object);
90
91 Ok(ObjectResponse(operation.0))
80 92 }
81 93
82 94 async fn value_getter(
83 state: (),
84 object: User,
95 _state: (),
96 _object: User,
85 97 ) -> Result<DisplayName, OperationError<anyhow::Error>> {
86 98 info!("OwO, value gotten!");
87 99
88 100 Ok(DisplayName(String::from("heya!")))
89 101 }
90 102
91 // fn setting_getter(state: (), object: User) -> Result<DisplayName, ()> {
92 // info!("OwO, setting gotten!");
103 async fn setting_getter(
104 _state: (),
105 _object: User,
106 ) -> Result<DisplayName, OperationError<anyhow::Error>> {
107 info!("OwO, setting gotten!");
93 108
94 // Ok(DisplayName(String::from("heya! (but from a setting)")))
95 // }
109 Ok(DisplayName(String::from("heya! (but from a setting)")))
110 }

plugins/example-plugin/src/main.rs

View file
@@ -1,62 +1,52 @@
1 use giterated_models::object_backend::ObjectBackend;
1 2 use giterated_models::{
2 3 instance::Instance,
3 object::{GiteratedObject, ObjectRequest},
4 operation::GiteratedOperation,
5 settings::{GetSetting, Setting},
4 object::ObjectRequest,
5 operation::OperationState,
6 6 user::{DisplayName, User},
7 value::GetValue,
8 7 };
9 use giterated_plugin::{handle::PluginHandle, new_stack::Runtime, GiteratedPluginApi};
8 use giterated_plugin::{callback::RuntimeState, handle::PluginHandle, new_stack::Runtime};
10 9 use tracing::{info, Level};
11 10
12 fn main() {
11 #[tokio::main]
12 async fn main() -> Result<(), anyhow::Error> {
13 13 tracing_subscriber::fmt()
14 14 .pretty()
15 15 .with_thread_names(true)
16 16 .with_max_level(Level::TRACE)
17 17 .init();
18 18
19 let mut handle = PluginHandle::from_dylib("example_plugin_dylib.dll").unwrap();
19 let handle = PluginHandle::from_dylib("example_plugin_dylib.dll").unwrap();
20 20
21 21 let mut runtime = Runtime::new();
22 22
23 23 runtime.insert_plugin(handle);
24 24
25 let object_request = ObjectRequest(String::from("foobar"));
26
27 match runtime.handle(
28 Instance::object_name(),
29 ObjectRequest::operation_name(),
30 "meow",
31 &serde_json::to_vec(&object_request).unwrap(),
32 ) {
33 Ok(success) => info!("handler call success!"),
34 Err(_) => info!("handler call error"),
35 }
36
37 match runtime.handle(
38 User::object_name(),
39 <GetValue as GiteratedOperation<User>>::operation_name(),
40 "amber:giterated.dev",
41 &serde_json::to_vec(&GetValue {
42 value_name: String::from("display_name"),
43 })
44 .unwrap(),
45 ) {
46 Ok(success) => info!("get_value handler call success!"),
47 Err(_) => info!("get_value handler call error"),
48 }
49
50 match runtime.handle(
51 User::object_name(),
52 <GetSetting as GiteratedOperation<User>>::operation_name(),
53 "amber:giterated.dev",
54 &serde_json::to_vec(&GetSetting {
55 setting_name: DisplayName::name().to_string(),
56 })
57 .unwrap(),
58 ) {
59 Ok(success) => info!("get_setting handler call success!"),
60 Err(_) => info!("get_setting handler call error"),
61 }
25 runtime.init();
26
27 let runtime = unsafe { RuntimeState::from_static() };
28
29 let _object_request = ObjectRequest(String::from("foobar"));
30
31 let _state = OperationState::default();
32
33 let _instance = runtime
34 .get_object::<Instance>("giterated.dev", &OperationState::default())
35 .await?;
36
37 let mut user = runtime
38 .get_object::<User>("ambee:giterated.dev", &OperationState::default())
39 .await?;
40
41 let display_name = user.get::<DisplayName>(&OperationState::default()).await?;
42
43 info!("Display name for user as a value: {}", display_name);
44
45 let display_name = user
46 .get_setting::<DisplayName>(&OperationState::default())
47 .await?;
48
49 info!("Display name for user as a setting: {}", display_name);
50
51 Ok(())
62 52 }

plugins/giterated-backend/src/handlers.rs

View file
@@ -1,28 +1,27 @@
1 use std::sync::Arc;
2
3 1 use giterated_models::{
4 2 error::{OperationError, RepositoryError, UserError},
3 operation::OperationState,
5 4 repository::{Repository, RepositoryInfoRequest, RepositorySummary, RepositoryView},
6 5 user::{User, UserRepositoriesRequest},
7 6 };
8 use giterated_plugin::new_stack::{handle::RuntimeHandle, OperationState, Runtime, State};
7 use giterated_plugin::new_stack::{handle::RuntimeHandle, State};
9 8
10 9 use crate::DatabaseBackend;
11 10
12 11 pub async fn user_get_repositories(
13 state: DatabaseBackend,
14 object: User,
15 request: UserRepositoriesRequest,
12 _state: DatabaseBackend,
13 _object: User,
14 _request: UserRepositoriesRequest,
16 15 ) -> Result<Vec<RepositorySummary>, OperationError<UserError>> {
17 16 todo!()
18 17 }
19 18
20 19 pub async fn repository_info(
21 state: DatabaseBackend,
22 object: Repository,
23 request: RepositoryInfoRequest,
24 runtime: RuntimeHandle,
25 State(operation_state): State<OperationState>,
20 _state: DatabaseBackend,
21 _object: Repository,
22 _request: RepositoryInfoRequest,
23 _runtime: RuntimeHandle,
24 State(_operation_state): State<OperationState>,
26 25 ) -> Result<RepositoryView, OperationError<RepositoryError>> {
27 26 todo!()
28 27 }

plugins/giterated-backend/src/lib.rs

View file
@@ -1,11 +1,9 @@
1 1 pub mod handlers;
2 2 pub mod value;
3 3
4 use giterated_models::{instance::Instance, repository::Repository, user::User};
5 use giterated_plugin_sys::{PluginStackBuilder, ValueSettingExt};
6 use handlers::{repository_info, user_get_repositories};
4 use giterated_models::instance::Instance;
5
7 6 use sqlx::PgPool;
8 use value::{user_get_bio, user_get_display_name, user_set_bio, user_set_display_name};
9 7
10 8 /// A backend implementation which attempts to resolve data from the instance's database.
11 9 #[derive(Debug, Clone)]

plugins/giterated-backend/src/value.rs

View file
@@ -6,31 +6,31 @@ use giterated_models::{
6 6 use crate::DatabaseBackend;
7 7
8 8 pub async fn user_get_display_name(
9 state: DatabaseBackend,
10 user: User,
9 _state: DatabaseBackend,
10 _user: User,
11 11 ) -> Result<DisplayName, OperationError<anyhow::Error>> {
12 12 todo!()
13 13 }
14 14
15 15 pub async fn user_set_display_name(
16 state: DatabaseBackend,
17 user: User,
18 display_name: DisplayName,
16 _state: DatabaseBackend,
17 _user: User,
18 _display_name: DisplayName,
19 19 ) -> Result<(), OperationError<anyhow::Error>> {
20 20 todo!()
21 21 }
22 22
23 23 pub async fn user_get_bio(
24 state: DatabaseBackend,
25 user: User,
24 _state: DatabaseBackend,
25 _user: User,
26 26 ) -> Result<Bio, OperationError<anyhow::Error>> {
27 27 todo!()
28 28 }
29 29
30 30 pub async fn user_set_bio(
31 state: DatabaseBackend,
32 user: User,
33 bio: Bio,
31 _state: DatabaseBackend,
32 _user: User,
33 _bio: Bio,
34 34 ) -> Result<(), OperationError<anyhow::Error>> {
35 35 todo!()
36 36 }

plugins/giterated-issues/src/lib.rs

View file
@@ -4,7 +4,7 @@ use anyhow::Error;
4 4 use giterated_models::{object::GiteratedObject, repository::Repository};
5 5 use giterated_plugin::{
6 6 handle::PluginInitializationState,
7 new_stack::{FFIPluginMeta, OperationState, PluginState},
7 new_stack::{FFIPluginMeta, PluginState},
8 8 vtable::{HostVTable, InitializationVTable},
9 9 };
10 10 use giterated_plugin_sys::PluginStackBuilder;
@@ -62,7 +62,7 @@ impl FromStr for Issue {
62 62 type Err = IssueParseError;
63 63
64 64 fn from_str(s: &str) -> Result<Self, Self::Err> {
65 let (index, repository) = s.split_once(':').ok_or_else(|| IssueParseError)?;
65 let (index, repository) = s.split_once(':').ok_or(IssueParseError)?;
66 66
67 67 let id: u32 = index.parse().map_err(|_| IssueParseError)?;
68 68 let repository = Repository::from_str(repository).map_err(|_| IssueParseError)?;
@@ -98,7 +98,7 @@ pub extern "C" fn load_host_vtable(_vtable: &HostVTable) {
98 98
99 99 #[no_mangle]
100 100 pub extern "C" fn load_initialization_vtable(init_vtable: &InitializationVTable) {
101 INIT_VTABLE.set(init_vtable.clone()).unwrap();
101 INIT_VTABLE.set(*init_vtable).unwrap();
102 102 println!("Loaded initialization vtable");
103 103 }
104 104

plugins/giterated-issues/src/main.rs

View file
@@ -1,13 +1,7 @@
1 1 use std::str::FromStr;
2 2
3 3 use giterated_issues::operations::CreateIssueRequest;
4 use giterated_models::{
5 instance::Instance,
6 object::{GiteratedObject, ObjectRequest},
7 operation::GiteratedOperation,
8 repository::Repository,
9 user::User,
10 };
4 use giterated_models::{repository::Repository, user::User};
11 5 use giterated_plugin::{handle::PluginHandle, new_stack::Runtime};
12 6 use tracing::Level;
13 7
@@ -19,7 +13,7 @@ pub async fn main() {
19 13 .with_max_level(Level::TRACE)
20 14 .init();
21 15
22 let mut handle = PluginHandle::from_dylib("giterated_issues.dll").unwrap();
16 let handle = PluginHandle::from_dylib("giterated_issues.dll").unwrap();
23 17
24 18 let mut runtime = Runtime::new();
25 19

plugins/giterated-protocol/src/handlers.rs

View file
@@ -9,8 +9,7 @@ use giterated_models::{
9 9 operation::GiteratedOperation,
10 10 };
11 11 use giterated_plugin::{
12 new_stack::{handle::RuntimeHandle, OperationState},
13 AnyFailure, AnyObject, AnyOperation, AnySuccess,
12 new_stack::handle::RuntimeHandle, AnyFailure, AnyObject, AnyOperation, AnySuccess,
14 13 };
15 14 use serde::{Deserialize, Serialize};
16 15 use tokio::net::TcpStream;
@@ -103,9 +102,9 @@ pub async fn try_handle_with_remote(
103 102 // TODO:
104 103 // Ideally we support pass-through on object types that aren't used locally.
105 104 // For now, we aren't worrying about that.
106 let object_meta = object.vtable().clone();
105 let object_meta = object.vtable();
107 106
108 let operation_meta = operation.vtable().clone();
107 let operation_meta = operation.vtable();
109 108
110 109 // trace!(
111 110 // "Serializing with {}::{}",
@@ -132,7 +131,7 @@ pub async fn try_handle_with_remote(
132 131 // operation.kind().operation_name
133 132 // );
134 133
135 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() });
136 135
137 136 let payload = unsafe { (operation_meta.serialize)(&operation) }.unwrap();
138 137 let payload = Vec::from(payload.as_ref());

plugins/giterated-protocol/src/lib.rs

View file
@@ -73,6 +73,12 @@ pub struct NetworkOperationState {
73 73 authentication: Vec<Arc<dyn AuthenticationSourceProviders + Send + Sync>>,
74 74 }
75 75
76 impl Default for NetworkOperationState {
77 fn default() -> Self {
78 Self::new()
79 }
80 }
81
76 82 impl NetworkOperationState {
77 83 pub fn new() -> Self {
78 84 Self {
@@ -286,8 +292,7 @@ impl<O: GiteratedObject, D: GiteratedOperation<O>> Authenticated<O, D> {
286 292 source: self
287 293 .source
288 294 .drain(..)
289 .map(|provider| provider.as_ref().authenticate_all(&payload))
290 .flatten()
295 .flat_map(|provider| provider.as_ref().authenticate_all(&payload))
291 296 .collect::<Vec<_>>(),
292 297 payload,
293 298 }