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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//! This is the module containing all the definitions of the structs and trait used by the host system.
//! We refer as `Host system` meaning the part of the application that is responsible to load, manage and call plugins.
//! The traits makes no distinction between dynamic and static dispatch, so restricting to a carticular case is a job of the developer.
use System;
// Currently the default global allocator is unspecified. Libraries, however,
// like cdylibs and staticlibs are guaranteed to use the System by default.
static ALLOCATOR: System = System;
/// Allow the plugin manager the possibility to load packages.
/// So a struct that doesn't implement this trait won't ba able to load plugins.
/// You may don't want to implement this trait to have more control over loaded plugins,
/// so once the plugins are loaded no more plugins can be loaded from other functions.
///
/// ```
/// use aanyx::host::PluginManagerLoad;
/// # use aanyx::host::PluginManagerGet;
/// use aanyx::host::PluginLoader;
/// use std::collections::HashMap;
///
/// struct MyPluginLoader { name: String }
/// impl PluginLoader<String, String> for MyPluginLoader {
/// fn into_plugin( self ) -> (String, String) {
/// // Simulates loading somethig and perform some calculations
/// let mut plugin = self.name.clone();
/// plugin.push_str("__");
///
/// ( self.name.clone(), plugin)
/// }
/// }
///
/// struct MyPluginManager { plugins: HashMap<String, String>}
/// impl PluginManagerLoad<String, String, ()> for MyPluginManager {
/// fn load( &mut self, new_plugin: impl PluginLoader<String, String>) -> Result<(), ()>{
/// let (id, plugin) = new_plugin.into_plugin();
/// self.plugins.insert( id, plugin );
/// Ok(())
/// }
/// }
/// # impl PluginManagerGet<String, String>for MyPluginManager {
/// # fn get( &self, plugin: &String ) -> Option<&String>{
/// # self.plugins.get( plugin )
/// # }
/// # }
///
/// let plugin1 = MyPluginLoader { name: String::from("Plugin_1")};
/// let mut plugin_manager = MyPluginManager { plugins: HashMap::new() };
///
/// plugin_manager.load( plugin1 );
/// plugin_manager.load( MyPluginLoader { name: String::from("Plugin_2")} );
///
/// # assert_eq!( plugin_manager.get( &String::from("Plugin_1") ), Some(&String::from("Plugin_1__")) );
/// # assert_eq!( plugin_manager.get( &String::from("Plugin_2") ), Some(&String::from("Plugin_2__")) );
///
/// ```
/// ## Safety
/// All functions are marked safe although some implementation may use `libloading` or other unsafe crates.
/// The [`PluginManagerLoad`] should then take care of the unsafeties itself depending on what crates and methods it uses.
/// This allows to make the trait also available for static plugins that doesn't require runtime loading.
/// Get the plugins loaded in the PluginManager.
/// This trait is independent from the loader, in fact you may want to implement a plugin manager that serves
/// only as container for a group of plugins and extract the required ones.
/// ```
/// use aanyx::host::PluginManagerGet;
/// use std::collections::HashMap;
///
/// struct MyPluginManager { plugins: HashMap<String, String>}
/// impl PluginManagerGet<String, String> for MyPluginManager {
/// fn get( &self, plugin: &String ) -> Option<&String> {
/// self.plugins.get( plugin )
/// }
/// }
///
/// impl MyPluginManager {
/// pub fn new() -> Self {
/// let mut plugins = HashMap::new();
/// plugins.insert( String::from("PluginName"), String::from("PlugintType") );
/// Self { plugins }
/// }
/// }
///
/// let plugin_manager = MyPluginManager::new();
/// assert_eq!( plugin_manager.get( &String::from("PluginName") ), Some(&String::from("PlugintType")))
/// ```
/// Unload a plugin
/// ```
/// use aanyx::host::{PluginManagerUnload};
/// use std::collections::HashMap;
/// struct MyPluginManager { pub plugins: HashMap<String, String>}
///
/// impl PluginManagerUnload<String, String, ()> for MyPluginManager {
/// fn unload( &mut self, old_plugin: &String ) -> Result<(), ()>{
/// assert!( self.plugins.remove( old_plugin ).is_some() );
/// Ok(())
/// }
/// }
///
/// let mut my_plugin_manager = MyPluginManager { plugins: HashMap::new() };
/// my_plugin_manager.plugins.insert( String::from("MyPlugin"), String::from("Plugin__"));
/// assert!( my_plugin_manager.unload ( &String::from("MyPlugin") ).is_ok());
///
/// ```
/// Allow the manager to overwrite a loaded plugin with another version of it
/// ```
/// use aanyx::host::{PluginManagerUnload, PluginManagerLoad, PluginManagerReload, PluginLoader};
/// use std::collections::HashMap;
///
/// struct MyPluginLoader { name: String }
/// impl PluginLoader<String, String> for MyPluginLoader {
/// fn into_plugin( self ) -> (String, String) {
/// // Simulates loading somethig and perform some calculations
/// let mut plugin = self.name.clone();
/// plugin.push_str("__");
///
/// ( self.name.clone(), plugin)
/// }
/// }
///
/// struct MyPluginManager { pub plugins: HashMap<String, String>}
/// impl PluginManagerLoad<String, String, ()> for MyPluginManager {
/// fn load( &mut self, new_plugin: impl PluginLoader<String, String>) -> Result<(), ()>{
/// let (id, plugin) = new_plugin.into_plugin();
/// self.plugins.insert( id, plugin );
/// Ok(())
/// }
/// }
/// impl PluginManagerUnload<String, String, ()> for MyPluginManager {
/// fn unload( &mut self, plugin: &String ) -> Result<(), ()>{
/// self.plugins.remove( plugin );
/// Ok(())
/// }
/// }
///
/// impl PluginManagerReload<String, String, ()> for MyPluginManager {
/// fn reload( &mut self, plugin: &String ) -> Result<(), ()>{
/// let mut new_plugin = MyPluginLoader { name: plugin.to_string() }.into_plugin();
/// new_plugin.1.push_str("reloaded");
/// *self.plugins.get_mut( plugin ).unwrap() = new_plugin.1;
/// Ok(())
/// }
/// }
///
/// let mut my_plugin_manager = MyPluginManager { plugins: HashMap::new() };
/// let my_plugin1 = MyPluginLoader { name: String::from("MyPlugin")};
/// my_plugin_manager.load( my_plugin1 );
///
/// assert_eq!( my_plugin_manager.plugins.get( "MyPlugin" ).unwrap(), &String::from("MyPlugin__"));
///
/// my_plugin_manager.reload( &String::from("MyPlugin") );
///
/// assert_eq!( my_plugin_manager.plugins.get( "MyPlugin" ).unwrap(), &String::from("MyPlugin__reloaded"));
/// ```