1use dynamic_reload::{DynamicReload, Lib, Symbol, Search, PlatformName, UpdateState};
2use std::collections::BTreeMap;
3use std::sync::Arc;
4use std::time::Duration;
5use std::thread;
6
7pub struct Plugins {
8 pub plugins: Vec<Arc<Lib>>,
9}
10
11impl Plugins {
12 fn add_plugin(&mut self, lib: &Arc<Lib>) {
13 self.plugins.push(lib.clone());
14 }
16
17 fn clear(&mut self){
18 self.plugins.clear();
19 }
20
21 fn get_plugins(&mut self) -> Vec<Arc<Lib>>{
22 self.plugins.clone()
23 }
24
25 fn get_plugin_count(&self) -> usize {
26 self.plugins.len()
27 }
28
29 fn unload_plugin(&mut self, lib: &Arc<Lib>) {
30
31 for i in (0..self.plugins.len()).rev() {
32 if &self.plugins[i] == lib {
33 self.plugins.swap_remove(i);
34 }
35 }
36 }
37
38 fn reload_plugin(&mut self, lib: &Arc<Lib>) {
39 Self::add_plugin(self, lib);
40 }
41
42 pub fn reload_callback(&mut self, state: UpdateState, lib: Option<&Arc<Lib>>) {
44 match state {
45 UpdateState::Before => Self::unload_plugin(self, lib.unwrap()),
46 UpdateState::After => Self::reload_plugin(self, lib.unwrap()),
47 UpdateState::ReloadFailed(_) => println!("Failed to reload"),
48 }
49 }
50}
51
52pub struct PluginManager<'a> {
53 reload_handler: DynamicReload<'a>,
54 plugins: Plugins,
55}
56
57impl <'a> Drop for PluginManager<'a> {
58 fn drop(&mut self){
59 self.unload();
61 }
62}
63
64impl<'a> PluginManager<'a> {
65 pub fn new(lib_dir_pathes: Vec<&'a str>, cache_dir_path: &'a str) -> PluginManager<'a>{
66 PluginManager {
67 reload_handler: DynamicReload::new(Some(lib_dir_pathes),
68 None,
69 Search::Backwards),
70 plugins: Plugins { plugins: Vec::new() },
71 }
72 }
73
74 pub fn add_plugin(&mut self, name: &str) -> std::result::Result<i32, &str>{
75 match &self.reload_handler.add_library(name, PlatformName::Yes) {
76 Ok(lib) => {
77 self.plugins.add_plugin(&lib);
78 Ok(1)
79 },
80 Err(e) => {
81 println!("Unable to load dynamic lib {}, err {:?}", name, e);
82 Err("Warning: Unable to load dynamic lib!")
83 }
84 }
85 }
86
87 pub fn get_plugin_count(&self) -> usize {
88 self.plugins.get_plugin_count()
89 }
90
91 pub fn get_plugin(&mut self) -> Arc<Lib>{
92 self.plugins.plugins[0].clone()
93 }
94
95 pub fn get_plugins(&mut self) -> Vec<Arc<Lib>>{
96 self.plugins.plugins.clone()
97 }
98
99 pub fn refresh_plugins(&mut self){
100 &self.reload_handler.update(Plugins::reload_callback, &mut self.plugins);
101 }
102
103 pub fn unload(&mut self) -> std::result::Result<i32, &'static str>{
104 debug!("Unloading plugins");
105
106 for plugin in self.plugins.get_plugins() {
107 trace!("Firing on_plugin_unload for {:?}", plugin.original_path.as_ref());
108 }
110
111 self.plugins.clear();
112 Ok(1)
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::PluginManager;
119 use dynamic_reload::{Lib,Symbol};
120
121 #[ignore]
122 #[test]
123 fn test_01() {
124 assert!(true)
125 }
126}