99 lines
3.9 KiB
Rust
Raw Normal View History

2017-02-16 01:05:33 -06:00
use std::collections::BTreeMap;
use std::error::Error;
use std::fmt;
use toml::value::Table;
2017-02-16 01:05:33 -06:00
use modules::{Module, EventLoop};
2017-02-16 01:05:33 -06:00
use modules::discord::DiscordModule;
use modules::lua::LuaModule;
use modules::stdin::StdinModule;
use modules::echo::EchoModule;
2017-02-16 02:00:38 -06:00
use modules::random::RandomModule;
2017-02-19 04:49:06 -06:00
use modules::pvn::PvnModule;
2017-02-22 23:40:30 -06:00
use modules::echobox::EchoboxModule;
use modules::autolink::AutolinkModule;
use modules::logger::LoggerModule;
2018-02-25 04:47:04 -06:00
use modules::irc::IrcHandler;
2017-02-16 01:05:33 -06:00
use std::sync::{Arc, Mutex};
2017-02-16 01:05:33 -06:00
pub struct ModuleLoader {
types: BTreeMap<&'static str, fn(&Table, &Table) -> Box<EventLoop>>
2017-02-16 01:05:33 -06:00
}
impl ModuleLoader {
pub fn new () -> ModuleLoader {
let mut types = BTreeMap::new();
types.insert("discord", DiscordModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("lua", LuaModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("stdin", StdinModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("echo", EchoModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("random", RandomModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("pvn", PvnModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("echobox", EchoboxModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("autolink", AutolinkModule::new as fn(&Table, &Table) -> Box<EventLoop>);
types.insert("logger", LoggerModule::new as fn(&Table, &Table) -> Box<EventLoop>);
2018-02-25 04:47:04 -06:00
types.insert("irc", IrcHandler::new as fn(&Table, &Table) -> Box<EventLoop>);
2017-02-16 01:05:33 -06:00
ModuleLoader {
types: types
}
}
pub fn load_from_configuration (&self, configuration: Table) -> Result<BTreeMap<String, Module>, ModuleLoaderError> {
let general_config = configuration.get("general")
.and_then(|value| value.as_table())
.map(|value| value.clone())
.unwrap_or_else(|| BTreeMap::new());
2017-02-26 02:19:46 -06:00
configuration.into_iter().filter(|&(ref key, _)| {
key != "general"
}).map(|(key, value)| {
2017-02-16 01:05:33 -06:00
match value.as_table() {
Some(table) => {
let module = self.load_single_module(&key, &general_config, table)?;
2017-02-16 01:05:33 -06:00
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, general_configuration: &Table, module_configuration: &Table) -> Result<Module, ModuleLoaderError> {
2017-02-16 01:05:33 -06:00
/*
* 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 = module_configuration.get("type")
2017-02-16 01:05:33 -06:00
.and_then(|value| value.as_str())
.unwrap_or(name);
match self.types.get(module_type) {
Some(constructor) => Result::Ok(Module {
module_type: module_type.to_owned(),
config: module_configuration.clone(),
event_loop: constructor(general_configuration, module_configuration),
sender: Mutex::new(None)
}),
2017-02-16 01:05:33 -06:00
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)
}
}