diff --git a/Cargo.lock b/Cargo.lock index 20cc46b..5d59ddb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,6 +224,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] +name = "c_linked_list" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" + +[[package]] name = "cc" version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -695,6 +701,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "c_linked_list", "dlopen2", "giterated-models", ] @@ -864,6 +871,7 @@ dependencies = [ "giterated-abi", "giterated-core", "giterated-models", + "giterated-static-runtime", "tracing", ] diff --git a/giterated-core/giterated-models/src/instance/operations.rs b/giterated-core/giterated-models/src/instance/operations.rs index 716d3f2..a261363 100644 --- a/giterated-core/giterated-models/src/instance/operations.rs +++ b/giterated-core/giterated-models/src/instance/operations.rs @@ -104,13 +104,13 @@ impl GiteratedOperation for RepositoryCreateRequest { type Failure = InstanceError; } -impl Object { +impl + std::fmt::Debug, OS> Object { pub async fn register_account( &mut self, email: Option<&str>, username: &str, password: &Secret, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RegisterAccountRequest { @@ -127,7 +127,7 @@ impl Object { &mut self, username: &str, password: &Secret, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( AuthenticationTokenRequest { @@ -145,7 +145,7 @@ impl Object { instance: &Instance, username: &str, password: &Secret, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( AuthenticationTokenRequest { @@ -161,7 +161,7 @@ impl Object { pub async fn token_extension( &mut self, token: &UserAuthenticationToken, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result, OperationError> { self.request::( TokenExtensionRequest { @@ -179,7 +179,7 @@ impl Object { visibility: &RepositoryVisibility, default_branch: &str, owner: &User, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryCreateRequest { diff --git a/giterated-core/giterated-models/src/object.rs b/giterated-core/giterated-models/src/object.rs index 03a054f..48de89e 100644 --- a/giterated-core/giterated-models/src/object.rs +++ b/giterated-core/giterated-models/src/object.rs @@ -1,5 +1,6 @@ use std::{ fmt::{Debug, Display}, + marker::PhantomData, str::FromStr, }; @@ -17,26 +18,28 @@ mod operations; pub use operations::*; #[derive(Debug, Clone)] -pub struct Object { +pub struct Object + Send + Clone, OS> { pub(crate) inner: O, pub(crate) backend: B, + _marker: PhantomData, } -impl Object { +impl + Send + Sync + Clone, O: GiteratedObject, OS> Object { pub fn object(&self) -> &O { &self.inner } - pub unsafe fn new_unchecked(object: O, backend: B) -> Object { + pub unsafe fn new_unchecked(object: O, backend: B) -> Object { Object { inner: object, backend, + _marker: PhantomData, } } } -impl Display - for Object +impl + Send + Sync + Clone, OS> Display + for Object { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.fmt(f) @@ -50,10 +53,10 @@ pub trait GiteratedObject: Send + Display + FromStr + Sync + Clone { fn from_object_str(object_str: &str) -> Result; } -impl Object { +impl, OS> Object { pub async fn get + Send + Debug + 'static>( &mut self, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { let result = self .request( @@ -69,7 +72,7 @@ impl Object( &mut self, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request( GetSetting { @@ -84,7 +87,7 @@ impl Object( &mut self, setting: S, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result<(), OperationError> { self.request( SetSetting { @@ -99,7 +102,7 @@ impl Object + Debug + 'static>( &mut self, request: R, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> where R::Success: Clone, diff --git a/giterated-core/giterated-models/src/object_backend.rs b/giterated-core/giterated-models/src/object_backend.rs index 3edea81..5bd3401 100644 --- a/giterated-core/giterated-models/src/object_backend.rs +++ b/giterated-core/giterated-models/src/object_backend.rs @@ -7,13 +7,13 @@ use crate::{ use std::fmt::Debug; #[async_trait::async_trait(?Send)] -pub trait ObjectBackend: Sized + Clone + Send { +pub trait ObjectBackend: Sized + Clone + Send { async fn object_operation( &self, object: O, operation: &str, payload: D, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> where O: GiteratedObject + Debug + 'static, @@ -24,6 +24,6 @@ pub trait ObjectBackend: Sized + Clone + Send { async fn get_object( &self, object_str: &str, - operation_state: &OperationState, - ) -> Result, OperationError>; + operation_state: &mut OS, + ) -> Result, OperationError>; } diff --git a/giterated-core/giterated-models/src/repository/operations.rs b/giterated-core/giterated-models/src/repository/operations.rs index 41f2cc6..2bfdf75 100644 --- a/giterated-core/giterated-models/src/repository/operations.rs +++ b/giterated-core/giterated-models/src/repository/operations.rs @@ -271,13 +271,13 @@ impl GiteratedOperation for RepositoryBranchesRequest { type Failure = RepositoryError; } -impl Object { +impl + std::fmt::Debug, OS> Object { pub async fn info( &mut self, extra_metadata: bool, rev: Option, path: Option, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryInfoRequest { @@ -293,7 +293,7 @@ impl Object { pub async fn file_from_id( &mut self, id: String, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryFileFromIdRequest(id), @@ -306,7 +306,7 @@ impl Object { &mut self, rev: Option, path: String, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result<(RepositoryFile, String), OperationError> { self.request::( RepositoryFileFromPathRequest { rev, path }, @@ -319,7 +319,7 @@ impl Object { &mut self, start_commit: String, path: String, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryLastCommitOfFileRequest { start_commit, path }, @@ -331,7 +331,7 @@ impl Object { pub async fn commit_by_id( &mut self, id: String, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryCommitFromIdRequest(id), @@ -344,7 +344,7 @@ impl Object { &mut self, old_id: String, new_id: String, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryDiffRequest { old_id, new_id }, @@ -357,7 +357,7 @@ impl Object { &mut self, old_id: String, new_id: String, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryDiffPatchRequest { old_id, new_id }, @@ -369,7 +369,7 @@ impl Object { pub async fn commit_before( &mut self, id: String, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryCommitBeforeRequest(id), @@ -381,7 +381,7 @@ impl Object { pub async fn statistics( &mut self, rev: Option, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result> { self.request::( RepositoryStatisticsRequest { rev }, @@ -392,7 +392,7 @@ impl Object { pub async fn branches( &mut self, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result, OperationError> { self.request::(RepositoryBranchesRequest, operation_state) .await @@ -405,7 +405,7 @@ impl Object { pub async fn issue_labels( &mut self, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result, OperationError> { self.request::(RepositoryIssueLabelsRequest, operation_state) .await @@ -413,7 +413,7 @@ impl Object { pub async fn issues( &mut self, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result, OperationError> { self.request::(RepositoryIssuesRequest, operation_state) .await @@ -424,7 +424,7 @@ impl Object { extra_metadata: bool, rev: Option<&str>, path: Option<&str>, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result, OperationError> { self.request::( RepositoryFileInspectRequest { diff --git a/giterated-core/giterated-models/src/user/operations.rs b/giterated-core/giterated-models/src/user/operations.rs index 95de7b1..2d8d2ed 100644 --- a/giterated-core/giterated-models/src/user/operations.rs +++ b/giterated-core/giterated-models/src/user/operations.rs @@ -22,11 +22,11 @@ impl GiteratedOperation for UserRepositoriesRequest { type Failure = UserError; } -impl Object { +impl + std::fmt::Debug, OS> Object { pub async fn repositories( &mut self, instance: &Instance, - operation_state: &OperationState, + operation_state: &mut OS, ) -> Result, OperationError> { self.request::( UserRepositoriesRequest { diff --git a/giterated-core/src/lib.rs b/giterated-core/src/lib.rs index 7ec4988..c447ca8 100644 --- a/giterated-core/src/lib.rs +++ b/giterated-core/src/lib.rs @@ -1,4 +1,7 @@ -use giterated_abi::vtable::{runtime::RuntimeHandle, VTable}; +use giterated_abi::{ + state::{State, StateUUID}, + vtable::{runtime::RuntimeHandle, VTable}, +}; use giterated_models::{ error::OperationError, object::{GiteratedObject, Object, ObjectRequestError}, @@ -6,6 +9,7 @@ use giterated_models::{ operation::{GiteratedOperation, OperationState}, }; use std::fmt::Debug; +use types::TypeMetadata; pub mod types; @@ -16,13 +20,13 @@ pub struct RuntimeState { } #[async_trait::async_trait(?Send)] -impl ObjectBackend for RuntimeState { +impl ObjectBackend for RuntimeState { async fn object_operation( &self, object: O, operation: &str, payload: D, - operation_state: &OperationState, + operation_state: &mut State, ) -> Result> where O: GiteratedObject + Debug + 'static, @@ -36,8 +40,8 @@ impl ObjectBackend for RuntimeState { async fn get_object( &self, object_str: &str, - operation_state: &OperationState, - ) -> Result, OperationError> { + operation_state: &mut State, + ) -> Result, OperationError> { todo!() } } @@ -101,3 +105,17 @@ impl ObjectBackend for RuntimeState { // todo!() // } // } + +pub struct DomainMetadata(pub &'static TypeMetadata); + +impl DomainMetadata { + pub fn from_static() -> Self { + DomainMetadata(unsafe { TypeMetadata::from_static() }) + } +} + +impl StateUUID for DomainMetadata { + fn uuid() -> u128 { + 1 + } +} diff --git a/giterated-daemon/src/client.rs b/giterated-daemon/src/client.rs index 61479d0..cffcba2 100644 --- a/giterated-daemon/src/client.rs +++ b/giterated-daemon/src/client.rs @@ -92,11 +92,11 @@ pub async fn client_wrapper( pub async fn handle_client_message( payload: AuthenticatedPayload, - operation_state: OperationState, + mut operation_state: giterated_plugin::abi::state::State, runtime: RuntimeHandle, ) -> Result, OperationError>> { let mut networked_object = runtime - .get_object::(&payload.object, &operation_state) + .get_object::(&payload.object, &mut operation_state) .await .as_internal_error_with_context("handling client message")?; @@ -111,6 +111,6 @@ pub async fn handle_client_message( trace!("Calling handler for networked operation"); networked_object - .request(networked_operation, &operation_state) + .request(networked_operation, &mut operation_state) .await } diff --git a/giterated-daemon/src/main.rs b/giterated-daemon/src/main.rs index 2a43c2d..8714d4a 100644 --- a/giterated-daemon/src/main.rs +++ b/giterated-daemon/src/main.rs @@ -51,8 +51,6 @@ async fn main() -> Result<(), Error> { let runtime = Runtime::new(); - let runtime = Arc::new(runtime); - let pool = LocalPoolHandle::new(5); loop { diff --git a/giterated-plugin/giterated-macros/src/lib.rs b/giterated-plugin/giterated-macros/src/lib.rs index 953379d..015f7ce 100644 --- a/giterated-plugin/giterated-macros/src/lib.rs +++ b/giterated-plugin/giterated-macros/src/lib.rs @@ -32,13 +32,31 @@ fn emit_plugin_api() -> impl Into { #[doc(hidden)] #[no_mangle] unsafe extern "C" fn __load_runtime_vtable(vtable: &'static ::giterated_plugin::abi::vtable::VTable<::giterated_plugin::abi::vtable::runtime::RuntimeHandle>) { - todo!() + todo!("runtime vtable insertion is not implemented") } #[doc(hidden)] #[no_mangle] unsafe extern "C" fn __get_plugin_vtable() -> &'static ::giterated_plugin::abi::vtable::VTable<::giterated_plugin::abi::vtable::plugin::Plugin> { - todo!() + unsafe extern "C" fn plugin_name() -> ::giterated_plugin::abi::FfiSliceRef { + ::giterated_plugin::abi::FfiSliceRef::static_ref("plugin name") + } + + unsafe extern "C" fn plugin_version() -> ::giterated_plugin::abi::FfiSliceRef { + ::giterated_plugin::abi::FfiSliceRef::static_ref("0.0.1") + } + + unsafe extern "C" fn type_metadata() -> ::giterated_plugin::abi::value_ex::FfiValueRefUntyped { + todo!() + } + + static PLUGIN_VTABLE: ::giterated_plugin::abi::vtable::plugin::PluginVTable = ::giterated_plugin::abi::vtable::plugin::PluginVTable { + plugin_name, + plugin_version, + type_metadata + }; + + ::giterated_plugin::abi::vtable::VTable::new(&PLUGIN_VTABLE) } } } diff --git a/giterated-plugin/src/domain.rs b/giterated-plugin/src/domain.rs new file mode 100644 index 0000000..5de2081 --- /dev/null +++ b/giterated-plugin/src/domain.rs @@ -0,0 +1,10 @@ +use giterated_abi::state::{DomainState, StateItem}; + +struct PluginDomainState { + pub metadata: StateItem, +} + +/// Sources a [`DomainState`] state entry for the plugin. +pub fn plugin_domain_state() -> DomainState { + todo!() +} diff --git a/giterated-plugin/src/lib.rs b/giterated-plugin/src/lib.rs index f2aad7a..901b291 100644 --- a/giterated-plugin/src/lib.rs +++ b/giterated-plugin/src/lib.rs @@ -1,5 +1,6 @@ #![allow(improper_ctypes_definitions)] +pub mod domain; pub mod future; pub mod local; diff --git a/giterated-runtime/Cargo.toml b/giterated-runtime/Cargo.toml index 29490d6..429e15c 100644 --- a/giterated-runtime/Cargo.toml +++ b/giterated-runtime/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" giterated-abi = { path = "giterated-abi" } giterated-models = { path = "../giterated-core/giterated-models" } giterated-core = { path = "../giterated-core" } +giterated-static-runtime = { path = "giterated-static-runtime" } tracing = "0.1" dlopen2 = "0.6" diff --git a/giterated-runtime/giterated-abi/Cargo.toml b/giterated-runtime/giterated-abi/Cargo.toml index f9f245f..dc0bead 100644 --- a/giterated-runtime/giterated-abi/Cargo.toml +++ b/giterated-runtime/giterated-abi/Cargo.toml @@ -10,4 +10,5 @@ giterated-models = { path = "../../giterated-core/giterated-models"} anyhow = "1" dlopen2 = "0.6" -async-trait = "0.1" \ No newline at end of file +async-trait = "0.1" +c_linked_list = "=1.1.1" \ No newline at end of file diff --git a/giterated-runtime/giterated-abi/src/lib.rs b/giterated-runtime/giterated-abi/src/lib.rs index 197e7f0..898a8a1 100644 --- a/giterated-runtime/giterated-abi/src/lib.rs +++ b/giterated-runtime/giterated-abi/src/lib.rs @@ -197,7 +197,11 @@ impl DerefMut for FfiSlice { } } -impl FfiSliceRef {} +impl FfiSliceRef { + pub fn static_ref(source: &'static T) -> FfiSliceRef { + todo!() + } +} impl Deref for FfiSliceRef<[T]> { type Target = [T]; @@ -233,6 +237,16 @@ impl Deref for FfiValueRef { } } +impl FfiValue { + pub unsafe fn from_raw_ptr(ptr: *mut T) -> FfiValue { + todo!() + } + + pub unsafe fn ptr(&self) -> *const T { + self.inner as *const T + } +} + impl Deref for FfiValueMut { type Target = T; @@ -387,7 +401,7 @@ mod guards { impl<'v, T> StackPinnedSlice<'v, T> { #[inline(always)] - pub fn as_ref(&self) -> FfiSliceRef { + pub fn grant_ref(&self) -> FfiSliceRef { FfiSliceRef { inner: &self.slice as *const _ as *const (), _type_marker: PhantomData, @@ -396,7 +410,7 @@ mod guards { } #[inline(always)] - pub fn as_mut(&mut self) -> FfiSliceMut { + pub fn grant_mut(&mut self) -> FfiSliceMut { FfiSliceMut { inner: &mut self.slice as *mut _ as *mut (), _type_marker: PhantomData, @@ -424,11 +438,11 @@ mod guards { } } - pub struct StackPinnedValue<'v, T> { + pub struct StackPinnedValue<'v, T: ?Sized> { value_ref: &'v T, } - impl<'v, T> StackPinnedValue<'v, T> { + impl<'v, T: ?Sized> StackPinnedValue<'v, T> { /// Grants a reference to the pinned value. /// /// # SAFETY @@ -442,9 +456,23 @@ mod guards { _abi_marker: PhantomData, } } + + /// Grants a reference to the pinned value. + /// + /// # SAFETY + /// - The granted reference **must not** outlive the lifetime of `&self`. + /// - There **must not** be a mutable reference created or mutable dereference performed during the lifetime of the [`FfiValueRef`]. + #[inline(always)] + pub unsafe fn grant_mut(&mut self) -> FfiValueMut { + Ffi { + inner: self.value_ref as *const _ as *const (), + _type_marker: PhantomData, + _abi_marker: PhantomData, + } + } } - impl<'v, T> StackPinnedValue<'v, T> { + impl<'v, T: ?Sized> StackPinnedValue<'v, T> { #[inline(always)] pub(crate) fn from_raw(value: &'v T) -> Self { Self { value_ref: value } diff --git a/giterated-runtime/giterated-abi/src/model_impl/mod.rs b/giterated-runtime/giterated-abi/src/model_impl/mod.rs index dff24e8..b70d081 100644 --- a/giterated-runtime/giterated-abi/src/model_impl/mod.rs +++ b/giterated-runtime/giterated-abi/src/model_impl/mod.rs @@ -1,4 +1,4 @@ -use std::ffi::CStr; +use std::ffi::{CStr, CString}; use giterated_models::{object::GiteratedObject, operation::GiteratedOperation}; @@ -16,7 +16,7 @@ impl IntoObjectVTable for T where T: GiteratedObject, { - fn object_kind() -> &'static CStr { + unsafe extern "C" fn object_kind() -> &'static str { todo!() } diff --git a/giterated-runtime/giterated-abi/src/state.rs b/giterated-runtime/giterated-abi/src/state.rs index a87f22c..1f59138 100644 --- a/giterated-runtime/giterated-abi/src/state.rs +++ b/giterated-runtime/giterated-abi/src/state.rs @@ -1,3 +1,9 @@ +use std::{ + marker::PhantomData, + mem::{transmute, MaybeUninit}, + ptr::{null, null_mut, read}, +}; + use anyhow::Error; pub trait FromOperationState: Sized { @@ -16,16 +22,40 @@ impl FromState for StateExtractor { } } -use giterated_models::error::OperationError; +use c_linked_list::CLinkedListMut; +use giterated_models::{error::OperationError, value}; use crate::{ value_ex::FfiValueUntyped, vtable::{runtime::RuntimeHandle, VTable}, + FfiValue, }; +#[derive(Debug)] #[repr(transparent)] pub struct State { - inner: StateHandle, + list: CLinkedListMut, fn(&StateItem<()>) -> *mut StateItem<()>>, +} + +unsafe impl Send for State {} +unsafe impl Sync for State {} + +impl Default for State { + fn default() -> Self { + let value = FfiValue::new(StateItem { + next_item: core::ptr::null(), + state_uuid: 0, + state: (), + }); + + State { + list: unsafe { + CLinkedListMut::from_ptr(value.ptr() as *const StateItem<()> as *mut _, |n| { + n.next_item as *mut StateItem<()> + }) + }, + } + } } #[repr(transparent)] @@ -33,8 +63,20 @@ struct StateHandle { state: FfiValueUntyped, } +impl StateHandle { + pub unsafe fn clone_unsafe(&self) -> Self { + Self { + state: FfiValueUntyped { + inner: self.state.inner, + _type_marker: PhantomData, + _abi_marker: PhantomData, + }, + } + } +} + #[repr(C)] -struct StateItem { +pub struct StateItem { /// The pointer to the next item. /// /// `next_item` is most likely always an `FfiValue>` and that's how we free them. @@ -43,38 +85,76 @@ struct StateItem { pub state: T, } +impl std::fmt::Debug for StateItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("StateItem") + .field("state_uuid", &self.state_uuid) + .finish() + } +} + impl Drop for State { fn drop(&mut self) { let state_manager = unsafe { StateManager::new(self) }; - for state in state_manager {} + // for state in state_manager {} } } -struct StateManager<'s> { - state: &'s mut State, - last: Option, +pub struct StateManager<'s, S> { + state: S, + _marker: PhantomData<&'s ()>, } -impl<'s> StateManager<'s> { - pub unsafe fn new(handle: &'s mut State) -> Self { - todo!() +impl<'s> StateManager<'s, &'s mut State> { + pub unsafe fn new_mut(handle: &'s mut State) -> Self { + Self { + state: handle, + _marker: PhantomData, + } } - pub unsafe fn write_state(&mut self, state: S) -> Self { - todo!() - } + pub unsafe fn write_state(&mut self, state: S) -> &mut Self { + let list = &mut self.state.list; + let last_item = list.iter_mut().last().unwrap(); - pub unsafe fn get_state(&mut self) -> Option<&S> { - todo!() + last_item.next_item = unsafe { + FfiValue::new(StateItem { + next_item: null(), + state_uuid: S::uuid(), + state, + }) + .ptr() + } as *const StateItem<()>; + + self } } -impl<'s> Iterator for StateManager<'s> { - type Item = StateItem<()>; +impl<'s> StateManager<'s, &'s State> { + pub unsafe fn new<'o: 's>(handle: &'o State) -> Self { + Self { + state: handle, + _marker: PhantomData, + } + } + + pub unsafe fn get_state(&self) -> Option<&S> { + println!("state info: {:#?}", self.state); - fn next(&mut self) -> Option> { - todo!() + for state in self.state.list.iter() { + println!("iter"); + if state.state_uuid == S::uuid() { + let state: *const StateItem = unsafe { transmute(&state) }; + + let value_ref = state.as_ref().unwrap(); + let value_ref = &value_ref.state as *const S; + + return value_ref.as_ref(); + } + } + + None } } @@ -89,11 +169,12 @@ pub trait StateUUID { /// State values for the current execution domain. 99.99% of the time this means "plugin-specific" /// /// The remainder 0.01% of the time it refers to the daemon's runtime domain. -pub struct DomainState(StateItem<()>); +#[repr(transparent)] +pub struct DomainState(pub &'static State); impl StateUUID for DomainState { fn uuid() -> u128 { - todo!() + 32894238940832489328402398490328423 } } @@ -111,10 +192,6 @@ impl RuntimeState { } } -// pub struct Runtime { -// pub queue_insert_state: unsafe extern "C" fn(state_uuid: u128, state: FfiValueUntyped), -// } - pub trait FromState: Sized { fn from_state(state: &mut State) -> Result; } diff --git a/giterated-runtime/giterated-abi/src/vtable/object.rs b/giterated-runtime/giterated-abi/src/vtable/object.rs index ec9338f..d2872ae 100644 --- a/giterated-runtime/giterated-abi/src/vtable/object.rs +++ b/giterated-runtime/giterated-abi/src/vtable/object.rs @@ -1,4 +1,9 @@ -use std::{ffi::CStr, str::FromStr}; +use std::{ + ffi::{CStr, CString}, + str::FromStr, +}; + +use giterated_models::object::GiteratedObject; use crate::{ result::{FfiError, FfiResult}, @@ -18,6 +23,10 @@ impl Object { pub fn home_uri(&self) -> String { todo!() } + + pub unsafe fn cast(self) -> T { + todo!() + } } impl From for Object { @@ -45,7 +54,7 @@ impl ObjectABI for Object { } pub struct ObjectVTable { - pub object_kind: &'static CStr, + pub object_kind: unsafe extern "C" fn() -> &'static str, pub to_str: unsafe extern "C" fn(this: FfiValueRef) -> FfiSlice, pub from_str: unsafe extern "C" fn(from: FfiSliceRef) -> FfiResult, pub home_uri: unsafe extern "C" fn(this: FfiValueRef) -> FfiSlice, @@ -53,14 +62,19 @@ pub struct ObjectVTable { impl ObjectVTable { pub const fn new() -> Self { - todo!() + Self { + object_kind: O::object_kind, + to_str: O::to_str, + from_str: O::from_str, + home_uri: O::home_uri, + } } } pub trait IntoObjectVTable: Sized { const VTABLE: &'static VTable = VTable::new(&ObjectVTable::new::()); - fn object_kind() -> &'static CStr; + unsafe extern "C" fn object_kind() -> &'static str; unsafe extern "C" fn to_str(this: FfiValueRef) -> FfiSlice; unsafe extern "C" fn from_str(from: FfiSliceRef) -> FfiResult; unsafe extern "C" fn home_uri(this: FfiValueRef) -> FfiSlice; diff --git a/giterated-runtime/giterated-abi/src/vtable/runtime.rs b/giterated-runtime/giterated-abi/src/vtable/runtime.rs index 40cb196..93a769d 100644 --- a/giterated-runtime/giterated-abi/src/vtable/runtime.rs +++ b/giterated-runtime/giterated-abi/src/vtable/runtime.rs @@ -1,6 +1,6 @@ use giterated_models::{ error::OperationError, - object::{GiteratedObject, ObjectRequestError}, + object::{self, GiteratedObject, ObjectRequestError}, object_backend::ObjectBackend, operation::{GiteratedOperation, OperationState}, }; @@ -9,15 +9,17 @@ use crate::{ result::{FfiError, FfiResult}, state::State, value_ex::FfiValueUntyped, - FfiFuture, FfiSliceRef, FfiValueMut, + FfiFuture, FfiSliceRef, FfiValueMut, StackPinned, }; use core::fmt::Debug; -use super::{Object, ObjectABI}; +use super::{Object, ObjectABI, VTable}; #[derive(Clone)] -pub struct RuntimeHandle; +pub struct RuntimeHandle { + pub vtable: &'static VTable, +} impl ObjectABI for RuntimeHandle { type VTable = RuntimeVTable; @@ -45,10 +47,20 @@ impl RuntimeHandle { todo!() } - pub async fn inner_get_object( + pub fn inner_get_object( &self, object_str: &str, + state: &mut State, ) -> Result> { + let pinned_object_str = (*object_str.as_bytes()).pin(); + let mut pinned_state = (*state).pin(); + + let result = unsafe { + (self.vtable.get_object)(unsafe { pinned_object_str.grant_ref() }, unsafe { + pinned_state.grant_mut() + }) + }; + todo!() } } @@ -66,15 +78,26 @@ pub struct RuntimeVTable { >, pub(crate) get_object: unsafe extern "C" fn( - &str, + object_str: FfiSliceRef, state: FfiValueMut, ) -> FfiResult>, } +impl RuntimeVTable { + pub const fn new() -> RuntimeVTable { + RuntimeVTable { + handle_fn: R::handle, + get_object: R::get_object, + } + } +} + unsafe impl Send for RuntimeVTable {} unsafe impl Sync for RuntimeVTable {} -pub trait IntoRuntimeVtable { +pub trait IntoRuntimeVtable: Sized { + const VTABLE: RuntimeVTable = RuntimeVTable::new::(); + unsafe extern "C" fn handle( object_kind: FfiSliceRef, operation_name: FfiSliceRef, @@ -84,19 +107,19 @@ pub trait IntoRuntimeVtable { ) -> FfiFuture>>; unsafe extern "C" fn get_object( - object_str: &str, + object_str: FfiSliceRef, operation_state: FfiValueMut, ) -> FfiResult>; } #[async_trait::async_trait(?Send)] -impl ObjectBackend for RuntimeHandle { +impl ObjectBackend for RuntimeHandle { async fn object_operation( &self, object: O, operation: &str, payload: D, - operation_state: &OperationState, + operation_state: &mut State, ) -> Result> where O: GiteratedObject + Debug + 'static, @@ -110,8 +133,10 @@ impl ObjectBackend for RuntimeHandle { async fn get_object( &self, object_str: &str, - operation_state: &OperationState, - ) -> Result, OperationError> { - todo!() + operation_state: &mut State, + ) -> Result, OperationError> { + let result = self.inner_get_object(object_str, operation_state)?; + + Ok(unsafe { object::Object::new_unchecked(result.cast(), self.clone()) }) } } diff --git a/giterated-runtime/giterated-static-runtime/src/lib.rs b/giterated-runtime/giterated-static-runtime/src/lib.rs index 1fd008b..d8e87c7 100644 --- a/giterated-runtime/giterated-static-runtime/src/lib.rs +++ b/giterated-runtime/giterated-static-runtime/src/lib.rs @@ -15,6 +15,16 @@ pub unsafe fn get_runtime_reference() -> NonNull<()> { GITERATED_RUNTIME.assume_init_read().0 } +static mut GITERATED_RUNTIME_HANDLE: MaybeUninit = MaybeUninit::zeroed(); + +pub unsafe fn initialize_runtime_handle(runtime_handle: *mut ()) { + GITERATED_RUNTIME_HANDLE.write(RuntimePointer(NonNull::new(runtime_handle).unwrap())); +} + +pub unsafe fn get_runtime_handle() -> NonNull<()> { + GITERATED_RUNTIME_HANDLE.assume_init_read().0 +} + static mut GITERATED_TYPE_METADATA: MaybeUninit = MaybeUninit::zeroed(); pub unsafe fn initialize_type_metadata(runtime_pointer: *mut ()) { diff --git a/giterated-runtime/src/domain.rs b/giterated-runtime/src/domain.rs new file mode 100644 index 0000000..7ba1dca --- /dev/null +++ b/giterated-runtime/src/domain.rs @@ -0,0 +1,18 @@ +use std::{cell::OnceCell, sync::OnceLock}; + +use giterated_abi::state::{DomainState, State, StateItem}; +use giterated_core::DomainMetadata; + +struct RuntimeDomainState { + pub metadata: DomainMetadata, +} + +unsafe impl Send for RuntimeDomainState {} +unsafe impl Sync for RuntimeDomainState {} + +static RUNTIME_DOMAIN_STATE: OnceLock = OnceLock::new(); + +/// Sources a [`DomainState`] state entry for the application hosting the runtime. +pub fn runtime_domain_state() -> DomainState { + DomainState(RUNTIME_DOMAIN_STATE.get().unwrap()) +} diff --git a/giterated-runtime/src/lib.rs b/giterated-runtime/src/lib.rs index bfd2fdb..c8e5a07 100644 --- a/giterated-runtime/src/lib.rs +++ b/giterated-runtime/src/lib.rs @@ -1,3 +1,4 @@ +pub mod domain; mod operation_walker; pub mod plugin; @@ -13,12 +14,19 @@ use giterated_abi::{ CallbackPtr, }, plugin::GiteratedPluginAbi, - vtable::{operation::Operation, plugin::Plugin, Object, Setting, VTable, Value}, + state::{DomainState, State, StateManager, StateUUID}, + vtable::{ + operation::Operation, + plugin::Plugin, + runtime::{IntoRuntimeVtable, RuntimeVTable}, + Object, Setting, VTable, Value, + }, + FfiSliceRef, FfiValueMut, }; -use giterated_core::types::TypeMetadata; +use giterated_core::{types::TypeMetadata, DomainMetadata}; use giterated_models::{ error::OperationError, - object::{GiteratedObject, ObjectOperationPair}, + object::{GiteratedObject, ObjectOperationPair, ObjectRequestError}, operation::GiteratedOperation, settings::ObjectSettingPair, value::ObjectValuePair, @@ -63,7 +71,9 @@ impl Runtime { } pub fn state(self: &Box) -> RuntimeHandle { - RuntimeHandle + RuntimeHandle { + vtable: VTable::new(&::VTABLE), + } } pub fn load_dylib(&mut self, path: impl AsRef) -> Result<(), Error> { @@ -142,8 +152,12 @@ impl Runtime { } pub fn init(self: Box) { - todo!() - // unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) } + unsafe { + giterated_static_runtime::initialize_runtime_handle( + &Self::VTABLE as *const _ as *const () as *mut (), + ) + } + unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) } } // pub async fn handle( @@ -404,6 +418,41 @@ pub trait StaticRuntimeExt { impl StaticRuntimeExt for RuntimeHandle { fn from_static() -> Self { + let vtable = unsafe { + giterated_static_runtime::get_runtime_handle() + .cast::>() + .as_ref() + }; + + RuntimeHandle { vtable } + } +} + +impl IntoRuntimeVtable for Runtime { + unsafe extern "C" fn handle( + object_kind: giterated_abi::FfiSliceRef, + operation_name: giterated_abi::FfiSliceRef, + object: giterated_abi::FfiSliceRef, + operation_payload: giterated_abi::FfiSliceRef<[u8]>, + operation_state: giterated_abi::FfiSliceRef<[u8]>, + ) -> giterated_abi::FfiFuture< + giterated_abi::result::FfiResult< + giterated_abi::value_ex::FfiValueUntyped, + OperationError, + >, + > { + todo!() + } + + unsafe extern "C" fn get_object( + object_str: FfiSliceRef, + mut operation_state: FfiValueMut, + ) -> giterated_abi::result::FfiResult> { + let state_manager = StateManager::new(&mut operation_state); + + let domain_state = state_manager.get_state::().unwrap(); + + // let runtime = todo!() } } diff --git a/plugins/example-plugin/src/main.rs b/plugins/example-plugin/src/main.rs index f38276f..76cd7d4 100644 --- a/plugins/example-plugin/src/main.rs +++ b/plugins/example-plugin/src/main.rs @@ -6,6 +6,7 @@ use giterated_models::{ user::{DisplayName, User}, }; use giterated_plugin::abi::vtable::runtime::RuntimeHandle; +use giterated_runtime::domain::runtime_domain_state; use giterated_runtime::{Runtime, StaticRuntimeExt}; use tracing::{info, Level}; @@ -23,27 +24,31 @@ async fn main() -> Result<(), anyhow::Error> { runtime.init(); - let runtime = unsafe { RuntimeHandle::from_static() }; + let runtime = RuntimeHandle::from_static(); let _object_request = ObjectRequest(String::from("foobar")); - let _state = OperationState::default(); + let mut state = giterated_plugin::abi::state::State::default(); + + let mut state_manager = + unsafe { giterated_plugin::abi::state::StateManager::new_mut(&mut state) }; + unsafe { state_manager.write_state(unsafe { runtime_domain_state() }) }; + + println!("state info: {:#?}", state); let _instance = runtime - .get_object::("giterated.dev", &OperationState::default()) + .get_object::("giterated.dev", &mut state) .await?; let mut user = runtime - .get_object::("ambee:giterated.dev", &OperationState::default()) + .get_object::("ambee:giterated.dev", &mut state) .await?; - let display_name = user.get::(&OperationState::default()).await?; + let display_name = user.get::(&mut state).await?; info!("Display name for user as a value: {}", display_name); - let display_name = user - .get_setting::(&OperationState::default()) - .await?; + let display_name = user.get_setting::(&mut state).await?; info!("Display name for user as a setting: {}", display_name);