Add skeleton of external API and tests

This commit is contained in:
Mark McCaskey 2020-03-24 18:59:09 -07:00
parent d8bd258ef2
commit cc13e45215
7 changed files with 286 additions and 0 deletions

11
Cargo.lock generated
View File

@ -24,6 +24,14 @@ version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
[[package]]
name = "api-tests"
version = "0.16.2"
dependencies = [
"wabt",
"wasmer",
]
[[package]]
name = "arrayref"
version = "0.3.6"
@ -1843,7 +1851,10 @@ dependencies = [
name = "wasmer"
version = "0.16.2"
dependencies = [
"wasmer-clif-backend",
"wasmer-llvm-backend",
"wasmer-runtime-core",
"wasmer-singlepass-backend",
]
[[package]]

View File

@ -46,6 +46,7 @@ wasmer-wasi-experimental-io-devices = { path = "lib/wasi-experimental-io-devices
[workspace]
members = [
"lib/api",
"lib/api-tests",
"lib/clif-backend",
"lib/singlepass-backend",
"lib/runtime",

15
lib/api-tests/Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "api-tests"
version = "0.16.2"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"
license = "MIT"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wasmer = { version = "0.16.2", path = "../api" }
[dev-dependencies]
wabt = "0.9.1"

1
lib/api-tests/src/lib.rs Normal file
View File

@ -0,0 +1 @@

View File

@ -0,0 +1,33 @@
static TEST_WAT: &str = r#"
(module
(table $test-table 2 anyfunc)
(export "test-table" (table $test-table))
(export "ret_2" (func $ret_2))
(export "ret_4" (func $ret_4))
(elem (;0;) (i32.const 0) $ret_2)
(func $ret_2 (result i32)
i32.const 2)
(func $ret_4 (result i32)
i32.const 4)
)
"#;
#[test]
fn it_works() {
use wasmer::{imports, CompiledModule, Func, Module, Table};
let wasm = wabt::wat2wasm(TEST_WAT).unwrap();
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be
// misleading, if so we may want to do something about it.
let module = Module::new(wasm).unwrap();
let import_object = imports! {};
let instance = module.instantiate(&import_object).unwrap();
let ret_2: Func<(), i32> = instance.exports_new().get("ret_2").unwrap();
let ret_4: Func<(), i32> = instance.exports_new().get("ret_4").unwrap();
assert_eq!(ret_2.call(), Ok(2));
assert_eq!(ret_4.call(), Ok(4));
let _test_table: Table = instance.exports_new().get("test-table").unwrap();
// TODO: when table get is stablized test this
}

40
lib/api/Cargo.toml Normal file
View File

@ -0,0 +1,40 @@
[package]
name = "wasmer"
version = "0.16.2"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"
publish = true
description = "The high-level public API of the Wasmer WebAssembly runtime"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wasmer-runtime-core = { version = "0.16.2", path = "../runtime-core" }
[dependencies.wasmer-singlepass-backend]
path = "../singlepass-backend"
version = "0.16.2"
optional = true
[dependencies.wasmer-llvm-backend]
path = "../llvm-backend"
optional = true
[dependencies.wasmer-clif-backend]
path = "../clif-backend"
version = "0.16.2"
optional = true
[features]
default = ["cranelift", "default-backend-cranelift"]
singlepass = ["wasmer-singlepass-backend"]
llvm = ["wasmer-llvm-backend"]
cranelift = ["wasmer-clif-backend"]
default-backend-singlepass = ["singlepass"]
default-backend-llvm = ["llvm"]
default-backend-cranelift = ["cranelift"]
deterministic-execution = ["wasmer-singlepass-backend/deterministic-execution", "wasmer-runtime-core/deterministic-execution"]

185
lib/api/src/lib.rs Normal file
View File

@ -0,0 +1,185 @@
#![deny(
dead_code,
// missing_docs,
nonstandard_style,
unused_imports,
unused_mut,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
// Aspirational. I hope to have no unsafe code in this crate.
#![forbid(unsafe_code)]
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
//! TODO: Write high value, high-level API intro docs here
//! Intro/background information
//!
//! quick links to places in this document/other crates/standards etc.
//!
//! example code, link to projects using it
//!
//! more info, what to do if you run into problems
/// Commonly used types and functions.
pub mod prelude {
pub use crate::module::*;
pub use wasmer_runtime_core::instance::{DynFunc, Instance};
pub use wasmer_runtime_core::memory::Memory;
pub use wasmer_runtime_core::table::Table;
pub use wasmer_runtime_core::Func;
pub use wasmer_runtime_core::{func, imports};
}
pub mod module {
//! Types and functions for WebAssembly modules.
//!
//! # Usage
//! ## Create a Module
//!
//! ```
//! ```
//!
//! ## Get the exports from a Module
//! ```
//! # use wasmer::*;
//! # fn get_exports(module: &Module) {
//! let exports: Vec<ExportDescriptor> = module.exports().collect();
//! # }
//! ```
// TODO: verify that this is the type we want to export, with extra methods on it
pub use wasmer_runtime_core::module::Module;
// should this be in here?
pub use wasmer_runtime_core::module::{ExportDescriptor, ExportKind, Import, ImportType};
// TODO: implement abstract module API
}
pub mod memory {
//! Types and functions for Wasm linear memory.
pub use wasmer_runtime_core::memory::{Atomically, Memory, MemoryView};
}
pub mod wasm {
//! Various types exposed by the Wasmer Runtime.
//!
//! TODO: Add index with links to sub sections
//!
//! # Globals
//!
//! # Tables
pub use wasmer_runtime_core::global::Global;
pub use wasmer_runtime_core::module::{ExportDescriptor, ExportKind, Import, ImportType};
pub use wasmer_runtime_core::table::Table;
pub use wasmer_runtime_core::types::{
FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, Value,
};
}
pub mod import {
//! Types and functions for Wasm imports.
pub use wasmer_runtime_core::module::{Import, ImportType};
pub use wasmer_runtime_core::{func, imports};
}
pub mod export {
//! Types and functions for Wasm exports.
pub use wasmer_runtime_core::module::{ExportDescriptor, ExportKind};
}
pub mod units {
//! Various unit types.
pub use wasmer_runtime_core::units::{Bytes, Pages};
}
pub mod types {
//! Types used in the Wasm runtime and conversion functions.
pub use wasmer_runtime_core::types::*;
}
pub mod error {
//! Various error types returned by Wasmer APIs.
pub use wasmer_runtime_core::error::*;
}
pub use prelude::*;
/// Idea for generic trait; consider rename; it will need to be moved somewhere else
pub trait CompiledModule {
fn new(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module>;
fn from_binary(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module>;
fn from_binary_unchecked(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module>;
fn from_file(file: impl AsRef<std::path::Path>) -> error::CompileResult<Module>;
fn validate(bytes: impl AsRef<[u8]>) -> error::CompileResult<()>;
}
use wasmer_runtime_core::backend::Compiler;
/// Copied from runtime core; TODO: figure out what we want to do here
pub fn default_compiler() -> impl Compiler {
#[cfg(any(
all(
feature = "default-backend-llvm",
not(feature = "docs"),
any(
feature = "default-backend-cranelift",
feature = "default-backend-singlepass"
)
),
all(
not(feature = "docs"),
feature = "default-backend-cranelift",
feature = "default-backend-singlepass"
)
))]
compile_error!(
"The `default-backend-X` features are mutually exclusive. Please choose just one"
);
#[cfg(all(feature = "default-backend-llvm", not(feature = "docs")))]
use wasmer_llvm_backend::LLVMCompiler as DefaultCompiler;
#[cfg(all(feature = "default-backend-singlepass", not(feature = "docs")))]
use wasmer_singlepass_backend::SinglePassCompiler as DefaultCompiler;
#[cfg(any(feature = "default-backend-cranelift", feature = "docs"))]
use wasmer_clif_backend::CraneliftCompiler as DefaultCompiler;
DefaultCompiler::new()
}
// this implementation should be moved
impl CompiledModule for Module {
fn new(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module> {
let bytes = bytes.as_ref();
wasmer_runtime_core::compile_with(bytes, &default_compiler())
}
fn from_binary(_bytes: impl AsRef<[u8]>) -> error::CompileResult<Module> {
todo!("from_binary: how is this different from `new`?")
}
fn from_binary_unchecked(_bytes: impl AsRef<[u8]>) -> error::CompileResult<Module> {
todo!("from_binary_unchecked")
}
fn from_file(_file: impl AsRef<std::path::Path>) -> error::CompileResult<Module> {
todo!("from_file");
/*
use std::fs;
use std::io::Read;
let path = file.as_ref();
let mut f =
fs::File::open(path).map_err(|_| todo!("Current error enum can't handle this case"))?;
// TODO: ideally we can support a streaming compilation API and not have to read in the entire file
let mut bytes = vec![];
f.read_to_end(&mut bytes)
.map_err(|_| todo!("Current error enum can't handle this case"))?;
Module::from_binary(bytes.as_slice())
*/
}
fn validate(_bytes: impl AsRef<[u8]>) -> error::CompileResult<()> {
todo!("validate")
}
}