use std::collections::HashMap; use global::GlobalRef; use memory::MemoryRef; use func::FuncRef; use table::TableRef; use module::ModuleRef; use types::{GlobalDescriptor, TableDescriptor, MemoryDescriptor}; use {Error, Signature}; pub trait ImportResolver { fn resolve_func( &self, module_name: &str, field_name: &str, func_type: &Signature, ) -> Result; fn resolve_global( &self, module_name: &str, field_name: &str, global_type: &GlobalDescriptor, ) -> Result; fn resolve_memory( &self, module_name: &str, field_name: &str, memory_type: &MemoryDescriptor, ) -> Result; fn resolve_table( &self, module_name: &str, field_name: &str, table_type: &TableDescriptor, ) -> Result; } pub struct ImportsBuilder<'a> { modules: HashMap, } impl<'a> Default for ImportsBuilder<'a> { fn default() -> Self { Self::new() } } impl<'a> ImportsBuilder<'a> { pub fn new() -> ImportsBuilder<'a> { ImportsBuilder { modules: HashMap::new() } } pub fn with_resolver>( mut self, name: N, resolver: &'a ModuleImportResolver, ) -> Self { self.modules.insert(name.into(), resolver); self } pub fn push_resolver>(&mut self, name: N, resolver: &'a ModuleImportResolver) { self.modules.insert(name.into(), resolver); } pub fn resolver(&self, name: &str) -> Option<&ModuleImportResolver> { self.modules.get(name).cloned() } } impl<'a> ImportResolver for ImportsBuilder<'a> { fn resolve_func( &self, module_name: &str, field_name: &str, signature: &Signature, ) -> Result { self.resolver(module_name).ok_or_else(|| Error::Instantiation(format!("Module {} not found", module_name)) )?.resolve_func(field_name, signature) } fn resolve_global( &self, module_name: &str, field_name: &str, global_type: &GlobalDescriptor, ) -> Result { self.resolver(module_name).ok_or_else(|| Error::Instantiation(format!("Module {} not found", module_name)) )?.resolve_global(field_name, global_type) } fn resolve_memory( &self, module_name: &str, field_name: &str, memory_type: &MemoryDescriptor, ) -> Result { self.resolver(module_name).ok_or_else(|| Error::Instantiation(format!("Module {} not found", module_name)) )?.resolve_memory(field_name, memory_type) } fn resolve_table( &self, module_name: &str, field_name: &str, table_type: &TableDescriptor, ) -> Result { self.resolver(module_name).ok_or_else(|| Error::Instantiation(format!("Module {} not found", module_name)) )?.resolve_table(field_name, table_type) } } pub trait ModuleImportResolver { fn resolve_func( &self, field_name: &str, _signature: &Signature, ) -> Result { Err(Error::Instantiation( format!("Export {} not found", field_name), )) } fn resolve_global( &self, field_name: &str, _global_type: &GlobalDescriptor, ) -> Result { Err(Error::Instantiation( format!("Export {} not found", field_name), )) } fn resolve_memory( &self, field_name: &str, _memory_type: &MemoryDescriptor, ) -> Result { Err(Error::Instantiation( format!("Export {} not found", field_name), )) } fn resolve_table( &self, field_name: &str, _table_type: &TableDescriptor, ) -> Result { Err(Error::Instantiation( format!("Export {} not found", field_name), )) } } impl ModuleImportResolver for ModuleRef { fn resolve_func( &self, field_name: &str, _signature: &Signature, ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Instantiation(format!("Export {} not found", field_name)) })? .as_func() .ok_or_else(|| { Error::Instantiation(format!("Export {} is not a function", field_name)) })?) } fn resolve_global( &self, field_name: &str, _global_type: &GlobalDescriptor, ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Instantiation(format!("Export {} not found", field_name)) })? .as_global() .ok_or_else(|| { Error::Instantiation(format!("Export {} is not a global", field_name)) })?) } fn resolve_memory( &self, field_name: &str, _memory_type: &MemoryDescriptor, ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Instantiation(format!("Export {} not found", field_name)) })? .as_memory() .ok_or_else(|| { Error::Instantiation(format!("Export {} is not a memory", field_name)) })?) } fn resolve_table( &self, field_name: &str, _table_type: &TableDescriptor, ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Instantiation(format!("Export {} not found", field_name)) })? .as_table() .ok_or_else(|| { Error::Instantiation(format!("Export {} is not a table", field_name)) })?) } }