1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/**
* \file wasmtime/module.hh
*/
#ifndef WASMTIME_MODULE_HH
#define WASMTIME_MODULE_HH
#include <memory>
#include <string_view>
#include <wasmtime/engine.hh>
#include <wasmtime/helpers.hh>
#include <wasmtime/module.h>
#include <wasmtime/span.hh>
#include <wasmtime/types/export.hh>
#include <wasmtime/types/import.hh>
#include <wasmtime/wat.hh>
namespace wasmtime {
/**
* \brief Representation of a compiled WebAssembly module.
*
* This type contains JIT code of a compiled WebAssembly module. A `Module` is
* connected to an `Engine` and can only be instantiated within that `Engine`.
* You can inspect a `Module` for its type information. This is passed as an
* argument to other APIs to instantiate it.
*/
class Module {
WASMTIME_CLONE_WRAPPER(Module, wasmtime_module);
#ifdef WASMTIME_FEATURE_COMPILER
#ifdef WASMTIME_FEATURE_WAT
/**
* \brief Compiles a module from the WebAssembly text format.
*
* This function will automatically use `wat2wasm` on the input and then
* delegate to the #compile function.
*/
static Result<Module> compile(Engine &engine, std::string_view wat) {
auto wasm = wat2wasm(wat);
if (!wasm) {
return wasm.err();
}
auto bytes = wasm.ok();
return compile(engine, bytes);
}
#endif // WASMTIME_FEATURE_WAT
/**
* \brief Compiles a module from the WebAssembly binary format.
*
* This function compiles the provided WebAssembly binary specified by `wasm`
* within the compilation settings configured by `engine`. This method is
* synchronous and will not return until the module has finished compiling.
*
* This function can fail if the WebAssembly binary is invalid or doesn't
* validate (or similar).
*/
static Result<Module> compile(Engine &engine, Span<uint8_t> wasm) {
wasmtime_module_t *ret = nullptr;
auto *error =
wasmtime_module_new(engine.capi(), wasm.data(), wasm.size(), &ret);
if (error != nullptr) {
return Error(error);
}
return Module(ret);
}
/**
* \brief Validates the provided WebAssembly binary without compiling it.
*
* This function will validate whether the provided binary is indeed valid
* within the compilation settings of the `engine` provided.
*/
static Result<std::monostate> validate(Engine &engine, Span<uint8_t> wasm) {
auto *error =
wasmtime_module_validate(engine.capi(), wasm.data(), wasm.size());
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
#endif // WASMTIME_FEATURE_COMPILER
/**
* \brief Deserializes a previous list of bytes created with `serialize`.
*
* This function is intended to be much faster than `compile` where it uses
* the artifacts of a previous compilation to quickly create an in-memory
* module ready for instantiation.
*
* It is not safe to pass arbitrary input to this function, it is only safe to
* pass in output from previous calls to `serialize`. For more information see
* the Rust documentation -
* https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize
*/
static Result<Module> deserialize(Engine &engine, Span<uint8_t> wasm) {
wasmtime_module_t *ret = nullptr;
auto *error = wasmtime_module_deserialize(engine.capi(), wasm.data(),
wasm.size(), &ret);
if (error != nullptr) {
return Error(error);
}
return Module(ret);
}
/**
* \brief Deserializes a module from an on-disk file.
*
* This function is the same as `deserialize` except that it reads the data
* for the serialized module from the path on disk. This can be faster than
* the alternative which may require copying the data around.
*
* It is not safe to pass arbitrary input to this function, it is only safe to
* pass in output from previous calls to `serialize`. For more information see
* the Rust documentation -
* https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize
*/
static Result<Module> deserialize_file(Engine &engine,
const std::string &path) {
wasmtime_module_t *ret = nullptr;
auto *error =
wasmtime_module_deserialize_file(engine.capi(), path.c_str(), &ret);
if (error != nullptr) {
return Error(error);
}
return Module(ret);
}
/// Returns the list of types imported by this module.
ImportType::List imports() const {
ImportType::List list;
wasmtime_module_imports(ptr.get(), &list.list);
return list;
}
/// Returns the list of types exported by this module.
ExportType::List exports() const {
ExportType::List list;
wasmtime_module_exports(ptr.get(), &list.list);
return list;
}
#ifdef WASMTIME_FEATURE_COMPILER
/**
* \brief Serializes this module to a list of bytes.
*
* The returned bytes can then be used to later pass to `deserialize` to
* quickly recreate this module in a different process perhaps.
*/
Result<std::vector<uint8_t>> serialize() const {
wasm_byte_vec_t bytes;
auto *error = wasmtime_module_serialize(ptr.get(), &bytes);
if (error != nullptr) {
return Error(error);
}
std::vector<uint8_t> ret;
// NOLINTNEXTLINE TODO can this be done without triggering lints?
Span<uint8_t> raw(reinterpret_cast<uint8_t *>(bytes.data), bytes.size);
ret.assign(raw.begin(), raw.end());
wasm_byte_vec_delete(&bytes);
return ret;
}
#endif // WASMTIME_FEATURE_COMPILER
};
} // namespace wasmtime
#endif // WASMTIME_MODULE_HH