1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use std::{fs, path::Path};
use async_std::task;
use libloading::{Library, Symbol};
use tracing::{info, span, trace, Level};
use crate::{
commands,
plugins::{
manager::{PluginsManager, PluginsManagerType},
prelude::*,
},
};
pub fn loader(plugins_dir: &str) -> anyhow::Result<PluginsManagerType> {
if !Path::new(plugins_dir).exists() {
fs::create_dir_all(plugins_dir)?;
}
let plugins_files = fs::read_dir(plugins_dir)?;
let mut plugins_manager = PluginsManager::new();
plugins_manager.commands = commands::register_commands();
for plugin_path in plugins_files {
let path = plugin_path?.path();
let path_str = path.to_str().unwrap();
let span = span!(Level::TRACE, "", plugin_path = path_str);
let _enter = span.enter();
info!("Loading plugin {}", path_str);
unsafe {
let lib = Box::leak(Box::new(Library::new(&path)?));
trace!("Finding symbol `plugin_entry` in {}", path_str);
let func: Symbol<unsafe extern "C" fn(&mut dyn Registrar) -> ()> =
lib.get(b"plugin_entry")?;
trace!("Running function `plugin_entry` from plugin {}", path_str);
func(&mut plugins_manager);
}
}
for plugin in plugins_manager.plugins.iter() {
task::block_on(async { plugin.on_load().await });
info!("Loaded plugin {}.", plugin.name());
}
Ok(plugins_manager.into())
}