Skip to content

Commit

Permalink
Added function to merge ImportObjects
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Perkins committed Mar 7, 2019
1 parent 49dc213 commit a01b4e9
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
52 changes: 50 additions & 2 deletions lib/runtime-core/src/import.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::export::Export;
use hashbrown::{hash_map::Entry, HashMap};
use hashbrown::{hash_map::Entry, HashMap, HashSet};

pub trait LikeNamespace {
fn get_all_exports(&self) -> HashMap<String, Export>;
fn get_export(&self, name: &str) -> Option<Export>;
}

Expand Down Expand Up @@ -41,7 +42,7 @@ pub struct ImportObject {
}

impl ImportObject {
/// Create a new `ImportObject`.
/// Create a new `ImportObject`.
pub fn new() -> Self {
Self {
map: HashMap::new(),
Expand Down Expand Up @@ -79,6 +80,46 @@ impl ImportObject {
pub fn get_namespace(&self, namespace: &str) -> Option<&(dyn LikeNamespace + 'static)> {
self.map.get(namespace).map(|namespace| &**namespace)
}

pub fn merged(mut imports_a: ImportObject, mut imports_b: ImportObject) -> Self {
let all_names: HashSet<String> = imports_a
.map
.keys()
.chain(imports_b.map.keys())
.cloned()
.collect();
let mut combined_imports = ImportObject::new();
for name in all_names {
match (imports_a.map.remove(&name), imports_b.map.remove(&name)) {
(Some(namespace_a), Some(namespace_b)) => {
// Create a combined namespace
let mut combined_namespace = Namespace {
map: HashMap::new(),
};
let mut exports_a = namespace_a.get_all_exports();
let mut exports_b = namespace_b.get_all_exports();
// Import from A will win over B
combined_namespace.map.extend(exports_b.drain().map(
|(export_name, export)| (export_name, Box::new(export) as Box<IsExport>),
));
combined_namespace.map.extend(exports_a.drain().map(
|(export_name, export)| (export_name, Box::new(export) as Box<IsExport>),
));
combined_imports
.map
.insert(name, Box::new(combined_namespace));
}
(Some(namespace_a), None) => {
combined_imports.map.insert(name, namespace_a);
}
(None, Some(namespace_b)) => {
combined_imports.map.insert(name, namespace_b);
}
(None, None) => panic!("Unreachable"),
}
}
combined_imports
}
}

pub struct Namespace {
Expand All @@ -102,6 +143,13 @@ impl Namespace {
}

impl LikeNamespace for Namespace {
fn get_all_exports(&self) -> HashMap<String, Export> {
self.map
.iter()
.map(|(name, is_export)| (name.to_string(), is_export.to_export()))
.collect()
}

fn get_export(&self, name: &str) -> Option<Export> {
self.map.get(name).map(|is_export| is_export.to_export())
}
Expand Down
15 changes: 15 additions & 0 deletions lib/runtime-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value},
vm,
};
use hashbrown::HashMap;
use std::{mem, sync::Arc};

pub(crate) struct InstanceInner {
Expand Down Expand Up @@ -416,6 +417,20 @@ impl InstanceInner {
}

impl LikeNamespace for Instance {
fn get_all_exports(&self) -> HashMap<String, Export> {
self.module
.info
.exports
.iter()
.map(|(name, export_index)| {
(
name.to_string(),
self.inner.get_export_from_index(&self.module, export_index),
)
})
.collect()
}

fn get_export(&self, name: &str) -> Option<Export> {
let export_index = self.module.info.exports.get(name)?;

Expand Down

0 comments on commit a01b4e9

Please sign in to comment.