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

ambee/giterated

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

Structure refactoring

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨a8f41ac

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