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

ambee/giterated

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

So. Much. Work.

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨b05f964

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