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