Coverage Report

Created: 2026-07-28 15:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/src/lib.rs
Line
Count
Source
1
//! An in-place interpreter for WebAssembly 2.0
2
//!
3
//! # General Usage
4
//!
5
//! WebAssembly (Wasm) modules must first be decoded and validated through [`decode_and_validate`],
6
//! producing a [`Module`]. This module can then be instantiated in a [`Store`] via
7
//! [`Store::module_instantiate`], creating a module instance and returning its module address,
8
//! uniquely identifying this module instance within that store.
9
//!
10
//! When a [`Store`] is initially created through [`Store::new`], it is empty. This store exposes
11
//! many other functions besides module instantiation to interact with it and objects allocated
12
//! within it. Most notably, the [`Store::invoke_simple`] and [`Store::invoke`] methods are used to
13
//! interpret Wasm code. Refer to the examples in `examples/` for more information.
14
//!
15
//! # Example
16
//!
17
//! This is an example for how to run a function exposed from a simple Wasm module (full code in
18
//! `examples/function_invocation.rs`):
19
//!
20
//! ```
21
//! # use dlr_wasm_interpreter::{ExternVal, FuncAddr, InstantiationOutcome, Module, Store, Value, decode_and_validate};
22
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
23
//! const WAT_CODE: &str = r#"
24
//! (module
25
//!     (func (export "add_one") (param $n i32) (result i32)
26
//!         local.get $n
27
//!         i32.const 1
28
//!         i32.add))
29
//! "#;
30
//!
31
//! // Use the `wat` crate to convert from the text format to bytecode
32
//! let wasm_bytecode = wat::parse_str(WAT_CODE)?;
33
//!
34
//! // Decode and validate the module
35
//! let module = decode_and_validate(&wasm_bytecode, &mut ())?;
36
//!
37
//! // Create a new empty store
38
//! let mut store = Store::new(());
39
//!
40
//! // Instantiate the module to create a module instance, returning its address
41
//! // SAFETY: There are no extern values.
42
//! let module_addr = unsafe { store.module_instantiate(&module, vec![], None) }?.module_addr;
43
//!
44
//! // Get the function address of the exported add_one function
45
//! // SAFETY: The module address was returned from the same store.
46
//! let add_one_extern = unsafe { store.instance_export(module_addr, "add_one") }?;
47
//! let add_one = add_one_extern.as_func().ok_or("add_one is not a function")?;
48
//!
49
//! // Invoke the function
50
//! // SAFETY: The function address was returned from the same store. There are also no address
51
//! // type parameters.
52
//! let return_values = unsafe { store.invoke_simple(add_one, vec![Value::I32(16)]) }?;
53
//! assert_eq!(*return_values, [Value::I32(17)]);
54
//! # Ok(())
55
//! # }
56
//! ```
57
//!
58
//! # Optional Features
59
//!
60
//! - `log`: Enables logging (enables `log` dependency).
61
62
#![no_std]
63
64
extern crate alloc;
65
66
pub use crate::{
67
    core::{
68
        decoding::{error::DecodingError, modules::custom_section::CustomSection},
69
        rw_spinlock,
70
        structure::instructions,
71
        structure::types::{
72
            ExternType, FuncType, GlobalType, Limits, MemType, NumType, RefType, ResultType,
73
            TableType, ValType,
74
        },
75
    },
76
    execution::{
77
        config::Config,
78
        error::{RuntimeError, TrapError},
79
        resumable::*,
80
        runtime_structure::{
81
            addresses::*,
82
            external_values::ExternVal,
83
            store::{Hostcode, InstantiationOutcome, Store},
84
            values::{ExternAddr, Ref, Value, ValueTypeMismatchError, F32, F64},
85
        },
86
    },
87
    validation::{config::ValidationConfig, decode_and_validate, error::ValidationError, Module},
88
};
89
90
pub(crate) mod core;
91
pub(crate) mod execution;
92
pub(crate) mod validation;
93
94
/// A definition for a [`Result`] using the optional [`Error`] type.
95
pub type Result<T> = ::core::result::Result<T, Error>;
96
97
/// An opt-in error type useful for merging all error types of this crate into a single type.
98
///
99
/// Note: This crate does not use this type in any public interfaces, making it optional for downstream users.
100
#[derive(Debug, PartialEq, Eq)]
101
pub enum Error {
102
    Validation(ValidationError),
103
    RuntimeError(RuntimeError),
104
}
105
106
impl From<ValidationError> for Error {
107
1
    fn from(value: ValidationError) -> Self {
108
1
        Self::Validation(value)
109
1
    }
110
}
111
112
impl From<RuntimeError> for Error {
113
1
    fn from(value: RuntimeError) -> Self {
114
1
        Self::RuntimeError(value)
115
1
    }
116
}
117
118
#[cfg(test)]
119
mod test {
120
    use crate::{core::decoding::error::DecodingError, Error, RuntimeError, ValidationError};
121
122
    #[test]
123
1
    fn error_conversion_validation_error() {
124
1
        let validation_error = ValidationError::Decoding(DecodingError::InvalidMagic);
125
1
        let error: Error = validation_error.into();
126
127
1
        assert_eq!(
128
            error,
129
            Error::Validation(ValidationError::Decoding(DecodingError::InvalidMagic))
130
        )
131
1
    }
132
133
    #[test]
134
1
    fn error_conversion_runtime_error() {
135
1
        let runtime_error = RuntimeError::ModuleNotFound;
136
1
        let error: Error = runtime_error.into();
137
138
1
        assert_eq!(error, Error::RuntimeError(RuntimeError::ModuleNotFound))
139
1
    }
140
}