1 /** 2 * \file wasmtime/component/component.hh 3 */ 4 5 #ifndef WASMTIME_COMPONENT_HH 6 #define WASMTIME_COMPONENT_HH 7 8 #include <wasmtime/conf.h> 9 10 #ifdef WASMTIME_FEATURE_COMPONENT_MODEL 11 12 #include <memory> 13 #include <optional> 14 #include <string_view> 15 #include <vector> 16 #include <wasmtime/component/component.h> 17 #include <wasmtime/engine.hh> 18 #include <wasmtime/error.hh> 19 #include <wasmtime/span.hh> 20 #include <wasmtime/wat.hh> 21 22 namespace wasmtime { 23 namespace component { 24 25 /** 26 * \brief An index to an exported item within a particular component. 27 * 28 * This structure is acquired from a `Component` and used to lookup exports on 29 * instances. 30 */ 31 class ExportIndex { 32 friend class Component; 33 34 struct deleter { 35 void operator()(wasmtime_component_export_index_t *p) const { 36 wasmtime_component_export_index_delete(p); 37 } 38 }; 39 40 std::unique_ptr<wasmtime_component_export_index_t, deleter> ptr; 41 42 ExportIndex(wasmtime_component_export_index_t *raw) : ptr(raw) {} 43 44 public: 45 /// Copies another index into this one. 46 ExportIndex(const ExportIndex &other) 47 : ptr(wasmtime_component_export_index_clone(other.ptr.get())) {} 48 /// Copies another index into this one. 49 ExportIndex &operator=(const ExportIndex &other) { 50 ptr.reset(wasmtime_component_export_index_clone(other.ptr.get())); 51 return *this; 52 } 53 54 ~ExportIndex() = default; 55 /// Moves resources from another component into this one. 56 ExportIndex(ExportIndex &&other) = default; 57 /// Moves resources from another component into this one. 58 ExportIndex &operator=(ExportIndex &&other) = default; 59 60 /// \brief Returns the underlying C API pointer. 61 const wasmtime_component_export_index_t *capi() const { return ptr.get(); } 62 63 /// \brief Returns the underlying C API pointer. 64 wasmtime_component_export_index_t *capi() { return ptr.get(); } 65 }; 66 67 /** 68 * \brief Representation of a compiled WebAssembly component. 69 */ 70 class Component { 71 struct deleter { 72 void operator()(wasmtime_component_t *p) const { 73 wasmtime_component_delete(p); 74 } 75 }; 76 77 std::unique_ptr<wasmtime_component_t, deleter> ptr; 78 79 Component(wasmtime_component_t *raw) : ptr(raw) {} 80 81 public: 82 /// Copies another component into this one. 83 Component(const Component &other) 84 : ptr(wasmtime_component_clone(other.ptr.get())) {} 85 /// Copies another component into this one. 86 Component &operator=(const Component &other) { 87 ptr.reset(wasmtime_component_clone(other.ptr.get())); 88 return *this; 89 } 90 ~Component() = default; 91 /// Moves resources from another component into this one. 92 Component(Component &&other) = default; 93 /// Moves resources from another component into this one. 94 Component &operator=(Component &&other) = default; 95 96 /// \brief Returns the underlying C API pointer. 97 const wasmtime_component_t *capi() const { return ptr.get(); } 98 99 /// \brief Returns the underlying C API pointer. 100 wasmtime_component_t *capi() { return ptr.get(); } 101 102 #ifdef WASMTIME_FEATURE_COMPILER 103 /** 104 * \brief Compiles a component from the WebAssembly text format. 105 * 106 * This function will automatically use `wat2wasm` on the input and then 107 * delegate to the #compile function. 108 */ 109 static Result<Component> compile(Engine &engine, std::string_view wat) { 110 auto wasm = wat2wasm(wat); 111 if (!wasm) { 112 return wasm.err(); 113 } 114 auto bytes = wasm.ok(); 115 return compile(engine, bytes); 116 } 117 118 /** 119 * \brief Compiles a component from the WebAssembly binary format. 120 * 121 * This function compiles the provided WebAssembly binary specified by `wasm` 122 * within the compilation settings configured by `engine`. This method is 123 * synchronous and will not return until the component has finished compiling. 124 * 125 * This function can fail if the WebAssembly binary is invalid or doesn't 126 * validate (or similar). Note that this API does not compile WebAssembly 127 * modules, which is done with `Module` instead of `Component`. 128 */ 129 static Result<Component> compile(Engine &engine, Span<uint8_t> wasm) { 130 wasmtime_component_t *ret = nullptr; 131 auto *error = 132 wasmtime_component_new(engine.capi(), wasm.data(), wasm.size(), &ret); 133 if (error != nullptr) { 134 return Error(error); 135 } 136 return Component(ret); 137 } 138 #endif // WASMTIME_FEATURE_COMPILER 139 140 /** 141 * \brief Deserializes a previous list of bytes created with `serialize`. 142 * 143 * This function is intended to be much faster than `compile` where it uses 144 * the artifacts of a previous compilation to quickly create an in-memory 145 * component ready for instantiation. 146 * 147 * It is not safe to pass arbitrary input to this function, it is only safe to 148 * pass in output from previous calls to `serialize`. For more information see 149 * the Rust documentation - 150 * https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize 151 */ 152 static Result<Component> deserialize(Engine &engine, Span<uint8_t> wasm) { 153 wasmtime_component_t *ret = nullptr; 154 auto *error = wasmtime_component_deserialize(engine.capi(), wasm.data(), 155 wasm.size(), &ret); 156 if (error != nullptr) { 157 return Error(error); 158 } 159 return Component(ret); 160 } 161 162 /** 163 * \brief Deserializes a component from an on-disk file. 164 * 165 * This function is the same as `deserialize` except that it reads the data 166 * for the serialized component from the path on disk. This can be faster than 167 * the alternative which may require copying the data around. 168 * 169 * It is not safe to pass arbitrary input to this function, it is only safe to 170 * pass in output from previous calls to `serialize`. For more information see 171 * the Rust documentation - 172 * https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize 173 */ 174 static Result<Component> deserialize_file(Engine &engine, 175 const std::string &path) { 176 wasmtime_component_t *ret = nullptr; 177 auto *error = 178 wasmtime_component_deserialize_file(engine.capi(), path.c_str(), &ret); 179 if (error != nullptr) { 180 return Error(error); 181 } 182 return Component(ret); 183 } 184 185 #ifdef WASMTIME_FEATURE_COMPILER 186 /** 187 * \brief Serializes this component to a list of bytes. 188 * 189 * The returned bytes can then be used to later pass to `deserialize` to 190 * quickly recreate this component in a different process perhaps. 191 */ 192 Result<std::vector<uint8_t>> serialize() const { 193 wasm_byte_vec_t bytes; 194 auto *error = wasmtime_component_serialize(ptr.get(), &bytes); 195 if (error != nullptr) { 196 return Error(error); 197 } 198 std::vector<uint8_t> ret; 199 Span<uint8_t> raw(reinterpret_cast<uint8_t *>(bytes.data), bytes.size); 200 ret.assign(raw.begin(), raw.end()); 201 wasm_byte_vec_delete(&bytes); 202 return ret; 203 } 204 #endif // WASMTIME_FEATURE_COMPILER 205 206 /** 207 * \brief Returns the export index for the export named `name` in this 208 * component. 209 * 210 * The `instance` argument is an optionally provided index which is the 211 * instance under which the `name` should be looked up. 212 */ 213 std::optional<ExportIndex> export_index(ExportIndex *instance, 214 std::string_view name) { 215 auto ret = wasmtime_component_get_export_index( 216 capi(), instance ? instance->capi() : nullptr, name.data(), 217 name.size()); 218 if (ret) { 219 return ExportIndex(ret); 220 } 221 return std::nullopt; 222 }; 223 }; 224 225 } // namespace component 226 } // namespace wasmtime 227 228 #endif // WASMTIME_FEATURE_COMPONENT_MODEL 229 230 #endif // WASMTIME_COMPONENT_HH 231