summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2023-12-10 14:22:48 +0100
committerHenry Gressmann <mail@henrygressmann.de>2023-12-10 14:22:48 +0100
commit5315ea932697da4bf6fa814576e1823233063a95 (patch)
tree56239489c19ee3d6ae731fe08559521f86605354 /crates
parent52bebfac2e6a2dc934273e38230d3986e68a3fe3 (diff)
docs: improve rustdoc
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
-rw-r--r--crates/cli/src/args.rs2
-rw-r--r--crates/cli/src/bin.rs2
-rw-r--r--crates/tinywasm/src/lib.rs56
-rw-r--r--crates/tinywasm/src/runtime/mod.rs3
-rw-r--r--crates/tinywasm/src/store.rs2
-rw-r--r--crates/types/src/lib.rs66
-rw-r--r--crates/wasm-testsuite/lib.rs49
7 files changed, 120 insertions, 60 deletions
diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs
index 4023be6..379ecf8 100644
--- a/crates/cli/src/args.rs
+++ b/crates/cli/src/args.rs
@@ -1,5 +1,5 @@
use std::str::FromStr;
-use tinywasm::WasmValue;
+use tinywasm::types::WasmValue;
#[derive(Debug)]
pub struct WasmArg(WasmValue);
diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs
index 07513fb..2712751 100644
--- a/crates/cli/src/bin.rs
+++ b/crates/cli/src/bin.rs
@@ -4,7 +4,7 @@ use argh::FromArgs;
use args::WasmArg;
use color_eyre::eyre::Result;
use log::{debug, info};
-use tinywasm::{self, Module, WasmValue};
+use tinywasm::{self, types::WasmValue, Module};
use crate::args::to_wasm_args;
mod args;
diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs
index aa01ef9..8abf280 100644
--- a/crates/tinywasm/src/lib.rs
+++ b/crates/tinywasm/src/lib.rs
@@ -10,7 +10,56 @@
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
#![cfg_attr(feature = "nightly", feature(error_in_core))]
-//! ## A tiny WebAssembly Runtime written in Rust
+//! A tiny WebAssembly Runtime written in Rust
+//!
+//! TinyWasm provides a minimal WebAssembly runtime for executing WebAssembly modules.
+//! It currently supports a subset of the WebAssembly MVP specification and is intended
+//! to be useful for embedded systems and other environments where a full-featured
+//! runtime is not required.
+//!
+//! ## Getting Started
+//!
+//! The easiest way to get started is to use the [`Module::parse_bytes`] function to load a
+//! WebAssembly module from bytes. This will parse the module and validate it, returning
+//! a [`Module`] that can be used to instantiate the module.
+//!
+//! ```rust
+//! use tinywasm::{Store, Module};
+//!
+//! // Load a module from bytes
+//! let wasm = include_bytes!("../../../examples/wasm/add.wasm");
+//! let module = Module::parse_bytes(wasm)?;
+//!
+//! // Create a new store
+//! // Stores are used to allocate objects like functions and globals
+//! let mut store = Store::default();
+//!
+//! // Instantiate the module
+//! // This will allocate the module and its globals into the store
+//! // and execute the module's start function.
+//! // Every ModuleInstance has its own ID space for functions, globals, etc.
+//! let instance = module.instantiate(&mut store)?;
+//!
+//! // Get a typed handle to the exported "add" function
+//! // Alternatively, you can use `instance.get_func` to get an untyped handle
+//! // that takes and returns WasmValue types
+//! let func = instance.get_typed_func::<(i32, i32), (i32,)>(&mut store, "add")?;
+//! let res = func.call(&mut store, (1, 2))?;
+//!
+//! assert_eq!(res, (3,));
+//! # Ok::<(), tinywasm::Error>(())
+//! ```
+//!
+//! ## Features
+//! - `std` (default): Enables the use of `std` and `std::io` for parsing from files and streams.
+//! - `logging` (default): Enables logging via the `log` crate.
+//! - `parser` (default): Enables the `tinywasm_parser` crate for parsing WebAssembly modules.
+//!
+//! ## No-std support
+//! TinyWasm supports `no_std` environments by disabling the `std` feature. This removes
+//! support for parsing from files and streams, but otherwise the API is the same.
+//! Additionally, you must use a nightly compiler as TinyWasm uses the `error_in_core` feature
+//! and have a `GlobalAlloc` implementation for allocating memory.
// compiler error when using no_std without nightly
#[cfg(all(not(feature = "std"), not(nightly)))]
@@ -57,7 +106,10 @@ pub mod parser {
pub use tinywasm_parser::*;
}
-pub use tinywasm_types::*;
+/// Re-export of [`tinywasm_types`].
+pub mod types {
+ pub use tinywasm_types::*;
+}
#[cfg(test)]
mod tests {
diff --git a/crates/tinywasm/src/runtime/mod.rs b/crates/tinywasm/src/runtime/mod.rs
index 07cff38..610810f 100644
--- a/crates/tinywasm/src/runtime/mod.rs
+++ b/crates/tinywasm/src/runtime/mod.rs
@@ -5,6 +5,7 @@ mod value;
pub use stack::*;
pub(crate) use value::RawWasmValue;
+#[allow(rustdoc::private_intra_doc_links)]
/// A WebAssembly Runtime.
///
/// Generic over `CheckTypes` to enable type checking at runtime.
@@ -13,6 +14,6 @@ pub(crate) use value::RawWasmValue;
///
/// See <https://webassembly.github.io/spec/core/exec/runtime.html>
///
-/// Execution is implemented in the [`crate::runtime::executer`] module
+/// Execution is implemented in the [`crate::runtime::executor`] module
#[derive(Debug, Default)]
pub struct DefaultRuntime {}
diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs
index 3214540..1a9d968 100644
--- a/crates/tinywasm/src/store.rs
+++ b/crates/tinywasm/src/store.rs
@@ -98,7 +98,7 @@ impl FunctionInstance {
#[derive(Debug, Default)]
/// Global state that can be manipulated by WebAssembly programs
-pub struct StoreData {
+pub(crate) struct StoreData {
pub(crate) funcs: Vec<Rc<FunctionInstance>>,
// pub tables: Vec<TableAddr>,
// pub mems: Vec<MemAddr>,
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index b79c72a..4e09e00 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -1,3 +1,16 @@
+#![no_std]
+#![forbid(unsafe_code)]
+#![doc(test(
+ no_crate_inject,
+ attr(
+ deny(warnings, rust_2018_idioms),
+ allow(dead_code, unused_assignments, unused_variables)
+ )
+))]
+#![warn(missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
+
+//! Types used by [`tinywasm`](https://docs.rs/tinywasm) and [`tinywasm_parser`](https://docs.rs/tinywasm_parser).
+
extern crate alloc;
// log for logging (optional).
@@ -15,15 +28,29 @@ extern crate alloc;
mod instructions;
use core::fmt::Debug;
+use alloc::boxed::Box;
pub use instructions::*;
+/// A TinyWasm WebAssembly Module
+///
+/// This is the internal representation of a WebAssembly module in TinyWasm.
+/// TinyWasmModules are validated before being created, so they are guaranteed to be valid (as long as they were created by TinyWasm).
+/// This means you should not trust a TinyWasmModule created by a third party to be valid.
#[derive(Debug)]
pub struct TinyWasmModule {
+ /// The version of the WebAssembly module.
pub version: Option<u16>,
+
+ /// The start function of the WebAssembly module.
pub start_func: Option<FuncAddr>,
+ /// The functions of the WebAssembly module.
pub funcs: Box<[Function]>,
+
+ /// The types of the WebAssembly module.
pub types: Box<[FuncType]>,
+
+ /// The exports of the WebAssembly module.
pub exports: Box<[Export]>,
// pub tables: Option<TableType>,
// pub memories: Option<MemoryType>,
@@ -39,15 +66,20 @@ pub struct TinyWasmModule {
#[derive(Clone, PartialEq, Copy)]
pub enum WasmValue {
// Num types
+ /// A 32-bit integer.
I32(i32),
+ /// A 64-bit integer.
I64(i64),
+ /// A 32-bit float.
F32(f32),
+ /// A 64-bit float.
F64(f64),
// Vec types
// V128(i128),
}
impl WasmValue {
+ /// Get the default value for a given type.
pub fn default_for(ty: ValType) -> Self {
match ty {
ValType::I32 => Self::I32(0),
@@ -135,19 +167,8 @@ impl TryFrom<WasmValue> for f64 {
}
}
-// impl TryFrom<WasmValue> for i128 {
-// type Error = ();
-
-// fn try_from(value: WasmValue) -> Result<Self, Self::Error> {
-// match value {
-// WasmValue::V128(i) => Ok(i),
-// _ => Err(()),
-// }
-// }
-// }
-
impl Debug for WasmValue {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
match self {
WasmValue::I32(i) => write!(f, "i32({})", i),
WasmValue::I64(i) => write!(f, "i64({})", i),
@@ -159,6 +180,7 @@ impl Debug for WasmValue {
}
impl WasmValue {
+ /// Get the type of a [`WasmValue`]
pub fn val_type(&self) -> ValType {
match self {
Self::I32(_) => ValType::I32,
@@ -173,12 +195,19 @@ impl WasmValue {
/// Type of a WebAssembly value.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValType {
+ /// A 32-bit integer.
I32,
+ /// A 64-bit integer.
I64,
+ /// A 32-bit float.
F32,
+ /// A 64-bit float.
F64,
+ /// A 128-bit vector.
V128,
+ /// A reference to a function.
FuncRef,
+ /// A reference to an external value.
ExternRef,
}
@@ -187,9 +216,13 @@ pub enum ValType {
/// See <https://webassembly.github.io/spec/core/syntax/types.html#external-types>
#[derive(Debug, Clone, PartialEq)]
pub enum ExternalKind {
+ /// A WebAssembly Function.
Func,
+ /// A WebAssembly Table.
Table,
+ /// A WebAssembly Memory.
Memory,
+ /// A WebAssembly Global.
Global,
}
@@ -212,15 +245,6 @@ pub type LocalAddr = Addr;
pub type LabelAddr = Addr;
pub type ModuleInstanceAddr = Addr;
-/// A WebAssembly Export Instance.
-///
-/// See <https://webassembly.github.io/spec/core/exec/runtime.html#export-instances>
-#[derive(Debug)]
-pub struct ExportInst {
- pub name: String,
- pub value: ExternVal,
-}
-
/// A WebAssembly External Value.
///
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#external-values>
diff --git a/crates/wasm-testsuite/lib.rs b/crates/wasm-testsuite/lib.rs
index 102389a..5590f35 100644
--- a/crates/wasm-testsuite/lib.rs
+++ b/crates/wasm-testsuite/lib.rs
@@ -2,7 +2,7 @@
//!
//! The testsuite is included as a git submodule and embedded into the binary.
//!
-//! Generated from https://github.com/WebAssembly/testsuite
+//! Generated from <https://github.com/WebAssembly/testsuite>
#![forbid(unsafe_code)]
#![doc(test(
@@ -22,18 +22,21 @@ use std::borrow::Cow;
#[include = "*.wast"]
struct Asset;
-/// List of all proposals.
-/// This list is generated from the `proposals` folder in https://github.com/WebAssembly/testsuite
+/// List of all proposals. Used to filter tests.
+///
+/// Includes all proposals from <https://github.com/WebAssembly/testsuite/tree/master/proposals>
#[rustfmt::skip]
pub const PROPOSALS: &[&str] = &["annotations", "exception-handling", "memory64", "function-references", "multi-memory", "relaxed-simd", "tail-call", "threads", "extended-const", "gc"];
/// Get all test file names and their contents.
-///
-/// Proposals can be filtered by passing a list of proposal names.
-/// Valid proposal names are listed in [`PROPOSALS`].
-/// Returns an iterator over tuples of the form `(test_name, test_data)`.
-/// test_name is the name of the test file and the proposal name (if any), e.g. `annotations/br.wast`.
-pub fn get_tests(include_proposals: &[String]) -> impl Iterator<Item = (String, Cow<'static, [u8]>)> {
+pub fn get_tests_wast(include_proposals: &[String]) -> impl Iterator<Item = (String, Cow<'static, [u8]>)> {
+ get_tests(&include_proposals)
+ .filter_map(|name| Some((name.clone(), get_test_wast(&name)?)))
+ .map(|(name, data)| (name, Cow::Owned(data.to_vec())))
+}
+
+/// Get all test file names.
+pub fn get_tests(include_proposals: &[String]) -> impl Iterator<Item = String> {
let include_proposals = include_proposals.to_vec();
Asset::iter().filter_map(move |x| {
@@ -45,27 +48,19 @@ pub fn get_tests(include_proposals: &[String]) -> impl Iterator<Item = (String,
if proposal.map_or(false, |p| include_proposals.contains(&p.to_string())) {
let full_path = format!("{}/{}", proposal.unwrap_or_default(), test_name);
- let data = Asset::get(&x).unwrap().data;
- Some((full_path, data))
+ Some(full_path)
} else {
None
}
}
- Some(test_name) => {
- let data = Asset::get(&x).unwrap().data;
- Some((test_name.to_owned(), data))
- }
+ Some(test_name) => Some(test_name.to_owned()),
None => None,
}
})
}
/// Get the WAST file as a byte slice.
-///
-/// # Examples
-/// proposals: {proposal}/{test_name}.wast
-/// tests: {test_name}.wast
-pub fn get_wast(name: &str) -> Option<Cow<'_, [u8]>> {
+pub fn get_test_wast(name: &str) -> Option<Cow<'static, [u8]>> {
if !name.ends_with(".wast") {
panic!("Expected .wast file. Got: {}", name);
}
@@ -94,19 +89,7 @@ mod tests {
let proposal = proposal.split('/').nth(1).unwrap();
unique_proposals.insert(proposal.to_owned());
- // assert!(PROPOSALS.contains(&proposal));
+ assert!(PROPOSALS.contains(&proposal));
}
- println!("{:?}", unique_proposals);
- }
-
- #[test]
- fn test_get_tests() {
- let tests = get_tests(&["annotations".to_owned()]);
- let tests: Vec<_> = tests.collect();
- println!("{:?}", tests.iter().map(|(name, _)| name).collect::<Vec<_>>());
-
- // for (name, data) in tests {
- // println!("{}: {}", name, data.len());
- // }
}
}