use { file_funcs, FuncMapper, Payload, string };
use error::*;
use func::Func;
use libflo_module::{ ModuleMapper, PathResolver, self_module_name };
use serialization::{ Dll, Func as SerialFunc };
use sharedlib::LibArc;
use std::collections::HashMap;
pub unsafe fn load(
module_mapper: &ModuleMapper,
path_resolver: &PathResolver,
) -> Result<Payload> {
let my_id = module_mapper.get(self_module_name())?;
let func_file_name = string::func_file_name();
let mut pre_func_list = Vec::new();
let mut pre_func_map = module_mapper.get_raw_map().into_iter().map(|_| None).collect();
for (module_name, module_id) in module_mapper.get_raw_map() {
if let Some(dll_json_path) = path_resolver.try_find_submodule_file_path(func_file_name, *module_id, my_id)? {
let dll_json = file_funcs::dll_from_path(dll_json_path)?;
create_funcs(dll_json, module_name, *module_id, my_id, &path_resolver, &mut pre_func_list, &mut pre_func_map)?;
};
}
let func_mapper = FuncMapper::new(pre_func_map, pre_func_list);
let result =
Payload::new(
func_mapper,
);
Ok(result)
}
unsafe fn create_funcs(
dll: Dll,
module_name: &String,
module_id: usize,
self_module_id: usize,
path_resolver: &PathResolver,
pre_func_list: &mut Vec<Func>,
pre_func_map: &mut Vec<Option<HashMap<String, usize>>>,
) -> Result<()> {
let (path, funcs) = dll.destructure();
let dll_full_path = path_resolver.find_submodule_file_path(path, module_id, self_module_id)?;
let library = LibArc::new(dll_full_path.clone())
.chain_err(|| ErrorKind::DllCouldNotLoad(dll_full_path, module_id))?;
for func in funcs {
create_func(func, &library, module_name, module_id, pre_func_list, pre_func_map)?;
}
Ok(())
}
unsafe fn create_func(
func: SerialFunc,
library: &LibArc,
module_name: &String,
module_id: usize,
pre_func_list: &mut Vec<Func>,
pre_func_map: &mut Vec<Option<HashMap<String, usize>>>,
) -> Result<()> {
let (func_type, has_input, has_output, symbol, use_as) = func.destructure();
let name = use_as.unwrap_or(symbol.clone());
let func_id = pre_func_list.len();
if let Some(&None) = pre_func_map.get(module_id) {
pre_func_map[module_id] = Some(HashMap::new());
}
if let Some(&mut Some(ref mut inner_func_map)) = pre_func_map.get_mut(module_id) {
if let Some(_) = inner_func_map.insert(name.clone(), func_id) {
return Err(ErrorKind::FuncLoadNameCollision(name, module_name.clone()).into());
}
}
let has_input = has_input.unwrap_or(false);
let has_output = has_output.unwrap_or(false);
let func = Func::new(library, &symbol, func_type, has_input, has_output)?;
pre_func_list.push(func);
Ok(())
}