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