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

ambee/giterated

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

MOre pre vtable changes

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨9cfa135

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