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

ambee/giterated

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

More progress :)

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨92c3f32

⁨giterated-plugin/src/new_stack/mod.rs⁩ - ⁨14667⁩ 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,
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)]
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 fn register_object(&mut self, object_kind: &'static str, vtable: ObjectVtable) {
51 trace!("Registering type metadata for {}", object_kind);
52
53 self.objects.insert(object_kind, vtable);
54 }
55
56 pub fn register_operation(
57 &mut self,
58 object_kind: &'static str,
59 operation_name: &'static str,
60 vtable: OperationVTable,
61 ) {
62 trace!(
63 "Registering operation metadata for {}::{}",
64 object_kind,
65 operation_name
66 );
67
68 self.operations.insert(
69 ObjectOperationPair {
70 object_kind,
71 operation_name,
72 },
73 vtable,
74 );
75 }
76
77 pub fn register_setting(
78 &mut self,
79 object_kind: &'static str,
80 setting_name: &'static str,
81 vtable: SettingVtable,
82 ) {
83 trace!("Registering setting {}::{}", object_kind, setting_name);
84
85 self.settings.insert(
86 ObjectSettingPair {
87 object_kind,
88 setting_name,
89 },
90 vtable,
91 );
92 }
93
94 pub fn register_value(
95 &mut self,
96 object_kind: &'static str,
97 value_name: &'static str,
98 vtable: ValueVTable,
99 ) {
100 trace!("Registering value {}::{}", object_kind, value_name);
101
102 self.values.insert(
103 ObjectValuePair {
104 object_kind,
105 value_name,
106 },
107 vtable,
108 );
109 }
110 }
111
112 #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
113 pub struct ObjectOperationPair<'s> {
114 pub object_kind: &'s str,
115 pub operation_name: &'s str,
116 }
117
118 impl<'s> ObjectOperationPair<'s> {
119 pub fn new(object_kind: &'s str, operation_name: &'s str) -> Self {
120 Self {
121 object_kind,
122 operation_name,
123 }
124 }
125 }
126
127 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
128 pub struct ObjectSettingPair<'s> {
129 pub object_kind: &'s str,
130 pub setting_name: &'s str,
131 }
132
133 impl<'s> ObjectSettingPair<'s> {
134 pub fn new(object_kind: &'s str, setting_name: &'s str) -> Self {
135 Self {
136 object_kind,
137 setting_name,
138 }
139 }
140 }
141
142 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
143 pub struct ObjectValuePair<'s> {
144 pub object_kind: &'s str,
145 pub value_name: &'s str,
146 }
147
148 impl<'s> ObjectValuePair<'s> {
149 pub fn new(object_kind: &'s str, value_name: &'s str) -> Self {
150 Self {
151 object_kind,
152 value_name,
153 }
154 }
155 }
156
157 #[derive(Clone, Copy)]
158 #[repr(C)]
159 pub struct PluginState {
160 pub inner: *mut (),
161 }
162
163 unsafe impl Send for PluginState {}
164 unsafe impl Sync for PluginState {}
165
166 impl PluginState {
167 pub unsafe fn transmute_owned<T>(&mut self) -> Box<T> {
168 Box::from_raw(self.inner as *mut T)
169 }
170
171 pub unsafe fn transmute_ref<T>(&self) -> &T {
172 let ptr: *const T = transmute(self.inner);
173
174 ptr.as_ref().unwrap()
175 }
176 }
177
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
191 pub fn null() -> Self {
192 Self { inner: null_mut() }
193 }
194 }
195
196 pub struct Runtime {
197 plugins: Vec<(PluginMeta, PluginHandle)>,
198 handlers: RuntimeHandlers,
199 }
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
214 impl Runtime {
215 pub fn new() -> Box<Self> {
216 Box::new(Self {
217 plugins: vec![],
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(),
229 }
230 }
231
232 pub fn insert_plugin(&mut self, plugin: PluginHandle) {
233 let _guard = debug_span!("inserting plugin", meta = debug(&plugin.meta)).entered();
234
235 for (pair, callback) in &plugin.initialization.operation_handlers {
236 let _guard =
237 trace_span!("processing operation handler callbacks", pair = debug(pair)).entered();
238
239 if self
240 .handlers
241 .operation_handlers
242 .insert(*pair, (RuntimeDomain::from_plugin(&plugin), *callback))
243 .is_some()
244 {
245 warn!("Warning! Insertion of handler for overwrote a previous handler.")
246 }
247
248 trace!("Insertion of operation handler successful")
249 }
250
251 for (pair, callback) in &plugin.initialization.value_getters {
252 let _guard =
253 trace_span!("processing value getter callbacks", pair = debug(pair)).entered();
254
255 if self
256 .handlers
257 .value_getters
258 .insert(*pair, (RuntimeDomain::from_plugin(&plugin), *callback))
259 .is_some()
260 {
261 warn!("Warning! Insertion of handler for overwrote a previous handler.")
262 }
263
264 trace!("Insertion of operation handler successful")
265 }
266
267 for (pair, callback) in &plugin.initialization.setting_getters {
268 let _guard =
269 trace_span!("processing setting getter callbacks", pair = debug(pair)).entered();
270
271 if self
272 .handlers
273 .setting_getters
274 .insert(*pair, (RuntimeDomain::from_plugin(&plugin), *callback))
275 .is_some()
276 {
277 warn!("Warning! Insertion of setting handler for overwrote a previous handler.")
278 }
279
280 trace!("Insertion of setting handler successful")
281 }
282 }
283
284 pub fn init(self: Box<Self>) {
285 unsafe { giterated_static_runtime::initialize_runtime(Box::into_raw(self).cast::<()>()) }
286 }
287
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);
297
298 // let state = self.state(operation_state);
299
300 // rules.handle(&state, object, operation_payload).await
301 // }
302
303 pub fn handle_typed<O: GiteratedObject, D: GiteratedOperation<O>>(
304 &self,
305 _object: O,
306 _operation: D,
307 ) -> Result<D::Success, OperationError<D::Failure>> {
308 todo!()
309 }
310 }
311
312 #[derive(Default)]
313 pub struct RuntimeHandlers {
314 operation_handlers:
315 HashMap<ObjectOperationPair<'static>, (RuntimeDomain, OperationHandlerCallback)>,
316 value_getters: HashMap<ObjectValuePair<'static>, (RuntimeDomain, ValueGetterCallback)>,
317 setting_getters: HashMap<ObjectSettingPair<'static>, (RuntimeDomain, SettingGetterCallback)>,
318 value_change: HashMap<ObjectValuePair<'static>, (RuntimeDomain, ValueChangeCallback)>,
319 setting_change: HashMap<ObjectSettingPair<'static>, (RuntimeDomain, SettingChangeCallback)>,
320 }
321
322 unsafe impl Send for RuntimeHandlers {}
323 unsafe impl Sync for RuntimeHandlers {}
324
325 impl RuntimeHandlers {
326 pub fn operation_handler(
327 &mut self,
328 pair: ObjectOperationPair<'static>,
329 handler: OperationHandlerCallback,
330 domain: RuntimeDomain,
331 ) {
332 trace!(
333 "Inserting operation handler for {}::{}",
334 pair.object_kind,
335 pair.operation_name
336 );
337
338 // There can only be one handler per operation (at least for now?), send a warning if
339 // a newly registered handler overwrites the previous handler.
340 if self
341 .operation_handlers
342 .insert(pair, (domain, handler))
343 .is_some()
344 {
345 debug!("Warning! A newly inserted operation handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.operation_name);
346 }
347 }
348
349 pub fn value_getter(
350 &mut self,
351 pair: ObjectValuePair<'static>,
352 handler: ValueGetterCallback,
353 domain: RuntimeDomain,
354 ) {
355 trace!(
356 "Inserting value getter for {}::{}",
357 pair.object_kind,
358 pair.value_name
359 );
360
361 if self.value_getters.insert(pair, (domain, handler)).is_some() {
362 debug!(
363 "Warning! A newly inserted value getter for {}::{} overwrites a previous handler.",
364 pair.object_kind, pair.value_name
365 );
366 }
367 }
368
369 pub fn setting_getter(
370 &mut self,
371 pair: ObjectSettingPair<'static>,
372 handler: SettingGetterCallback,
373 domain: RuntimeDomain,
374 ) {
375 trace!(
376 "Inserting setting getter for {}::{}",
377 pair.object_kind,
378 pair.setting_name
379 );
380
381 if self
382 .setting_getters
383 .insert(pair, (domain, handler))
384 .is_some()
385 {
386 debug!("Warning! A newly inserted setting getter for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name);
387 }
388 }
389
390 pub fn value_change(
391 &mut self,
392 pair: ObjectValuePair<'static>,
393 handler: ValueChangeCallback,
394 domain: RuntimeDomain,
395 ) {
396 trace!(
397 "Inserting value change handler for {}::{}",
398 pair.object_kind,
399 pair.value_name
400 );
401
402 if self.value_change.insert(pair, (domain, handler)).is_some() {
403 debug!("Warning! A newly inserted value change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.value_name);
404 panic!("Not intended");
405 }
406 }
407
408 pub fn setting_change(
409 &mut self,
410 pair: ObjectSettingPair<'static>,
411 handler: SettingChangeCallback,
412 domain: RuntimeDomain,
413 ) {
414 trace!(
415 "Inserting setting change handler for {}::{}",
416 pair.object_kind,
417 pair.setting_name
418 );
419
420 if self
421 .setting_change
422 .insert(pair, (domain, handler))
423 .is_some()
424 {
425 debug!("Warning! A newly inserted setting change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name);
426 panic!("Not intended");
427 }
428 }
429 }
430
431 impl RuntimeHandlers {
432 pub fn handle_operation<'o>(
433 &'o self,
434 object_kind: &'o str,
435 operation_name: &'o str,
436 ) -> OperationHandlerRules<'o> {
437 OperationHandlerRules::new(object_kind, operation_name, self)
438 }
439 }
440
441 pub struct RuntimeDomain {
442 plugin: PluginHandle,
443 }
444
445 impl RuntimeDomain {
446 pub fn from_plugin(plugin: &PluginHandle) -> Self {
447 Self {
448 plugin: plugin.clone(),
449 }
450 }
451
452 pub fn object_vtable(&self, object_kind: &str) -> Option<ObjectVtable> {
453 self.plugin
454 .initialization
455 .type_metadata
456 .objects
457 .get(object_kind)
458 .copied()
459 }
460
461 pub fn operation_vtable(
462 &self,
463 object_kind: &str,
464 operation_name: &str,
465 ) -> Option<OperationVTable> {
466 self.plugin
467 .initialization
468 .type_metadata
469 .operations
470 .get(&ObjectOperationPair::new(object_kind, operation_name))
471 .copied()
472 }
473
474 pub fn setting_vtable(&self, object_kind: &str, setting_name: &str) -> Option<SettingVtable> {
475 self.plugin
476 .initialization
477 .type_metadata
478 .settings
479 .get(&ObjectSettingPair::new(object_kind, setting_name))
480 .copied()
481 }
482
483 pub fn value_vtable(&self, object_kind: &str, value_name: &str) -> Option<ValueVTable> {
484 self.plugin
485 .initialization
486 .type_metadata
487 .values
488 .get(&ObjectValuePair::new(object_kind, value_name))
489 .copied()
490 }
491 }
492
493 #[derive(Clone, Debug)]
494 pub struct PluginMeta {
495 pub name: String,
496 pub version: Version,
497 }
498
499 #[repr(C)]
500 pub struct FFIPluginMeta {
501 pub name: *const u8,
502 pub name_len: usize,
503 pub version: *const u8,
504 pub version_len: usize,
505 }
506
507 pub struct RuntimePlugin {
508 handle: PluginHandle,
509 type_metadata: Arc<TypeMetadata>,
510 }
511
512 impl RuntimePlugin {
513 pub fn plugin_meta(&self) -> PluginMeta {
514 let meta = unsafe { self.handle.raw.plugin_meta() };
515
516 let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) };
517 let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) };
518
519 let name = std::str::from_utf8(name).unwrap();
520 let version = std::str::from_utf8(version).unwrap();
521
522 PluginMeta {
523 name: String::from(name),
524 version: Version::parse(version).unwrap(),
525 }
526 }
527 }
528