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