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