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