2017-02-16 01:05:33 -06:00
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 ;
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 ;
2017-02-16 01:05:33 -06:00
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 > ) ;
2017-02-16 02:00:38 -06:00
types . insert ( " random " , RandomModule ::new as fn ( & Table ) -> Box < Module > ) ;
2017-02-19 04:49:06 -06:00
types . insert ( " pvn " , PvnModule ::new as fn ( & Table ) -> Box < Module > ) ;
2017-02-22 23:40:30 -06:00
types . insert ( " echobox " , EchoboxModule ::new as fn ( & Table ) -> Box < Module > ) ;
2017-02-16 01:05:33 -06:00
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 )
}
}