73 lines
2.5 KiB
Rust
73 lines
2.5 KiB
Rust
|
use std::collections::BTreeMap;
|
||
|
use std::error::Error;
|
||
|
use std::fmt;
|
||
|
|
||
|
use toml::Table;
|
||
|
|
||
|
use modules::Module;
|
||
|
use modules::discord::DiscordModule;
|
||
|
use modules::lua::LuaModule;
|
||
|
use modules::stdin::StdinModule;
|
||
|
use modules::echo::EchoModule;
|
||
|
|
||
|
pub struct ModuleLoader {
|
||
|
types: BTreeMap<&'static str, fn(&Table) -> Box<Module>>
|
||
|
}
|
||
|
|
||
|
impl ModuleLoader {
|
||
|
pub fn new () -> ModuleLoader {
|
||
|
let mut types = BTreeMap::new();
|
||
|
types.insert("discord", DiscordModule::new as fn(&Table) -> Box<Module>);
|
||
|
types.insert("lua", LuaModule::new as fn(&Table) -> Box<Module>);
|
||
|
types.insert("stdin", StdinModule::new as fn(&Table) -> Box<Module>);
|
||
|
types.insert("echo", EchoModule::new as fn(&Table) -> Box<Module>);
|
||
|
ModuleLoader {
|
||
|
types: types
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn load_from_configuration (&self, configuration: Table) -> Result<BTreeMap<String, Box<Module>>, ModuleLoaderError> {
|
||
|
configuration.into_iter().map(|(key, value)| {
|
||
|
match value.as_table() {
|
||
|
Some(table) => {
|
||
|
let module = self.load_single_module(&key, table)?;
|
||
|
Result::Ok((key, module))
|
||
|
},
|
||
|
None => Result::Err(ModuleLoaderError { message: format!("Bad configuration parameters for module instance: {}. Configuration for a Module must be a table.", key) })
|
||
|
}
|
||
|
}).collect()
|
||
|
}
|
||
|
|
||
|
pub fn load_single_module (&self, name: &str, configuration: &Table) -> Result<Box<Module>, ModuleLoaderError> {
|
||
|
/*
|
||
|
* The Module type defaults to the instance name (in the tenquestionmarks configuration)
|
||
|
* but can explicitly be set by using the special "type" parameter.
|
||
|
*/
|
||
|
let module_type: &str = configuration.get("type")
|
||
|
.and_then(|value| value.as_str())
|
||
|
.unwrap_or(name);
|
||
|
|
||
|
match self.types.get(module_type) {
|
||
|
Some(constructor) => Result::Ok(constructor(configuration)),
|
||
|
None => Result::Err(ModuleLoaderError { message: format!("No such module type: {}", module_type) })
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ModuleLoaderError {
|
||
|
message: String
|
||
|
}
|
||
|
|
||
|
impl Error for ModuleLoaderError {
|
||
|
fn description(&self) -> &str {
|
||
|
&self.message[..]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl fmt::Display for ModuleLoaderError {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||
|
write!(f, "ModuleLoaderError: {}", self.message)
|
||
|
}
|
||
|
}
|