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

ambee/giterated

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

Before

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨e432306

⁨giterated-plugin/src/new_stack/mod.rs⁩ - ⁨16533⁩ bytes
Raw
1 pub mod handle;
2 pub mod operation_walker;
3 pub mod runtime_handler;
4
5 use std::{collections::HashMap, fmt::Debug, mem::transmute, ptr::null_mut, sync::Arc};
6
7 use giterated_abi::{
8 callback::CallbackPtr,
9 result::FfiResult,
10 value_ex::FfiValueUntyped,
11 vtable::{operation::Operation, Object, Setting, VTable, Value},
12 FfiSliceRef,
13 };
14 use giterated_models::{
15 error::OperationError,
16 object::{GiteratedObject, ObjectRequestError},
17 operation::{GiteratedOperation, OperationState},
18 };
19 use semver::Version;
20
21 use tracing::{debug, debug_span, trace, trace_span, warn};
22
23 use crate::{
24 callback::{
25 OperationHandlerCallback, RuntimeState, SettingChangeCallback, SettingGetterCallback,
26 ValueChangeCallback, ValueGetterCallback,
27 },
28 future::RuntimeFuture,
29 handle::{PluginHandle, PluginInitializationState, PluginInitializationTable},
30 vtable::{IntoRuntimeVtable, RuntimeVTable},
31 };
32
33 use self::operation_walker::OperationHandlerRules;
34
35 pub struct State<S>(pub S);
36
37 impl<S> std::ops::Deref for State<S> {
38 type Target = S;
39
40 fn deref(&self) -> &Self::Target {
41 &self.0
42 }
43 }
44
45 #[derive(Default, Clone)]
46 pub struct TypeMetadata {
47 pub objects: HashMap<&'static str, &'static VTable<Object>>,
48 pub operations: HashMap<ObjectOperationPair<'static>, &'static VTable<Operation>>,
49 pub settings: HashMap<ObjectSettingPair<'static>, &'static VTable<Setting>>,
50 pub values: HashMap<ObjectValuePair<'static>, &'static VTable<Value>>,
51 }
52
53 impl TypeMetadata {
54 pub unsafe fn from_static() -> &'static Self {
55 giterated_static_runtime::get_type_metadata_reference()
56 .cast::<TypeMetadata>()
57 .as_ref()
58 }
59
60 pub fn register_object(&mut self, object_kind: &'static str, vtable: &'static VTable<Object>) {
61 trace!("Registering type metadata for {}", object_kind);
62
63 self.objects.insert(object_kind, vtable);
64 }
65
66 pub fn register_operation(
67 &mut self,
68 object_kind: &'static str,
69 operation_name: &'static str,
70 vtable: &'static VTable<Operation>,
71 ) {
72 trace!(
73 "Registering operation metadata for {}::{}",
74 object_kind,
75 operation_name
76 );
77
78 self.operations.insert(
79 ObjectOperationPair {
80 object_kind,
81 operation_name,
82 },
83 vtable,
84 );
85 }
86
87 pub fn register_setting(
88 &mut self,
89 object_kind: &'static str,
90 setting_name: &'static str,
91 vtable: &'static VTable<Setting>,
92 ) {
93 trace!("Registering setting {}::{}", object_kind, setting_name);
94
95 self.settings.insert(
96 ObjectSettingPair {
97 object_kind,
98 setting_name,
99 },
100 vtable,
101 );
102 }
103
104 pub fn register_value(
105 &mut self,
106 object_kind: &'static str,
107 value_name: &'static str,
108 vtable: &'static VTable<Value>,
109 ) {
110 trace!("Registering value {}::{}", object_kind, value_name);
111
112 self.values.insert(
113 ObjectValuePair {
114 object_kind,
115 value_name,
116 },
117 vtable,
118 );
119 }
120 }
121
122 #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
123 pub struct ObjectOperationPair<'s> {
124 pub object_kind: &'s str,
125 pub operation_name: &'s str,
126 }
127
128 impl<'s> ObjectOperationPair<'s> {
129 pub fn new(object_kind: &'s str, operation_name: &'s str) -> Self {
130 Self {
131 object_kind,
132 operation_name,
133 }
134 }
135 }
136
137 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
138 pub struct ObjectSettingPair<'s> {
139 pub object_kind: &'s str,
140 pub setting_name: &'s str,
141 }
142
143 impl<'s> ObjectSettingPair<'s> {
144 pub fn new(object_kind: &'s str, setting_name: &'s str) -> Self {
145 Self {
146 object_kind,
147 setting_name,
148 }
149 }
150 }
151
152 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
153 pub struct ObjectValuePair<'s> {
154 pub object_kind: &'s str,
155 pub value_name: &'s str,
156 }
157
158 impl<'s> ObjectValuePair<'s> {
159 pub fn new(object_kind: &'s str, value_name: &'s str) -> Self {
160 Self {
161 object_kind,
162 value_name,
163 }
164 }
165 }
166
167 #[derive(Clone, Copy)]
168 #[repr(C)]
169 pub struct PluginState {
170 pub inner: *mut (),
171 }
172
173 unsafe impl Send for PluginState {}
174 unsafe impl Sync for PluginState {}
175
176 impl PluginState {
177 pub unsafe fn transmute_owned<T>(&mut self) -> Box<T> {
178 Box::from_raw(self.inner as *mut T)
179 }
180
181 pub unsafe fn transmute_ref<T>(&self) -> &T {
182 let ptr: *const T = transmute(self.inner);
183
184 ptr.as_ref().unwrap()
185 }
186 }
187
188 impl PluginState {
189 pub fn from<S>(source: S) -> Self {
190 Self {
191 inner: Box::into_raw(Box::new(source)) as *mut _,
192 }
193 }
194
195 pub unsafe fn from_box<S>(raw: Box<S>) -> Self {
196 Self {
197 inner: Box::into_raw(raw) as *mut _,
198 }
199 }
200
201 pub unsafe fn from_raw_ptr(raw: *const ()) -> Self {
202 Self {
203 inner: raw as *mut (),
204 }
205 }
206
207 pub fn null() -> Self {
208 Self { inner: null_mut() }
209 }
210 }
211
212 pub struct Runtime {
213 plugins: Vec<PluginHandle>,
214 handlers: RuntimeHandlers,
215 }
216
217 pub struct FfiRuntimeMetadata {
218 runtime: PluginState,
219 }
220
221 impl IntoRuntimeVtable for Runtime {
222 unsafe extern "C" fn handle(
223 _this: PluginState,
224 _object_kind: FfiSliceRef<str>,
225 _operation_name: FfiSliceRef<str>,
226 _object: FfiSliceRef<str>,
227 _operation_payload: FfiSliceRef<[u8]>,
228 _operation_state: FfiSliceRef<[u8]>,
229 ) -> RuntimeFuture<FfiResult<FfiValueUntyped, OperationError<giterated_abi::result::FfiError>>>
230 {
231 todo!()
232 }
233
234 unsafe extern "C" fn get_object(
235 this: PluginState,
236 object_str: &str,
237 operation_state: *mut OperationState,
238 ) -> FfiResult<Object, OperationError<giterated_models::object::ObjectRequestError>> {
239 let runtime_state = unsafe { RuntimeState::from_static() };
240
241 let type_metada = runtime_state
242 .vtable
243 .type_metadata
244 .as_ref()
245 .unwrap_or_else(|| {
246 let runtime = this.transmute_ref::<Runtime>();
247
248 &runtime.plugins.first().unwrap().domain_metadata
249 });
250
251 // for (object_type, object_vtable) in &type_metada.objects {
252 // if let Ok(object) = (object_vtable.from_str)(object_str) {
253 // return Ok(object);
254 // }
255 // }
256
257 // Err(OperationError::Operation(ObjectRequestError::Invalid))
258
259 todo!()
260 }
261 }
262
263 impl Runtime {
264 pub fn new() -> Box<Self> {
265 Box::new(Self {
266 plugins: vec![],
267 handlers: RuntimeHandlers::default(),
268 })
269 }
270
271 pub fn state(self: &Box<Self>) -> RuntimeState {
272 RuntimeState {
273 vtable: RuntimeVTable {
274 runtime: PluginState::from(self),
275 handle_fn: <Runtime as IntoRuntimeVtable>::handle,
276 get_object: <Runtime as IntoRuntimeVtable>::get_object,
277 type_metadata: unsafe { TypeMetadata::from_static() },
278 },
279 }
280 }
281
282 pub fn insert_plugin(
283 &mut self,
284 mut plugin: PluginHandle,
285 mut initialization: PluginInitializationState,
286 ) {
287 let _guard = debug_span!("inserting plugin", meta = debug(&plugin.meta)).entered();
288
289 for (pair, callback) in initialization.operation_handlers.drain() {
290 let _guard =
291 trace_span!("processing operation handler callbacks", pair = debug(pair)).entered();
292
293 if self
294 .handlers
295 .operation_handlers
296 .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback))
297 .is_some()
298 {
299 warn!("Warning! Insertion of handler for overwrote a previous handler.")
300 }
301
302 trace!("Insertion of operation handler successful")
303 }
304
305 for (pair, callback) in initialization.value_getters.drain() {
306 let _guard =
307 trace_span!("processing value getter callbacks", pair = debug(pair)).entered();
308
309 if self
310 .handlers
311 .value_getters
312 .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback))
313 .is_some()
314 {
315 warn!("Warning! Insertion of handler for overwrote a previous handler.")
316 }
317
318 trace!("Insertion of operation handler successful")
319 }
320
321 for (pair, callback) in initialization.setting_getters {
322 let _guard =
323 trace_span!("processing setting getter callbacks", pair = debug(pair)).entered();
324
325 if self
326 .handlers
327 .setting_getters
328 .insert(pair, (RuntimeDomain::from_plugin(&plugin), callback))
329 .is_some()
330 {
331 warn!("Warning! Insertion of setting handler for overwrote a previous handler.")
332 }
333
334 trace!("Insertion of setting handler successful")
335 }
336
337 self.plugins.push(plugin);
338 }
339
340 pub fn init(self: Box<Self>) {
341 unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) }
342 }
343
344 // pub async fn handle(
345 // &self,
346 // object_kind: &str,
347 // operation_name: &str,
348 // object: &str,
349 // operation_payload: &[u8],
350 // operation_state: &OperationState,
351 // ) -> Result<AnySuccess, OperationError<AnyFailure>> {
352 // let rules = self.handlers.handle_operation(object_kind, operation_name);
353
354 // let state = self.state(operation_state);
355
356 // rules.handle(&state, object, operation_payload).await
357 // }
358
359 pub fn handle_typed<O: GiteratedObject, D: GiteratedOperation<O>>(
360 &self,
361 _object: O,
362 _operation: D,
363 ) -> Result<D::Success, OperationError<D::Failure>> {
364 todo!()
365 }
366 }
367
368 #[derive(Default)]
369 pub struct RuntimeHandlers {
370 operation_handlers: HashMap<
371 ObjectOperationPair<'static>,
372 (RuntimeDomain, CallbackPtr<OperationHandlerCallback>),
373 >,
374 value_getters:
375 HashMap<ObjectValuePair<'static>, (RuntimeDomain, CallbackPtr<ValueGetterCallback>)>,
376 setting_getters:
377 HashMap<ObjectSettingPair<'static>, (RuntimeDomain, CallbackPtr<SettingGetterCallback>)>,
378 value_change:
379 HashMap<ObjectValuePair<'static>, (RuntimeDomain, CallbackPtr<ValueChangeCallback>)>,
380 setting_change:
381 HashMap<ObjectSettingPair<'static>, (RuntimeDomain, CallbackPtr<SettingChangeCallback>)>,
382 }
383
384 unsafe impl Send for RuntimeHandlers {}
385 unsafe impl Sync for RuntimeHandlers {}
386
387 impl RuntimeHandlers {
388 pub fn operation_handler(
389 &mut self,
390 pair: ObjectOperationPair<'static>,
391 handler: CallbackPtr<OperationHandlerCallback>,
392 domain: RuntimeDomain,
393 ) {
394 trace!(
395 "Inserting operation handler for {}::{}",
396 pair.object_kind,
397 pair.operation_name
398 );
399
400 // There can only be one handler per operation (at least for now?), send a warning if
401 // a newly registered handler overwrites the previous handler.
402 if self
403 .operation_handlers
404 .insert(pair, (domain, handler))
405 .is_some()
406 {
407 debug!("Warning! A newly inserted operation handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.operation_name);
408 }
409 }
410
411 pub fn value_getter(
412 &mut self,
413 pair: ObjectValuePair<'static>,
414 handler: CallbackPtr<ValueGetterCallback>,
415 domain: RuntimeDomain,
416 ) {
417 trace!(
418 "Inserting value getter for {}::{}",
419 pair.object_kind,
420 pair.value_name
421 );
422
423 if self.value_getters.insert(pair, (domain, handler)).is_some() {
424 debug!(
425 "Warning! A newly inserted value getter for {}::{} overwrites a previous handler.",
426 pair.object_kind, pair.value_name
427 );
428 }
429 }
430
431 pub fn setting_getter(
432 &mut self,
433 pair: ObjectSettingPair<'static>,
434 handler: CallbackPtr<SettingGetterCallback>,
435 domain: RuntimeDomain,
436 ) {
437 trace!(
438 "Inserting setting getter for {}::{}",
439 pair.object_kind,
440 pair.setting_name
441 );
442
443 if self
444 .setting_getters
445 .insert(pair, (domain, handler))
446 .is_some()
447 {
448 debug!("Warning! A newly inserted setting getter for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name);
449 }
450 }
451
452 pub fn value_change(
453 &mut self,
454 pair: ObjectValuePair<'static>,
455 handler: CallbackPtr<ValueChangeCallback>,
456 domain: RuntimeDomain,
457 ) {
458 trace!(
459 "Inserting value change handler for {}::{}",
460 pair.object_kind,
461 pair.value_name
462 );
463
464 if self.value_change.insert(pair, (domain, handler)).is_some() {
465 debug!("Warning! A newly inserted value change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.value_name);
466 panic!("Not intended");
467 }
468 }
469
470 pub fn setting_change(
471 &mut self,
472 pair: ObjectSettingPair<'static>,
473 handler: CallbackPtr<SettingChangeCallback>,
474 domain: RuntimeDomain,
475 ) {
476 trace!(
477 "Inserting setting change handler for {}::{}",
478 pair.object_kind,
479 pair.setting_name
480 );
481
482 if self
483 .setting_change
484 .insert(pair, (domain, handler))
485 .is_some()
486 {
487 debug!("Warning! A newly inserted setting change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name);
488 panic!("Not intended");
489 }
490 }
491 }
492
493 impl RuntimeHandlers {
494 pub fn handle_operation<'o>(
495 &'o self,
496 object_kind: &'o str,
497 operation_name: &'o str,
498 ) -> OperationHandlerRules<'o> {
499 OperationHandlerRules::new(object_kind, operation_name, self)
500 }
501 }
502
503 pub struct RuntimeDomain {
504 plugin: PluginHandle,
505 }
506
507 impl RuntimeDomain {
508 pub fn from_plugin(plugin: &PluginHandle) -> Self {
509 Self {
510 plugin: plugin.clone(),
511 }
512 }
513
514 pub fn object_vtable(&self, object_kind: &str) -> Option<&'static VTable<Object>> {
515 self.plugin
516 .domain_metadata
517 .objects
518 .get(object_kind)
519 .copied()
520 }
521
522 pub fn operation_vtable(
523 &self,
524 object_kind: &str,
525 operation_name: &str,
526 ) -> Option<&'static VTable<Operation>> {
527 self.plugin
528 .domain_metadata
529 .operations
530 .get(&ObjectOperationPair::new(object_kind, operation_name))
531 .copied()
532 }
533
534 pub fn setting_vtable(
535 &self,
536 object_kind: &str,
537 setting_name: &str,
538 ) -> Option<&'static VTable<Setting>> {
539 self.plugin
540 .domain_metadata
541 .settings
542 .get(&ObjectSettingPair::new(object_kind, setting_name))
543 .copied()
544 }
545
546 pub fn value_vtable(
547 &self,
548 object_kind: &str,
549 value_name: &str,
550 ) -> Option<&'static VTable<Value>> {
551 self.plugin
552 .domain_metadata
553 .values
554 .get(&ObjectValuePair::new(object_kind, value_name))
555 .copied()
556 }
557 }
558
559 #[derive(Clone, Debug)]
560 pub struct PluginMeta {
561 pub name: String,
562 pub version: Version,
563 }
564
565 #[repr(C)]
566 pub struct FFIPluginMeta {
567 pub name: *const u8,
568 pub name_len: usize,
569 pub version: *const u8,
570 pub version_len: usize,
571 }
572
573 pub struct RuntimePlugin {
574 handle: PluginHandle,
575 type_metadata: Arc<TypeMetadata>,
576 }
577
578 impl RuntimePlugin {
579 pub fn plugin_meta(&self) -> PluginMeta {
580 let meta = unsafe { self.handle.raw.plugin_meta() };
581
582 let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) };
583 let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) };
584
585 let name = std::str::from_utf8(name).unwrap();
586 let version = std::str::from_utf8(version).unwrap();
587
588 PluginMeta {
589 name: String::from(name),
590 version: Version::parse(version).unwrap(),
591 }
592 }
593 }
594