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 #ifdef WASMTIME_FEATURE_WAT
45   /**
46    * \brief Compiles a component from the WebAssembly text format.
47    *
48    * This function will automatically use `wat2wasm` on the input and then
49    * delegate to the #compile function.
50    */
compile(Engine & engine,std::string_view wat)51   static Result<Component> compile(Engine &engine, std::string_view wat) {
52     auto wasm = wat2wasm(wat);
53     if (!wasm) {
54       return wasm.err();
55     }
56     auto bytes = wasm.ok();
57     return compile(engine, bytes);
58   }
59 #endif // WASMTIME_FEATURE_WAT
60 
61   /**
62    * \brief Compiles a component from the WebAssembly binary format.
63    *
64    * This function compiles the provided WebAssembly binary specified by `wasm`
65    * within the compilation settings configured by `engine`. This method is
66    * synchronous and will not return until the component has finished compiling.
67    *
68    * This function can fail if the WebAssembly binary is invalid or doesn't
69    * validate (or similar). Note that this API does not compile WebAssembly
70    * modules, which is done with `Module` instead of `Component`.
71    */
compile(Engine & engine,Span<uint8_t> wasm)72   static Result<Component> compile(Engine &engine, Span<uint8_t> wasm) {
73     wasmtime_component_t *ret = nullptr;
74     auto *error =
75         wasmtime_component_new(engine.capi(), wasm.data(), wasm.size(), &ret);
76     if (error != nullptr) {
77       return Error(error);
78     }
79     return Component(ret);
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    * component 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    */
deserialize(Engine & engine,Span<uint8_t> wasm)95   static Result<Component> deserialize(Engine &engine, Span<uint8_t> wasm) {
96     wasmtime_component_t *ret = nullptr;
97     auto *error = wasmtime_component_deserialize(engine.capi(), wasm.data(),
98                                                  wasm.size(), &ret);
99     if (error != nullptr) {
100       return Error(error);
101     }
102     return Component(ret);
103   }
104 
105   /**
106    * \brief Deserializes a component from an on-disk file.
107    *
108    * This function is the same as `deserialize` except that it reads the data
109    * for the serialized component 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    */
deserialize_file(Engine & engine,const std::string & path)117   static Result<Component> deserialize_file(Engine &engine,
118                                             const std::string &path) {
119     wasmtime_component_t *ret = nullptr;
120     auto *error =
121         wasmtime_component_deserialize_file(engine.capi(), path.c_str(), &ret);
122     if (error != nullptr) {
123       return Error(error);
124     }
125     return Component(ret);
126   }
127 
128 #ifdef WASMTIME_FEATURE_COMPILER
129   /**
130    * \brief Serializes this component to a list of bytes.
131    *
132    * The returned bytes can then be used to later pass to `deserialize` to
133    * quickly recreate this component in a different process perhaps.
134    */
serialize() const135   Result<std::vector<uint8_t>> serialize() const {
136     wasm_byte_vec_t bytes;
137     auto *error = wasmtime_component_serialize(ptr.get(), &bytes);
138     if (error != nullptr) {
139       return Error(error);
140     }
141     std::vector<uint8_t> ret;
142     Span<uint8_t> raw(reinterpret_cast<uint8_t *>(bytes.data), bytes.size);
143     ret.assign(raw.begin(), raw.end());
144     wasm_byte_vec_delete(&bytes);
145     return ret;
146   }
147 #endif // WASMTIME_FEATURE_COMPILER
148 
149   /**
150    * \brief Returns the export index for the export named `name` in this
151    * component.
152    *
153    * The `instance` argument is an optionally provided index which is the
154    * instance under which the `name` should be looked up.
155    */
export_index(ExportIndex * instance,std::string_view name)156   std::optional<ExportIndex> export_index(ExportIndex *instance,
157                                           std::string_view name) {
158     auto ret = wasmtime_component_get_export_index(
159         capi(), instance ? instance->capi() : nullptr, name.data(),
160         name.size());
161     if (ret) {
162       return ExportIndex(ret);
163     }
164     return std::nullopt;
165   };
166 
167   /// \brief Returns the type of this component.
type() const168   ComponentType type() const {
169     return ComponentType(wasmtime_component_type(ptr.get()));
170   }
171 };
172 
173 } // namespace component
174 } // namespace wasmtime
175 
176 #endif // WASMTIME_FEATURE_COMPONENT_MODEL
177 
178 #endif // WASMTIME_COMPONENT_COMPONENT_HH
179