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

ambee/giterated

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

More restructuring

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨10b7b7c

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