More progress :)
parent: tbd commit: 92c3f32
Showing 45 changed files with 1034 insertions and 495 deletions
Cargo.lock
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 | } |