Skip to content

Commit c7c26e8

Browse files
docs: improve rust docs
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent e96bab0 commit c7c26e8

12 files changed

Lines changed: 127 additions & 74 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
- Removed the parser's `optimize_remove_nop` option and accessors.
2929
- Changed public `Instruction` variants and the `.twasm` format. Existing archives must be regenerated.
3030
- `TableType` limits now use `u64`. Use `TableType::new` or `TableType::new64` instead of struct literals.
31-
- `ToWasmType` and `ToWasmTypes` now use associated constants, and `wasm_types` returns `Cow`.
31+
- `ToWasmTypes` now uses an associated constant, and `wasm_types` returns `Cow`.
3232
- `LinearMemory` now uses a single `usize` address and changed its fixed-width read/write signatures.
3333

3434
## [0.9.1] - 2026-06-29

‎README.md‎

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
```toml
1414
[dependencies]
15-
tinywasm = "0.9"
15+
tinywasm = "0.10"
1616
```
1717

1818
## Usage
@@ -31,7 +31,7 @@ let mut store = Store::default();
3131
let instance = ModuleInstance::instantiate(&mut store, &module, None)?;
3232

3333
// Call an exported function with typed parameters
34-
let func = instance.func::<(i32, i32), i32>(&mut store, "add")?;
34+
let func = instance.func::<(i32, i32), i32>(&store, "add")?;
3535
let result = func.call(&mut store, (1, 2))?;
3636

3737
assert_eq!(result, 3);
@@ -41,24 +41,15 @@ See the [examples](./examples) directory and [documentation](https://docs.rs/tin
4141

4242
## Cargo Features
4343

44-
- **`std`**\
45-
Enables the use of `std` and `std::io` for parsing from files and streams. This is enabled by default.
46-
- **`log`**\
47-
Enables logging using the `log` crate. This is enabled by default.
48-
- **`parser`**\
49-
Enables the `tinywasm-parser` crate. This is enabled by default.
50-
- **`archive`**\
51-
Enables serialization/deserialization of compiled modules to the internal `twasm` bytecode format. This is enabled by default.
52-
- **`canonicalize-nans`**\
53-
Canonicalizes NaN values to a single representation. This is enabled by default.
54-
- **`debug`**\
55-
Derives `Debug` for runtime types. This is enabled by default.
56-
- **`parallel-parser`**\
57-
Parallelizes function parsing and validation across threads (requires `std`). This is enabled by default.
58-
- **`guest-debug`**\
59-
Exposes module-internal by-index inspection APIs (`*_by_index`).
60-
- **`simd-x86`**\
61-
Enables x86-specific SIMD intrinsics for `i8x16_swizzle` and `i8x16_shuffle` (uses `unsafe` code).
44+
- **`std`:** Enables `std` and parsing from files and streams. Enabled by default.
45+
- **`log`:** Enables integration with the `log` crate. Enabled by default.
46+
- **`parser`:** Enables `tinywasm-parser` and top-level parse helpers. Enabled by default.
47+
- **`archive`:** Enables serialization and deserialization of the internal `twasm` format. Enabled by default.
48+
- **`canonicalize-nans`:** Canonicalizes NaN values. Enabled by default.
49+
- **`debug`:** Derives `Debug` for runtime types. Enabled by default.
50+
- **`parallel-parser`:** Parallelizes function parsing and validation when `std` is enabled. Enabled by default.
51+
- **`guest-debug`:** Exposes module-internal by-index inspection APIs (`*_by_index`).
52+
- **`simd-x86`:** Enables x86-specific SIMD intrinsics and uses `unsafe` internally.
6253

6354
With default features disabled, `tinywasm` depends only on `core`, `alloc`, and `libm`[^libm], making it usable in `no_std + alloc` environments.
6455

@@ -68,13 +59,13 @@ Use `Engine` and `engine::Config` when you need non-default runtime settings suc
6859

6960
## Current Status
7061

71-
`tinywasm` passes the WebAssembly MVP and WebAssembly 2.0 core testsuites. WebAssembly 3.0 support is still in progress, and some newer proposal suites are tracked in-repo as experimental coverage rather than release guarantees; see [Supported Proposals](#supported-proposals) for details.
62+
`tinywasm` passes the WebAssembly MVP and WebAssembly 2.0 core testsuites and supports the [Lime1](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1) interoperability target. WebAssembly 3.0 support is still in progress, and some newer proposal suites are tracked in-repo as experimental coverage rather than release guarantees; see [Supported Proposals](#supported-proposals) for details.
7263

73-
TinyWasm also has its own internal bytecode format, `twasm`. WebAssembly modules can be compiled to `twasm`, which stores TinyWasm's validated and optimized instruction representation for faster loading and reuse.
64+
TinyWasm also has its own internal bytecode format, `twasm`. WebAssembly modules can be compiled to `twasm`, which stores TinyWasm's optimized instruction representation for faster loading and reuse.
7465

7566
## Safety
7667

77-
TinyWasm only uses safe Rust by default. The optional `simd-x86` feature enables x86-specific SIMD intrinsics and uses `unsafe` internally. WebAssembly input is validated by TinyWasm before execution and runs inside a sandbox: untrusted Wasm should not be able to access host memory, escape the sandbox, or cause undefined behavior in the runtime.
68+
TinyWasm only uses safe Rust by default. The optional `simd-x86` feature enables x86-specific SIMD intrinsics and uses `unsafe` internally. WebAssembly input is validated by default and runs inside a sandbox: untrusted Wasm should not be able to access host memory, escape the sandbox, or cause undefined behavior in the runtime. Validation should only be disabled for trusted input.
7869

7970
The internal `twasm` bytecode format is not currently validated as an untrusted input format. Malformed `twasm` may panic, but should not compromise memory safety or allow sandbox escape. Only run trusted `twasm` bytecode, or generate it through TinyWasm from Wasm input.
8071

‎crates/parser/src/lib.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ pub use tinywasm_types::Module;
4949
#[non_exhaustive]
5050
#[derive(Debug, Clone)]
5151
pub struct ParserOptions {
52-
/// Whether to validate modules while parsing.
52+
/// Whether to validate modules while parsing. Enabled by default.
53+
///
54+
/// Disable this only for trusted input. Parsing without validation may produce
55+
/// a module that violates runtime assumptions.
5356
pub validation: bool,
5457
/// Whether to optimize local memory allocation by skipping allocation of unused local memories.
5558
pub optimize_local_memory_allocation: bool,
@@ -81,6 +84,9 @@ impl Default for ParserOptions {
8184

8285
impl ParserOptions {
8386
/// Enable or disable WebAssembly validation.
87+
///
88+
/// Disable this only for trusted input. Parsing without validation may produce
89+
/// a module that violates runtime assumptions.
8490
pub const fn with_validation(mut self, enabled: bool) -> Self {
8591
self.validation = enabled;
8692
self
@@ -337,7 +343,7 @@ pub fn parse_file(path: impl AsRef<crate::std::path::Path> + Clone) -> Result<Mo
337343
}
338344

339345
#[cfg(feature = "std")]
340-
/// Parse a module from a stream. Requires `parser` and `std` features.
346+
/// Parse a module from a stream. Requires the `std` feature.
341347
pub fn parse_stream(stream: impl crate::std::io::Read) -> Result<Module> {
342348
Parser::new().parse_module_stream(stream)
343349
}

‎crates/tinywasm/src/engine.rs‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ impl StackConfig {
9292
///
9393
/// let config = Config::new()
9494
/// .with_fuel_policy(FuelPolicy::Weighted)
95-
/// .with_value_stack(StackConfig::dynamic(1024, 16 * 1024))
95+
/// .with_value_stack_32(StackConfig::dynamic(1024, 36 * 1024))
96+
/// .with_value_stack_64(StackConfig::dynamic(1024, 32 * 1024))
97+
/// .with_value_stack_128(StackConfig::dynamic(256, 4 * 1024))
98+
/// .with_call_stack(StackConfig::dynamic(64, 1024))
9699
/// .with_memory_backend(MemoryBackend::paged(64 * 1024))
97100
/// .with_trap_on_oom(true);
98101
///
@@ -103,23 +106,27 @@ impl StackConfig {
103106
#[non_exhaustive]
104107
pub struct Config {
105108
/// Configuration for the 32-bit value stack (i32, f32, ref values).
109+
/// Defaults to `StackConfig::fixed(36 * 1024)`.
106110
pub value_stack_32: StackConfig,
107111
/// Configuration for the 64-bit value stack (i64, f64 values).
112+
/// Defaults to `StackConfig::fixed(32 * 1024)`.
108113
pub value_stack_64: StackConfig,
109114
/// Configuration for the 128-bit value stack (v128 values).
115+
/// Defaults to `StackConfig::fixed(4 * 1024)`.
110116
pub value_stack_128: StackConfig,
111-
/// Configuration for the call stack.
117+
/// Configuration for the call stack. Defaults to `StackConfig::fixed(1024)`.
112118
pub call_stack: StackConfig,
113-
/// Fuel accounting policy used by budgeted execution.
119+
/// Fuel accounting policy used by budgeted execution. Defaults to [`FuelPolicy::PerInstruction`].
114120
pub fuel_policy: FuelPolicy,
115-
/// Backend used for runtime memories.
121+
/// Backend used for runtime memories. Defaults to [`MemoryBackend::vec`].
116122
pub memory_backend: MemoryBackend,
117123
/// Whether memory and stack allocation failures should trap instead of degrading into normal operation failure modes.
124+
/// Defaults to `false`.
118125
pub trap_on_oom: bool,
119126
}
120127

121128
impl Config {
122-
/// Create a new stack configuration with default settings.
129+
/// Create a new interpreter configuration with default settings.
123130
pub fn new() -> Self {
124131
Self::default()
125132
}

‎crates/tinywasm/src/func.rs‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl Function {
4747
///
4848
/// The returned handle keeps a mutable borrow of the [`Store`] until it
4949
/// completes. Use [`FuncExecution::resume_with_fuel`] (or
50-
/// [`FuncExecution::resume_with_time_budget`] with `std`) to continue.
50+
/// `resume_with_time_budget` with `std`) to continue.
5151
pub fn call_resumable<'store>(
5252
&self,
5353
store: &'store mut Store,
@@ -540,6 +540,25 @@ impl<P: IntoWasmValues, R: FromWasmValues> FunctionTyped<P, R> {
540540
/// Call a typed function and return a resumable execution handle.
541541
///
542542
/// The handle keeps a mutable borrow of the [`Store`] until completion.
543+
///
544+
/// ## Example
545+
///
546+
/// ```rust
547+
/// # fn main() -> tinywasm::Result<()> {
548+
/// use tinywasm::{ExecProgress, ModuleInstance, Store};
549+
///
550+
/// let wasm = include_bytes!("../../../examples/wasm/add.wasm");
551+
/// let module = tinywasm::parse_bytes(wasm)?;
552+
/// let mut store = Store::default();
553+
/// let instance = ModuleInstance::instantiate(&mut store, &module, None)?;
554+
/// let add = instance.func::<(i32, i32), i32>(&store, "add")?;
555+
///
556+
/// let mut execution = add.call_resumable(&mut store, (20, 22))?;
557+
/// assert!(matches!(execution.resume_with_fuel(0)?, ExecProgress::Suspended));
558+
/// assert!(matches!(execution.resume_with_fuel(16)?, ExecProgress::Completed(42)));
559+
/// # Ok(())
560+
/// # }
561+
/// ```
543562
pub fn call_resumable<'store>(&self, store: &'store mut Store, params: P) -> Result<FuncExecutionTyped<'store, R>> {
544563
let wasm_values = params.into_wasm_values();
545564
let execution = self.func.call_resumable(store, &wasm_values)?;
@@ -574,7 +593,10 @@ impl<'store, R: FromWasmValues> FuncExecutionTyped<'store, R> {
574593

575594
/// Describes the WebAssembly value types produced by a Rust value or tuple shape.
576595
pub trait ToWasmTypes {
577-
/// Static WebAssembly types for shapes that do not require runtime concatenation.
596+
/// Static WebAssembly types for this shape.
597+
///
598+
/// Implementations that require runtime construction may set this to `None`,
599+
/// but must then override [`Self::wasm_types`].
578600
const WASM_TYPES: Option<&'static [WasmType]>;
579601

580602
/// Return the flattened WebAssembly value types for this tuple shape.

‎crates/tinywasm/src/instance.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,8 +560,8 @@ impl ModuleInstance {
560560

561561
/// Get the start function of the module
562562
///
563-
/// Returns None if the module has no start function
564-
/// If no start function is specified, also checks for a `_start` function in the exports
563+
/// Returns `None` if the module has no start section. Exported functions named
564+
/// `_start` are not treated as the module's start function.
565565
///
566566
/// ## Example
567567
/// ```rust

‎crates/tinywasm/src/lib.rs‎

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,22 @@
99

1010
//! `tinywasm` provides a small, portable WebAssembly interpreter with support for
1111
//! the WebAssembly MVP, WebAssembly 2.0, and a growing set of newer proposals.
12+
//! It also supports the [Lime1](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1)
13+
//! interoperability target.
1214
//! It is designed to stay lightweight while still being practical to embed in
1315
//! applications, tools, and `no_std + alloc` environments.
14-
//!
15-
//! ## Features
16-
//! - **`std`**\
17-
//! Enables parsing from files and streams. Enabled by default.
18-
//! - **`log`**\
19-
//! Enables integration with the `log` crate. Enabled by default.
20-
//! - **`parser`**\
21-
//! Enables the bundled `tinywasm-parser` crate and top-level parse helpers. Enabled by default.
22-
//! - **`archive`**\
23-
//! Enables serialization and deserialization of compiled modules in the internal `twasm` format. Enabled by default.
24-
//! - **`canonicalize-nans`**\
25-
//! Canonicalizes NaN values to a single representation. Enabled by default.
26-
//! - **`debug`**\
27-
//! Derives `Debug` for runtime types. Enabled by default.
28-
//! - **`parallel-parser`**\
29-
//! Parallelizes function parsing and validation across threads when `std` is enabled. Enabled by default.
30-
//! - **`guest-debug`**\
31-
//! Exposes module-internal by-index inspection APIs (`*_by_index`).
32-
//! - **`simd-x86`**\
33-
//! Enables x86-specific SIMD intrinsics for selected operations and uses `unsafe` internally.
34-
//!
35-
//! With default features disabled, `tinywasm` only depends on `core`, `alloc`, and `libm`.
36-
//! By disabling `std`, you can use `tinywasm` in `no_std` environments. This requires
37-
//! a custom allocator and removes support for parsing from files and streams, but otherwise the API is the same.
3816
3917
#![cfg_attr(docsrs, feature(doc_cfg))]
4018
//!
41-
//! ## Getting Started
42-
//! The easiest way to get started is to use the [`crate::parse_bytes`] function to load a
19+
//! ## Getting started
20+
//!
21+
//! The easiest way to get started is to use the `parse_bytes` function to load a
4322
//! WebAssembly module from bytes. This will parse the module and validate it, returning
4423
//! a [`Module`] that can be used to instantiate the module.
4524
//!
46-
//!
4725
//! ```rust
26+
//! # #[cfg(feature = "parser")]
27+
//! # fn main() -> tinywasm::Result<()> {
4828
//! use tinywasm::{ModuleInstance, Store};
4929
//!
5030
//! // Load a module from bytes
@@ -62,12 +42,15 @@
6242
//!
6343
//! // # Get a typed handle to the exported "add" function
6444
//! // Alternatively, you can use `instance.func_untyped` to get an untyped handle
65-
//! // that takes and returns [`WasmValue`]s
66-
//! let func = instance.func::<(i32, i32), i32>(&mut store, "add")?;
45+
//! // that takes and returns [`types::WasmValue`]s
46+
//! let func = instance.func::<(i32, i32), i32>(&store, "add")?;
6747
//! let res = func.call(&mut store, (1, 2))?;
6848
//!
6949
//! assert_eq!(res, 3);
70-
//! # Ok::<(), tinywasm::Error>(())
50+
//! # Ok(())
51+
//! # }
52+
//! # #[cfg(not(feature = "parser"))]
53+
//! # fn main() {}
7154
//! ```
7255
//!
7356
//! For non-default runtime behavior, construct a [`Store`] with a custom [`Engine`]
@@ -76,6 +59,21 @@
7659
//!
7760
//! For more examples, see the [`examples`](https://github.com/explodingcamera/tinywasm/tree/main/examples) directory.
7861
//!
62+
//! ## Cargo features
63+
//!
64+
//! - **`std`:** Enables `std` and parsing from files and streams. Enabled by default.
65+
//! - **`log`:** Enables integration with the `log` crate. Enabled by default.
66+
//! - **`parser`:** Enables `tinywasm-parser` and top-level parse helpers. Enabled by default.
67+
//! - **`archive`:** Enables serialization and deserialization of the internal `twasm` format. Enabled by default.
68+
//! - **`canonicalize-nans`:** Canonicalizes NaN values. Enabled by default.
69+
//! - **`debug`:** Derives `Debug` for runtime types. Enabled by default.
70+
//! - **`parallel-parser`:** Parallelizes function parsing and validation when `std` is enabled. Enabled by default.
71+
//! - **`guest-debug`:** Exposes module-internal by-index inspection APIs (`*_by_index`).
72+
//! - **`simd-x86`:** Enables x86-specific SIMD intrinsics and uses `unsafe` internally.
73+
//!
74+
//! With default features disabled, `tinywasm` depends only on `core`, `alloc`, and `libm`,
75+
//! making it usable in `no_std + alloc` environments with a custom allocator.
76+
//!
7977
//! ## Imports
8078
//!
8179
//! To provide imports to a module, you can use the [`Imports`] struct.

‎crates/tinywasm/src/reference.rs‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,29 @@ impl Memory {
167167
/// Creates a cursor positioned at the start of this memory.
168168
///
169169
/// Available with the `std` feature enabled.
170+
///
171+
/// ## Example
172+
///
173+
/// ```rust
174+
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
175+
/// use std::io::{Read, Seek, SeekFrom, Write};
176+
/// use tinywasm::types::MemoryType;
177+
/// use tinywasm::{Memory, Store};
178+
///
179+
/// let mut store = Store::default();
180+
/// let memory = Memory::new(&mut store, MemoryType::default().with_page_count_initial(1))?;
181+
/// let mut cursor = memory.cursor(&mut store)?;
182+
///
183+
/// cursor.seek(SeekFrom::Start(2))?;
184+
/// cursor.write_all(b"abc")?;
185+
/// cursor.seek(SeekFrom::Start(0))?;
186+
///
187+
/// let mut bytes = [0; 5];
188+
/// cursor.read_exact(&mut bytes)?;
189+
/// assert_eq!(bytes, [0, 0, b'a', b'b', b'c']);
190+
/// # Ok(())
191+
/// # }
192+
/// ```
170193
#[cfg(feature = "std")]
171194
pub fn cursor<'a>(&self, store: &'a mut Store) -> Result<MemoryCursor<'a>> {
172195
self.cursor_at(store, 0)

‎crates/tinywasm/src/store/memory/mod.rs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub use {lazy::LazyLinearMemory, paged::PagedMemory, vec_memory::VecMemory};
2323
/// This is a low-level trait that abstracts over the actual storage mechanism for linear memory.
2424
/// This will probably change in the future to allow more efficient implementations.
2525
/// See [`MemoryBackend`] for a higher-level interface to configuring memory storage.
26+
/// The runtime passes slices of the exact indicated width to the fixed-width `write_*` methods.
2627
pub trait LinearMemory {
2728
/// Returns the current memory length in bytes.
2829
fn len(&self) -> usize;
@@ -285,12 +286,13 @@ impl MemoryBackend {
285286

286287
/// Uses sparse chunked storage for each memory instance.
287288
///
288-
/// `chunk_size` is the backend chunk size in bytes. It is independent from the Wasm page size.
289+
/// `chunk_size` is the backend chunk size in bytes. It must be a non-zero power
290+
/// of two and is independent from the Wasm page size.
289291
///
290292
/// This generally makes growth cheaper than [`Self::vec`], but read and write operations do a
291293
/// little more work and may be slightly slower.
292294
pub fn paged(chunk_size: usize) -> Self {
293-
assert!(chunk_size != 0, "chunk_size must be greater than zero");
295+
assert!(chunk_size.is_power_of_two(), "chunk_size must be a non-zero power of two");
294296
Self(MemoryBackendInner::Paged { chunk_size })
295297
}
296298

‎crates/types/src/archive.rs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ impl Display for TwasmError {
4545
impl core::error::Error for TwasmError {}
4646

4747
impl Module {
48-
/// Creates a [`Module`] from a slice of bytes.
48+
/// Creates a [`Module`] from internal `twasm` archive bytes.
49+
///
50+
/// Archives are version-specific and are not validated as untrusted input.
51+
/// Only load archives from a trusted source.
4952
pub fn try_from_twasm(wasm: &[u8]) -> Result<Self, TwasmError> {
5053
let len = validate_magic(wasm)?;
5154
postcard::from_bytes(&wasm[len..]).map_err(TwasmError::InvalidArchive)

0 commit comments

Comments
 (0)