2022-06-20 21:22:45 +00:00
|
|
|
use std::{fs, sync::Arc};
|
2022-06-04 11:58:21 +00:00
|
|
|
|
|
|
|
use libloading::{Library, Symbol};
|
|
|
|
use log::{debug, trace};
|
|
|
|
|
2022-06-20 21:22:45 +00:00
|
|
|
use crate::{commands, plugins::Registrar};
|
2022-06-04 11:58:21 +00:00
|
|
|
|
2022-06-20 21:22:45 +00:00
|
|
|
use super::{PluginManager, PluginManagerType};
|
2022-06-16 17:31:09 +00:00
|
|
|
|
2022-06-05 20:10:23 +00:00
|
|
|
/// Plugins and Commands loader
|
2022-06-20 21:22:45 +00:00
|
|
|
pub fn loader() -> anyhow::Result<PluginManagerType> {
|
2022-06-04 11:58:21 +00:00
|
|
|
// get path to .so lib from command argument
|
|
|
|
let config_dir = "./plugins";
|
|
|
|
let paths = fs::read_dir(config_dir)?;
|
|
|
|
|
2022-06-20 21:22:45 +00:00
|
|
|
// create a plugin manager
|
2022-06-04 11:58:21 +00:00
|
|
|
let mut plugin_manager = PluginManager::new();
|
|
|
|
|
2022-06-04 18:10:21 +00:00
|
|
|
// register default commands
|
|
|
|
for command in commands::register_commands() {
|
2022-06-20 21:22:45 +00:00
|
|
|
plugin_manager.commands.push(command)
|
2022-06-04 18:10:21 +00:00
|
|
|
}
|
|
|
|
|
2022-06-04 11:58:21 +00:00
|
|
|
// for all plugin in directory
|
|
|
|
for path in paths {
|
|
|
|
// get library file path
|
|
|
|
let path = path?.path();
|
|
|
|
|
2022-06-05 14:08:13 +00:00
|
|
|
let plugin_path = path.to_str().unwrap_or("unknown");
|
|
|
|
|
|
|
|
// log debug info
|
|
|
|
debug!("Loading plugin `{}`", plugin_path);
|
|
|
|
|
2022-06-04 11:58:21 +00:00
|
|
|
// loading library with .so is unsafe
|
|
|
|
unsafe {
|
|
|
|
// load library
|
|
|
|
// Box::new and Box::leak must be there because if it isn't there it throws a segmentation fault
|
2022-06-05 14:08:13 +00:00
|
|
|
let lib = Box::leak(Box::new(Library::new(&path)?));
|
2022-06-04 11:58:21 +00:00
|
|
|
|
|
|
|
// get `plugin_entry` from library
|
2022-06-05 14:08:13 +00:00
|
|
|
trace!("Finding symbol `plugin_entry` in `{}`", plugin_path);
|
2022-06-20 21:22:45 +00:00
|
|
|
let func: Symbol<unsafe extern "C" fn(&mut dyn Registrar) -> ()> =
|
|
|
|
lib.get(b"plugin_entry")?;
|
2022-06-04 11:58:21 +00:00
|
|
|
|
2022-06-05 14:08:13 +00:00
|
|
|
// execute initial plugin function
|
|
|
|
trace!("Running `plugin_entry(...)` in plugin `{}`", plugin_path);
|
2022-06-20 21:22:45 +00:00
|
|
|
func(&mut plugin_manager);
|
2022-06-04 11:58:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-20 21:22:45 +00:00
|
|
|
// return a `PluginManager`
|
|
|
|
Ok(Arc::new(plugin_manager))
|
2022-06-04 11:58:21 +00:00
|
|
|
}
|