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/handle.rs⁩ - ⁨7645⁩ bytes
Raw
1 use std::{collections::HashMap, marker::PhantomData, sync::Arc};
2
3 use anyhow::Error;
4 use dlopen2::wrapper::Container;
5 use giterated_abi::{
6 callback::CallbackPtr,
7 vtable::{operation::Operation, Object, Setting, VTable, Value},
8 };
9 use giterated_models::operation::OperationState;
10 use semver::Version;
11 use tracing::{debug, trace};
12
13 use crate::{
14 callback::{
15 OperationHandlerCallback, RuntimeState, SettingGetterCallback, ValueGetterCallback,
16 },
17 new_stack::{
18 ObjectOperationPair, ObjectSettingPair, ObjectValuePair, PluginMeta, PluginState,
19 TypeMetadata,
20 },
21 vtable::Initialization,
22 GiteratedPluginApi,
23 };
24
25 #[derive(Clone)]
26 pub struct PluginHandle {
27 pub meta: PluginMeta,
28 pub raw: Arc<Container<GiteratedPluginApi>>,
29 pub domain_metadata: Arc<TypeMetadata>,
30 pub state: PluginState,
31 }
32
33 unsafe impl Send for PluginHandle {}
34 unsafe impl Sync for PluginHandle {}
35
36 impl PluginHandle {
37 pub fn from_dylib(path: &str) -> Result<Self, CreationError> {
38 let mut handle = unsafe { Container::load(path) }?;
39
40 // Initialize the raw handle
41 let init_state =
42 Self::initialize_raw_handle(&mut handle, &unsafe { RuntimeState::from_static() })?;
43
44 let metadata = Self::get_meta(&mut handle)?;
45
46 let initalization = Self::initialize_registration(&mut handle)?;
47
48 let type_metadata = Box::new(initalization.type_metadata.clone());
49
50 unsafe { handle.load_type_metadata(unsafe { Box::into_raw(type_metadata).cast() }) };
51
52 trace!(
53 "Loaded plugin {} (Version: {})",
54 metadata.name,
55 metadata.version
56 );
57
58 Ok(Self {
59 raw: Arc::new(handle),
60 meta: metadata,
61 state: init_state,
62 domain_metadata: todo!(),
63 })
64 }
65
66 /// Builds the Plugin's Substack.
67 ///
68 /// Builds the Plugin into a substack, which can then be provided to the Giterated Runtime.
69 pub fn build_substack(&mut self) -> Result<(), Error> {
70 todo!()
71 }
72
73 fn get_meta(handle: &mut Container<GiteratedPluginApi>) -> Result<PluginMeta, CreationError> {
74 let meta = unsafe { handle.plugin_meta() };
75
76 let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) };
77 let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) };
78
79 let name = std::str::from_utf8(name).unwrap();
80 let version = std::str::from_utf8(version).unwrap();
81
82 Ok(PluginMeta {
83 name: String::from(name),
84 version: Version::parse(version).unwrap(),
85 })
86 }
87
88 pub fn initialize_registration(
89 handle: &mut Container<GiteratedPluginApi>,
90 ) -> Result<PluginInitializationState, CreationError> {
91 debug!("Initializing plugin registration...");
92 let mut builder = PluginInitializationTable::default();
93
94 // SAFETY: The lifetime of the returned type is only valid as long
95 // as the builder that returned it lives
96 let func_table = unsafe { builder.func_table() };
97
98 let state = Box::new(PluginInitializationState::new());
99
100 unsafe { handle.load_initialization_vtable(&func_table) };
101 let state = unsafe { handle.initialize_registration(Box::into_raw(state)) };
102
103 debug!("Plugin handle initialized!");
104 Ok(unsafe { *Box::from_raw(state) })
105 }
106
107 fn initialize_raw_handle(
108 handle: &mut Container<GiteratedPluginApi>,
109 runtime_state: &RuntimeState,
110 ) -> Result<PluginState, CreationError> {
111 debug!("Initializing plugin handle...");
112
113 let state = unsafe { handle.initialize(runtime_state) };
114
115 debug!("Plugin handle initialized!");
116
117 Ok(state)
118 }
119 }
120
121 #[derive(Debug, thiserror::Error)]
122 pub enum CreationError {
123 #[error("an error occured opening the library {0}")]
124 LoadingLibrary(#[from] dlopen2::Error),
125 }
126
127 pub struct PluginSubstackBuilder {}
128
129 #[derive(Default)]
130 pub struct PluginInitializationState {
131 pub type_metadata: TypeMetadata,
132 pub operation_handlers:
133 HashMap<ObjectOperationPair<'static>, CallbackPtr<OperationHandlerCallback>>,
134 pub value_getters: HashMap<ObjectValuePair<'static>, CallbackPtr<ValueGetterCallback>>,
135 pub setting_getters: HashMap<ObjectSettingPair<'static>, CallbackPtr<SettingGetterCallback>>,
136 }
137
138 impl PluginInitializationState {
139 pub fn new() -> Self {
140 Self::default()
141 }
142 }
143
144 #[derive(Default)]
145 pub struct PluginInitializationTable<'a> {
146 _marker: PhantomData<&'a ()>,
147 }
148
149 impl<'a> PluginInitializationTable<'a> {
150 pub unsafe fn func_table(&mut self) -> &'static VTable<Initialization> {
151 VTable::new(&Initialization {
152 register_object,
153 register_operation,
154 register_setting,
155 register_value,
156 operation_handler,
157 value_getter,
158 setting_getter,
159 })
160 }
161 }
162
163 unsafe extern "C" fn register_object(
164 state: *mut PluginInitializationState,
165 object_kind: &'static str,
166 vtable: &'static VTable<Object>,
167 ) {
168 let mut state = Box::from_raw(state);
169
170 state.type_metadata.register_object(object_kind, vtable);
171
172 Box::into_raw(state);
173 }
174
175 unsafe extern "C" fn register_operation(
176 state: *mut PluginInitializationState,
177 object_kind: &'static str,
178 operation_name: &'static str,
179 vtable: &'static VTable<Operation>,
180 ) {
181 let mut state = Box::from_raw(state);
182
183 state
184 .type_metadata
185 .register_operation(object_kind, operation_name, vtable);
186
187 Box::into_raw(state);
188 }
189
190 unsafe extern "C" fn register_setting(
191 state: *mut PluginInitializationState,
192 object_kind: &'static str,
193 setting_name: &'static str,
194 vtable: &'static VTable<Setting>,
195 ) {
196 let mut state = Box::from_raw(state);
197
198 state
199 .type_metadata
200 .register_setting(object_kind, setting_name, vtable);
201
202 Box::into_raw(state);
203 }
204
205 unsafe extern "C" fn register_value(
206 state: *mut PluginInitializationState,
207 object_kind: &'static str,
208 value_name: &'static str,
209 vtable: &'static VTable<Value>,
210 ) {
211 let mut state = Box::from_raw(state);
212
213 state
214 .type_metadata
215 .register_value(object_kind, value_name, vtable);
216
217 Box::into_raw(state);
218 }
219
220 unsafe extern "C" fn operation_handler(
221 state: *mut PluginInitializationState,
222 object_kind: &'static str,
223 operation_name: &'static str,
224 handler: CallbackPtr<OperationHandlerCallback>,
225 ) {
226 let mut state = Box::from_raw(state);
227
228 trace!("Operation handler for {}::{}", object_kind, operation_name);
229
230 state.operation_handlers.insert(
231 ObjectOperationPair::new(object_kind, operation_name),
232 handler,
233 );
234
235 Box::into_raw(state);
236 }
237
238 unsafe extern "C" fn value_getter(
239 state: *mut PluginInitializationState,
240 object_kind: &'static str,
241 value_name: &'static str,
242 handler: CallbackPtr<ValueGetterCallback>,
243 ) {
244 let mut state = Box::from_raw(state);
245
246 trace!("Value getter for {}::{}", object_kind, value_name);
247
248 state
249 .value_getters
250 .insert(ObjectValuePair::new(object_kind, value_name), handler);
251
252 Box::into_raw(state);
253 }
254
255 unsafe extern "C" fn setting_getter(
256 state: *mut PluginInitializationState,
257 object_kind: &'static str,
258 setting_name: &'static str,
259 handler: CallbackPtr<SettingGetterCallback>,
260 ) {
261 let mut state = Box::from_raw(state);
262
263 trace!("Setting getter for {}::{}", object_kind, setting_name);
264
265 state
266 .setting_getters
267 .insert(ObjectSettingPair::new(object_kind, setting_name), handler);
268
269 Box::into_raw(state);
270 }
271