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

ambee/giterated

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

no clue what this is

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨7889bf6

⁨giterated-runtime/src/lib.rs⁩ - ⁨13761⁩ bytes
Raw
1 pub mod domain;
2 mod operation_walker;
3 pub mod plugin;
4
5 use std::{collections::HashMap, sync::Arc};
6
7 use anyhow::Error;
8 use dlopen2::wrapper::Container;
9 use giterated_abi::{
10 callback::{
11 operation::OperationHandlerCallback,
12 setting::{SettingChangeCallback, SettingGetterCallback},
13 value::{ValueChangeCallback, ValueGetterCallback},
14 CallbackPtr,
15 },
16 plugin::GiteratedPluginAbi,
17 state::{DomainState, State, StateManager, StateUUID},
18 vtable::{
19 operation::Operation,
20 plugin::Plugin,
21 runtime::{IntoRuntimeVtable, RuntimeVTable},
22 Object, Setting, VTable, Value,
23 },
24 FfiSliceRef, FfiValueMut,
25 };
26 use giterated_core::{types::TypeMetadata, DomainMetadata};
27 use giterated_models::{
28 error::OperationError,
29 object::{GiteratedObject, ObjectOperationPair, ObjectRequestError},
30 operation::GiteratedOperation,
31 settings::ObjectSettingPair,
32 value::ObjectValuePair,
33 };
34 use operation_walker::OperationHandlerRules;
35 use plugin::initialization::PluginInitializationState;
36 use tracing::{debug, debug_span, trace, trace_span, warn};
37
38 pub use giterated_abi::vtable::runtime::RuntimeHandle;
39
40 pub struct Runtime {
41 plugins: Vec<RuntimePlugin>,
42 handlers: RuntimeHandlers,
43 }
44
45 #[derive(Clone)]
46 pub struct RuntimePlugin {
47 vtable: &'static VTable<Plugin>,
48 library: Arc<Container<GiteratedPluginAbi>>,
49 }
50
51 impl RuntimePlugin {
52 pub fn name(&self) -> &'static str {
53 todo!()
54 }
55
56 pub fn version(&self) -> &'static str {
57 todo!()
58 }
59
60 pub fn metadata(&self) -> &TypeMetadata {
61 todo!()
62 }
63 }
64
65 impl Runtime {
66 pub fn new() -> Box<Self> {
67 Box::new(Self {
68 plugins: vec![],
69 handlers: RuntimeHandlers::default(),
70 })
71 }
72
73 pub fn state(self: &Box<Self>) -> RuntimeHandle {
74 RuntimeHandle {
75 vtable: VTable::new(&<Self as IntoRuntimeVtable>::VTABLE),
76 }
77 }
78
79 pub fn load_dylib(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
80 let path = path.as_ref();
81
82 let _guard = debug_span!("loading dylib", path = debug(path)).entered();
83
84 let library: Container<GiteratedPluginAbi> = unsafe { Container::load(path) }?;
85
86 let vtable = unsafe { library.__get_plugin_vtable() };
87
88 self.plugins.push(RuntimePlugin {
89 vtable,
90 library: Arc::new(library),
91 });
92
93 Ok(())
94 }
95
96 pub fn insert_plugin(
97 &mut self,
98 plugin: RuntimePlugin,
99 mut initialization: PluginInitializationState,
100 ) {
101 let _guard = debug_span!("inserting plugin", meta = debug(&plugin.name())).entered();
102
103 for (pair, callback) in initialization.operation_handlers.drain() {
104 let _guard =
105 trace_span!("processing operation handler callbacks", pair = debug(pair)).entered();
106
107 if self
108 .handlers
109 .operation_handlers
110 .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback))
111 .is_some()
112 {
113 warn!("Warning! Insertion of handler for overwrote a previous handler.")
114 }
115
116 trace!("Insertion of operation handler successful")
117 }
118
119 for (pair, callback) in initialization.value_getters.drain() {
120 let _guard =
121 trace_span!("processing value getter callbacks", pair = debug(pair)).entered();
122
123 if self
124 .handlers
125 .value_getters
126 .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback))
127 .is_some()
128 {
129 warn!("Warning! Insertion of handler for overwrote a previous handler.")
130 }
131
132 trace!("Insertion of operation handler successful")
133 }
134
135 for (pair, callback) in initialization.setting_getters {
136 let _guard =
137 trace_span!("processing setting getter callbacks", pair = debug(pair)).entered();
138
139 if self
140 .handlers
141 .setting_getters
142 .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback))
143 .is_some()
144 {
145 warn!("Warning! Insertion of setting handler for overwrote a previous handler.")
146 }
147
148 trace!("Insertion of setting handler successful")
149 }
150
151 self.plugins.push(plugin);
152 }
153
154 pub fn init(self: Box<Self>) {
155 unsafe {
156 giterated_static_runtime::initialize_runtime_handle(
157 &Self::VTABLE as *const _ as *const () as *mut (),
158 )
159 }
160 unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) }
161 }
162
163 // pub async fn handle(
164 // &self,
165 // object_kind: &str,
166 // operation_name: &str,
167 // object: &str,
168 // operation_payload: &[u8],
169 // operation_state: &OperationState,
170 // ) -> Result<AnySuccess, OperationError<AnyFailure>> {
171 // let rules = self.handlers.handle_operation(object_kind, operation_name);
172
173 // let state = self.state(operation_state);
174
175 // rules.handle(&state, object, operation_payload).await
176 // }
177
178 pub fn handle_typed<O: GiteratedObject, D: GiteratedOperation<O>>(
179 &self,
180 _object: O,
181 _operation: D,
182 ) -> Result<D::Success, OperationError<D::Failure>> {
183 todo!()
184 }
185 }
186
187 pub struct RuntimeDomain {
188 plugin: RuntimePlugin,
189 }
190
191 impl RuntimeDomain {
192 pub fn from_plugin(plugin: &RuntimePlugin) -> Self {
193 Self {
194 plugin: plugin.clone(),
195 }
196 }
197
198 pub fn object_vtable(&self, object_kind: &str) -> Option<&'static VTable<Object>> {
199 self.plugin.metadata().objects.get(object_kind).copied()
200 }
201
202 pub fn operation_vtable(
203 &self,
204 object_kind: &str,
205 operation_name: &str,
206 ) -> Option<&'static VTable<Operation>> {
207 self.plugin
208 .metadata()
209 .operations
210 .get(&ObjectOperationPair::new(object_kind, operation_name))
211 .copied()
212 }
213
214 pub fn setting_vtable(
215 &self,
216 object_kind: &str,
217 setting_name: &str,
218 ) -> Option<&'static VTable<Setting>> {
219 self.plugin
220 .metadata()
221 .settings
222 .get(&ObjectSettingPair::new(object_kind, setting_name))
223 .copied()
224 }
225
226 pub fn value_vtable(
227 &self,
228 object_kind: &str,
229 value_name: &str,
230 ) -> Option<&'static VTable<Value>> {
231 self.plugin
232 .metadata()
233 .values
234 .get(&ObjectValuePair::new(object_kind, value_name))
235 .copied()
236 }
237 }
238
239 #[repr(C)]
240 pub struct FFIPluginMeta {
241 pub name: *const u8,
242 pub name_len: usize,
243 pub version: *const u8,
244 pub version_len: usize,
245 }
246
247 // pub struct RuntimePlugin {
248 // handle: PluginHandle,
249 // type_metadata: Arc<TypeMetadata>,
250 // }
251
252 impl RuntimePlugin {
253 // pub fn plugin_meta(&self) -> PluginMeta {
254 // let meta = unsafe { self.handle.raw.plugin_meta() };
255
256 // let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) };
257 // let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) };
258
259 // let name = std::str::from_utf8(name).unwrap();
260 // let version = std::str::from_utf8(version).unwrap();
261
262 // PluginMeta {
263 // name: String::from(name),
264 // version: Version::parse(version).unwrap(),
265 // }
266 // }
267 }
268
269 // #[derive(WrapperApi)]
270 // pub struct GiteratedPluginApi {
271 // plugin_meta: unsafe extern "C" fn() -> FFIPluginMeta,
272 // load_host_vtable: unsafe extern "C" fn(vtable: &HostVTable),
273 // load_initialization_vtable: unsafe extern "C" fn(vtable: &'static VTable<Initialization>),
274 // initialize: unsafe extern "C" fn(runtime_state: *const RuntimeState) -> PluginState,
275 // initialize_registration: unsafe extern "C" fn(
276 // init_state: *mut PluginInitializationState,
277 // ) -> *mut PluginInitializationState,
278 // load_type_metadata: unsafe extern "C" fn(metadata: *mut ()),
279 // }
280 #[derive(Default)]
281 pub struct RuntimeHandlers {
282 operation_handlers: HashMap<
283 ObjectOperationPair<'static>,
284 (RuntimeDomain, CallbackPtr<OperationHandlerCallback>),
285 >,
286 value_getters:
287 HashMap<ObjectValuePair<'static>, (RuntimeDomain, CallbackPtr<ValueGetterCallback>)>,
288 setting_getters:
289 HashMap<ObjectSettingPair<'static>, (RuntimeDomain, CallbackPtr<SettingGetterCallback>)>,
290 value_change:
291 HashMap<ObjectValuePair<'static>, (RuntimeDomain, CallbackPtr<ValueChangeCallback>)>,
292 setting_change:
293 HashMap<ObjectSettingPair<'static>, (RuntimeDomain, CallbackPtr<SettingChangeCallback>)>,
294 }
295
296 unsafe impl Send for RuntimeHandlers {}
297 unsafe impl Sync for RuntimeHandlers {}
298
299 impl RuntimeHandlers {
300 pub fn operation_handler(
301 &mut self,
302 pair: ObjectOperationPair<'static>,
303 handler: CallbackPtr<OperationHandlerCallback>,
304 domain: RuntimeDomain,
305 ) {
306 trace!(
307 "Inserting operation handler for {}::{}",
308 pair.object_kind,
309 pair.operation_name
310 );
311
312 // There can only be one handler per operation (at least for now?), send a warning if
313 // a newly registered handler overwrites the previous handler.
314 if self
315 .operation_handlers
316 .insert(pair, (domain, handler))
317 .is_some()
318 {
319 debug!("Warning! A newly inserted operation handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.operation_name);
320 }
321 }
322
323 pub fn value_getter(
324 &mut self,
325 pair: ObjectValuePair<'static>,
326 handler: CallbackPtr<ValueGetterCallback>,
327 domain: RuntimeDomain,
328 ) {
329 trace!(
330 "Inserting value getter for {}::{}",
331 pair.object_kind,
332 pair.value_name
333 );
334
335 if self.value_getters.insert(pair, (domain, handler)).is_some() {
336 debug!(
337 "Warning! A newly inserted value getter for {}::{} overwrites a previous handler.",
338 pair.object_kind, pair.value_name
339 );
340 }
341 }
342
343 pub fn setting_getter(
344 &mut self,
345 pair: ObjectSettingPair<'static>,
346 handler: CallbackPtr<SettingGetterCallback>,
347 domain: RuntimeDomain,
348 ) {
349 trace!(
350 "Inserting setting getter for {}::{}",
351 pair.object_kind,
352 pair.setting_name
353 );
354
355 if self
356 .setting_getters
357 .insert(pair, (domain, handler))
358 .is_some()
359 {
360 debug!("Warning! A newly inserted setting getter for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name);
361 }
362 }
363
364 pub fn value_change(
365 &mut self,
366 pair: ObjectValuePair<'static>,
367 handler: CallbackPtr<ValueChangeCallback>,
368 domain: RuntimeDomain,
369 ) {
370 trace!(
371 "Inserting value change handler for {}::{}",
372 pair.object_kind,
373 pair.value_name
374 );
375
376 if self.value_change.insert(pair, (domain, handler)).is_some() {
377 debug!("Warning! A newly inserted value change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.value_name);
378 panic!("Not intended");
379 }
380 }
381
382 pub fn setting_change(
383 &mut self,
384 pair: ObjectSettingPair<'static>,
385 handler: CallbackPtr<SettingChangeCallback>,
386 domain: RuntimeDomain,
387 ) {
388 trace!(
389 "Inserting setting change handler for {}::{}",
390 pair.object_kind,
391 pair.setting_name
392 );
393
394 if self
395 .setting_change
396 .insert(pair, (domain, handler))
397 .is_some()
398 {
399 debug!("Warning! A newly inserted setting change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name);
400 panic!("Not intended");
401 }
402 }
403 }
404
405 impl RuntimeHandlers {
406 pub fn handle_operation<'o>(
407 &'o self,
408 object_kind: &'o str,
409 operation_name: &'o str,
410 ) -> OperationHandlerRules<'o> {
411 OperationHandlerRules::new(object_kind, operation_name, self)
412 }
413 }
414
415 pub trait StaticRuntimeExt {
416 fn from_static() -> Self;
417 }
418
419 impl StaticRuntimeExt for RuntimeHandle {
420 fn from_static() -> Self {
421 let vtable = unsafe {
422 giterated_static_runtime::get_runtime_handle()
423 .cast::<VTable<RuntimeHandle>>()
424 .as_ref()
425 };
426
427 RuntimeHandle { vtable }
428 }
429 }
430
431 impl IntoRuntimeVtable for Runtime {
432 unsafe extern "C" fn handle(
433 object_kind: giterated_abi::FfiSliceRef<str>,
434 operation_name: giterated_abi::FfiSliceRef<str>,
435 object: giterated_abi::FfiSliceRef<str>,
436 operation_payload: giterated_abi::FfiSliceRef<[u8]>,
437 operation_state: giterated_abi::FfiSliceRef<[u8]>,
438 ) -> giterated_abi::FfiFuture<
439 giterated_abi::result::FfiResult<
440 giterated_abi::value_ex::FfiValueUntyped,
441 OperationError<giterated_abi::result::FfiError>,
442 >,
443 > {
444 todo!()
445 }
446
447 unsafe extern "C" fn get_object(
448 object_str: FfiSliceRef<u8>,
449 mut operation_state: FfiValueMut<State>,
450 ) -> giterated_abi::result::FfiResult<Object, OperationError<ObjectRequestError>> {
451 let state_manager = StateManager::new(&mut operation_state);
452
453 let domain_state = state_manager.get_state::<DomainState>().unwrap();
454
455 // let runtime =
456 todo!()
457 }
458 }
459