zula_core/
plug.rs

1use std::{
2    error::Error,
3    ffi::OsStr,
4    ops::{Deref, DerefMut},
5    path::Path, mem::ManuallyDrop,
6};
7
8use libloading::Library;
9
10use crate::ShellState;
11
12///The plugin trait that defines how a plugin object acts.
13pub trait Plugin: Send + Sync {
14    ///The initializer function. Don't mind the `&self` parameter, its a technicallity for this
15    ///trait to be abi-safe.
16    fn init(&self) -> Box<dyn Plugin>;
17    ///Return the display name of your plugin. Due to abi restrictions, this must be a function and
18    ///not an associated constant.
19    fn name(&self) -> &str;
20    ///The "heart" of the plugin; this is called with the syntax `plugin.<name>`.
21    fn call(&self, _state: *mut ShellState) -> Result<(), Box<dyn Error + Send + Sync>> {
22        Ok(())
23    }
24}
25
26///Represents a plugin object. Not very useful outside of internal functions.
27pub struct PluginHook {
28    hook: libloading::Library,
29    obj: ManuallyDrop<Box<dyn Plugin>>,
30    path: String,
31}
32
33impl Deref for PluginHook {
34    type Target = Box<dyn Plugin>;
35
36    fn deref(&self) -> &Self::Target {
37        &self.obj
38    }
39}
40
41impl PluginHook {
42    pub unsafe fn new<S: AsRef<OsStr>>(path: S) -> Result<Self, libloading::Error> {
43        let str_path = OsStr::new(&path)
44            .to_str()
45            .map(|s| s.to_owned())
46            .unwrap_or("".to_owned());
47        let hook = Library::new(path)?;
48        let obj = hook.get::<libloading::Symbol<fn() -> Box<dyn Plugin>>>(b"init")?();
49        Ok(Self {
50            hook,
51            obj: ManuallyDrop::new(obj),
52            path: str_path,
53        })
54    }
55}
56
57impl Drop for PluginHook {
58    fn drop(&mut self) {
59        unsafe { ManuallyDrop::drop(&mut self.obj) };
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use crate::PluginHook;
66
67    #[test]
68    fn drop() {
69        let hook = unsafe { PluginHook::new("/home/jamie/.config/zula/plugins/libtest_plugin.so") }.unwrap();
70    }
71}