mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 22:25:40 +00:00
rewrite extending imports
This commit is contained in:
parent
40be4da925
commit
5e39a7b3d9
@ -1,5 +1,6 @@
|
|||||||
use crate::export::Export;
|
use crate::export::Export;
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
|
use std::collections::VecDeque;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Ref, RefCell},
|
cell::{Ref, RefCell},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
@ -7,6 +8,8 @@ use std::{
|
|||||||
|
|
||||||
pub trait LikeNamespace {
|
pub trait LikeNamespace {
|
||||||
fn get_export(&self, name: &str) -> Option<Export>;
|
fn get_export(&self, name: &str) -> Option<Export>;
|
||||||
|
fn get_exports(&self) -> Vec<(String, Export)>;
|
||||||
|
fn maybe_insert(&mut self, name: &str, export: Export) -> Option<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IsExport {
|
pub trait IsExport {
|
||||||
@ -97,6 +100,53 @@ impl ImportObject {
|
|||||||
map: Rc::clone(&self.map),
|
map: Rc::clone(&self.map),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_objects(&self) -> VecDeque<(String, String, Export)> {
|
||||||
|
let mut out = VecDeque::new();
|
||||||
|
for (name, ns) in self.map.borrow().iter() {
|
||||||
|
for (id, exp) in ns.get_exports() {
|
||||||
|
out.push_back((name.clone(), id, exp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImportObjectIterator {
|
||||||
|
elements: VecDeque<(String, String, Export)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for ImportObjectIterator {
|
||||||
|
type Item = (String, String, Export);
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.elements.pop_front()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for ImportObject {
|
||||||
|
type IntoIter = ImportObjectIterator;
|
||||||
|
type Item = (String, String, Export);
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
ImportObjectIterator {
|
||||||
|
elements: self.get_objects(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Extend<(String, String, Export)> for ImportObject {
|
||||||
|
fn extend<T: IntoIterator<Item = (String, String, Export)>>(&mut self, iter: T) {
|
||||||
|
let mut map = self.map.borrow_mut();
|
||||||
|
for (ns, id, exp) in iter.into_iter() {
|
||||||
|
if let Some(like_ns) = map.get_mut(&ns) {
|
||||||
|
like_ns.maybe_insert(&id, exp).expect(&format!("Insert failed. Duplicate name {} found in namespace {}", id, ns));
|
||||||
|
} else {
|
||||||
|
let mut new_ns = Namespace::new();
|
||||||
|
new_ns.insert(id, exp);
|
||||||
|
map.insert(ns, Box::new(new_ns));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Namespace {
|
pub struct Namespace {
|
||||||
@ -123,4 +173,71 @@ impl LikeNamespace for Namespace {
|
|||||||
fn get_export(&self, name: &str) -> Option<Export> {
|
fn get_export(&self, name: &str) -> Option<Export> {
|
||||||
self.map.get(name).map(|is_export| is_export.to_export())
|
self.map.get(name).map(|is_export| is_export.to_export())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_exports(&self) -> Vec<(String, Export)> {
|
||||||
|
self.map
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (k.clone(), v.to_export()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_insert(&mut self, name: &str, export: Export) -> Option<()> {
|
||||||
|
if self.map.contains_key(name) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.map.insert(name.to_owned(), Box::new(export));
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::global::Global;
|
||||||
|
use crate::types::Value;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extending_works() {
|
||||||
|
let mut imports1 = imports! {
|
||||||
|
"dog" => {
|
||||||
|
"happy" => Global::new(Value::I32(0)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let imports2 = imports! {
|
||||||
|
"dog" => {
|
||||||
|
"small" => Global::new(Value::I32(2)),
|
||||||
|
},
|
||||||
|
"cat" => {
|
||||||
|
"small" => Global::new(Value::I32(3)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
imports1.extend(imports2);
|
||||||
|
|
||||||
|
let cat_ns = imports1.get_namespace("cat").unwrap();
|
||||||
|
assert!(cat_ns.get_export("small").is_some());
|
||||||
|
|
||||||
|
let dog_ns = imports1.get_namespace("dog").unwrap();
|
||||||
|
assert!(dog_ns.get_export("happy").is_some());
|
||||||
|
assert!(dog_ns.get_export("small").is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn extending_conflict_panics() {
|
||||||
|
let mut imports1 = imports! {
|
||||||
|
"dog" => {
|
||||||
|
"happy" => Global::new(Value::I32(0)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let imports2 = imports! {
|
||||||
|
"dog" => {
|
||||||
|
"happy" => Global::new(Value::I32(4)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
imports1.extend(imports2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,6 +427,14 @@ impl LikeNamespace for Instance {
|
|||||||
|
|
||||||
Some(self.inner.get_export_from_index(&self.module, export_index))
|
Some(self.inner.get_export_from_index(&self.module, export_index))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_exports(&self) -> Vec<(String, Export)> {
|
||||||
|
unimplemented!("Use the exports method instead");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_insert(&mut self, _name: &str, _export: Export) -> Option<()> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A representation of an exported WebAssembly function.
|
/// A representation of an exported WebAssembly function.
|
||||||
|
Loading…
Reference in New Issue
Block a user