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