1 /// \file wasmtime/component/val.hh
2 
3 #ifndef WASMTIME_COMPONENT_VAL_HH
4 #define WASMTIME_COMPONENT_VAL_HH
5 
6 #include <wasmtime/conf.h>
7 
8 #ifdef WASMTIME_FEATURE_COMPONENT_MODEL
9 
10 #include <assert.h>
11 #include <memory>
12 #include <optional>
13 #include <string_view>
14 #include <utility>
15 #include <vector>
16 #include <wasmtime/component/types/val.hh>
17 #include <wasmtime/component/val.h>
18 #include <wasmtime/store.hh>
19 
20 namespace wasmtime {
21 namespace component {
22 
23 class Val;
24 class Record;
25 
26 namespace detail {
27 
28 /// Internal helper to convert from C to `Val`, sort of a forward-declaration
29 /// of `Val::from_capi` which I don't know how to otherwise forward-declare.
val_from_capi(const wasmtime_component_val_t * capi)30 inline const Val *val_from_capi(const wasmtime_component_val_t *capi) {
31   return reinterpret_cast<const Val *>(capi);
32 }
33 
34 } // namespace detail
35 
36 /// Internal helper macro to define ownership-semantics for C++ types based on
37 /// a C type as a single member where operations are defined in terms of
38 /// `transfer`, `copy`, and `destroy` functions.
39 #define VAL_REPR(name, raw_type)                                               \
40 private:                                                                       \
41   using Raw = raw_type;                                                        \
42   Raw raw;                                                                     \
43                                                                                \
44 public:                                                                        \
45   /**                                                                          \
46    * Create a variant that takes ownership of the underlying C API variant.    \
47    */                                                                          \
48   explicit name(Raw &&capi) { name::transfer(std::move(capi), raw); }          \
49                                                                                \
50   /**                                                                          \
51    * Converts the raw C API representation to this class without taking        \
52    * ownership.                                                                \
53    */                                                                          \
54   static const name *from_capi(const Raw *capi) {                              \
55     return reinterpret_cast<const name *>(capi);                               \
56   }                                                                            \
57                                                                                \
58   /**                                                                          \
59    * Converts the raw C API representation to this class without taking        \
60    * ownership.                                                                \
61    */                                                                          \
62   static name *from_capi(Raw *capi) { return reinterpret_cast<name *>(capi); } \
63                                                                                \
64   /**                                                                          \
65    * Converts to the raw C API representation to this class without taking     \
66    * ownership.                                                                \
67    */                                                                          \
68   static const Raw *to_capi(const name *capi) {                                \
69     return reinterpret_cast<const Raw *>(capi);                                \
70   }                                                                            \
71                                                                                \
72   /**                                                                          \
73    * Converts to the raw C API representation to this class without taking     \
74    * ownership.                                                                \
75    */                                                                          \
76   static Raw *to_capi(name *capi) { return reinterpret_cast<Raw *>(capi); }    \
77                                                                                \
78   /**                                                                          \
79    * \brief Copy constructor to clone `other`.                                 \
80    */                                                                          \
81   name(const name &other) { copy(other.raw); }                                 \
82                                                                                \
83   /**                                                                          \
84    * \brief Copy assignment to clone from `other`.                             \
85    */                                                                          \
86   name &operator=(const name &other) {                                         \
87     destroy();                                                                 \
88     copy(other.raw);                                                           \
89     return *this;                                                              \
90   }                                                                            \
91                                                                                \
92   /**                                                                          \
93    * \brief Move constructor to move the contents of `other`.                  \
94    */                                                                          \
95   name(name &&other) { name::transfer(std::move(other.raw), raw); }            \
96                                                                                \
97   /**                                                                          \
98    * \brief Move assignment to move the contents of `other`.                   \
99    */                                                                          \
100   name &operator=(name &&other) {                                              \
101     destroy();                                                                 \
102     name::transfer(std::move(other.raw), raw);                                 \
103     return *this;                                                              \
104   }                                                                            \
105                                                                                \
106   ~name() { destroy(); }                                                       \
107                                                                                \
108   /**                                                                          \
109    * \brief Returns a pointer to the underlying C API representation.          \
110    */                                                                          \
111   const Raw *capi() const { return &raw; }                                     \
112                                                                                \
113 private:
114 
115 /// \brief Class representing a field in a record value.
116 class RecordField {
117   friend class Record;
118 
119   wasmtime_component_valrecord_entry_t entry;
120 
121   // This value can't be constructed or destructed, it's only used in iteration
122   // of `Record`.
123   RecordField() = delete;
124   ~RecordField() = delete;
125 
126   static const RecordField *
from_capi(const wasmtime_component_valrecord_entry_t * capi)127   from_capi(const wasmtime_component_valrecord_entry_t *capi) {
128     return reinterpret_cast<const RecordField *>(capi);
129   }
130 
131 public:
132   /// \brief Returns the name of this record field.
name() const133   std::string_view name() const {
134     return std::string_view{entry.name.data, entry.name.size};
135   }
136 
137   /// \brief Returns the value of this record field.
value() const138   const Val &value() const { return *detail::val_from_capi(&entry.val); }
139 };
140 
141 /// \brief Class representing a component model record, a list of name/value
142 /// pairs.
143 class Record {
144   friend class Val;
145 
146   VAL_REPR(Record, wasmtime_component_valrecord_t);
147 
transfer(Raw && from,Raw & to)148   static void transfer(Raw &&from, Raw &to) {
149     to = from;
150     from.size = 0;
151     from.data = nullptr;
152   }
153 
copy(const Raw & other)154   void copy(const Raw &other) {
155     wasmtime_component_valrecord_copy(&raw, &other);
156   }
157 
destroy()158   void destroy() { wasmtime_component_valrecord_delete(&raw); }
159 
160 public:
161   /// Creates a new record from the named field pairs provided.
162   Record(std::vector<std::pair<std::string_view, Val>> entries);
163 
164   /// \brief Returns the number of entries in the record.
size() const165   size_t size() const { return raw.size; }
166 
167   /// \brief Returns an iterator to the beginning of the record fields.
begin() const168   const RecordField *begin() const { return RecordField::from_capi(raw.data); }
169 
170   /// \brief Returns an iterator to the end of the record fields.
end() const171   const RecordField *end() const {
172     return RecordField::from_capi(raw.data + raw.size);
173   }
174 };
175 
176 /// \brief Class representing a component model list, a sequence of values.
177 class List {
178   friend class Val;
179 
180   VAL_REPR(List, wasmtime_component_vallist_t);
181 
transfer(Raw && from,Raw & to)182   static void transfer(Raw &&from, Raw &to) {
183     to = from;
184     from.size = 0;
185     from.data = nullptr;
186   }
187 
copy(const Raw & other)188   void copy(const Raw &other) { wasmtime_component_vallist_copy(&raw, &other); }
189 
destroy()190   void destroy() { wasmtime_component_vallist_delete(&raw); }
191 
192 public:
193   /// Creates a new list from the named field pairs provided.
194   List(std::vector<Val> entries);
195 
196   /// \brief Returns the number of entries in the list.
size() const197   size_t size() const { return raw.size; }
198 
199   /// \brief Returns an iterator to the beginning of the list.
begin() const200   const Val *begin() const { return reinterpret_cast<const Val *>(raw.data); }
201 
202   /// \brief Returns an iterator to the end of the list.
end() const203   const Val *end() const {
204     return reinterpret_cast<const Val *>(raw.data + raw.size);
205   }
206 };
207 
208 /// \brief Class representing a component model tuple.
209 class Tuple {
210   friend class Val;
211 
212   VAL_REPR(Tuple, wasmtime_component_valtuple_t);
213 
transfer(Raw && from,Raw & to)214   static void transfer(Raw &&from, Raw &to) {
215     to = from;
216     from.size = 0;
217     from.data = nullptr;
218   }
219 
copy(const Raw & other)220   void copy(const Raw &other) {
221     wasmtime_component_valtuple_copy(&raw, &other);
222   }
223 
destroy()224   void destroy() { wasmtime_component_valtuple_delete(&raw); }
225 
226 public:
227   /// Creates a new tuple from the named field pairs provided.
228   Tuple(std::vector<Val> entries);
229 
230   /// \brief Returns the number of entries in the tuple.
size() const231   size_t size() const { return raw.size; }
232 
233   /// \brief Returns an iterator to the beginning of the tuple.
begin() const234   const Val *begin() const { return reinterpret_cast<const Val *>(raw.data); }
235 
236   /// \brief Returns an iterator to the end of the tuple.
end() const237   const Val *end() const {
238     return reinterpret_cast<const Val *>(raw.data + raw.size);
239   }
240 };
241 
242 /// Class representing a component model `variant` value.
243 class Variant {
244   friend class Val;
245 
246   VAL_REPR(Variant, wasmtime_component_valvariant_t);
247 
transfer(wasmtime_component_valvariant_t && from,wasmtime_component_valvariant_t & to)248   static void transfer(wasmtime_component_valvariant_t &&from,
249                        wasmtime_component_valvariant_t &to) {
250     to = from;
251     from.discriminant.size = 0;
252     from.discriminant.data = nullptr;
253     from.val = nullptr;
254   }
255 
copy(const wasmtime_component_valvariant_t & other)256   void copy(const wasmtime_component_valvariant_t &other) {
257     wasm_name_copy(&raw.discriminant, &other.discriminant);
258     if (other.val) {
259       wasmtime_component_val_t clone;
260       wasmtime_component_val_clone(other.val, &clone);
261       raw.val = wasmtime_component_val_new(&clone);
262     } else {
263       raw.val = nullptr;
264     }
265   }
266 
destroy()267   void destroy() {
268     wasm_name_delete(&raw.discriminant);
269     wasmtime_component_val_free(raw.val);
270   }
271 
272 public:
273   /// Constructs a new variant value with the provided discriminant and payload.
274   Variant(std::string_view discriminant, std::optional<Val> x);
275 
276   /// Returns the name of the discriminant of this value.
discriminant() const277   std::string_view discriminant() const {
278     return std::string_view(raw.discriminant.data, raw.discriminant.size);
279   }
280 
281   /// Returns the optional payload value associated with this variant value.
value() const282   const Val *value() const { return detail::val_from_capi(raw.val); }
283 };
284 
285 /// Class representing a component model `option` value.
286 class WitOption {
287   friend class Val;
288 
289   VAL_REPR(WitOption, wasmtime_component_val_t *);
290 
transfer(Raw && from,Raw & to)291   static void transfer(Raw &&from, Raw &to) {
292     to = from;
293     from = nullptr;
294   }
295 
copy(const Raw & other)296   void copy(const Raw &other) {
297     if (other) {
298       wasmtime_component_val_t clone;
299       wasmtime_component_val_clone(other, &clone);
300       raw = wasmtime_component_val_new(&clone);
301     } else {
302       raw = nullptr;
303     }
304   }
305 
destroy()306   void destroy() { wasmtime_component_val_free(raw); }
307 
308 public:
309   /// Constructs a new option value with the provided value.
310   explicit WitOption(std::optional<Val> val);
311 
312   /// Returns the optional payload value associated with this option.
value() const313   const Val *value() const { return detail::val_from_capi(raw); }
314 };
315 
316 /// Class representing a component model `result` value.
317 class WitResult {
318   friend class Val;
319 
320   VAL_REPR(WitResult, wasmtime_component_valresult_t);
321 
transfer(Raw && from,Raw & to)322   static void transfer(Raw &&from, Raw &to) {
323     to = from;
324     from.val = nullptr;
325   }
326 
copy(const Raw & other)327   void copy(const Raw &other) {
328     raw.is_ok = other.is_ok;
329     if (other.val) {
330       wasmtime_component_val_t clone;
331       wasmtime_component_val_clone(other.val, &clone);
332       raw.val = wasmtime_component_val_new(&clone);
333     } else {
334       raw.val = nullptr;
335     }
336   }
337 
destroy()338   void destroy() {
339     if (raw.val)
340       wasmtime_component_val_free(raw.val);
341   }
342 
343 public:
344   /// Constructs a new result value with the `ok` variant.
345   static WitResult ok(std::optional<Val> val);
346 
347   /// Constructs a new result value with the `err` variant.
348   static WitResult err(std::optional<Val> val);
349 
350   /// \brief Returns whether this result is the `ok` variant.
is_ok() const351   bool is_ok() const { return raw.is_ok; }
352 
353   /// Returns the optional payload value associated with this result.
payload() const354   const Val *payload() const { return detail::val_from_capi(raw.val); }
355 };
356 
357 /// Class representing a component model `flags` value.
358 class Flag {
359   friend class Flags;
360 
361   VAL_REPR(Flag, wasm_name_t);
362 
transfer(Raw && from,Raw & to)363   static void transfer(Raw &&from, Raw &to) {
364     to = from;
365     from.size = 0;
366     from.data = nullptr;
367   }
368 
copy(const Raw & other)369   void copy(const Raw &other) { wasm_name_copy(&raw, &other); }
370 
destroy()371   void destroy() { wasm_name_delete(&raw); }
372 
373 public:
374   /// Creates a new flag from the provided string.
Flag(std::string_view name)375   Flag(std::string_view name) { wasm_name_new(&raw, name.size(), name.data()); }
376 
377   /// \brief Returns the name of this flag.
name() const378   std::string_view name() const { return std::string_view{raw.data, raw.size}; }
379 };
380 
381 /// Class representing a component model `flags` value.
382 class Flags {
383   friend class Val;
384 
385   VAL_REPR(Flags, wasmtime_component_valflags_t);
386 
transfer(Raw && from,Raw & to)387   static void transfer(Raw &&from, Raw &to) {
388     to = from;
389     from.size = 0;
390     from.data = nullptr;
391   }
392 
copy(const Raw & other)393   void copy(const Raw &other) {
394     wasmtime_component_valflags_copy(&raw, &other);
395   }
396 
destroy()397   void destroy() { wasmtime_component_valflags_delete(&raw); }
398 
399 public:
400   /// Creates a new flags value from the provided flags.
Flags(std::vector<Flag> flags)401   Flags(std::vector<Flag> flags) {
402     wasmtime_component_valflags_new_uninit(&raw, flags.size());
403     auto dst = raw.data;
404     for (auto &&val : flags)
405       Flag::transfer(std::move(val.raw), *dst++);
406   }
407 
408   /// \brief Returns the number of flags.
size() const409   size_t size() const { return raw.size; }
410 
411   /// \brief Returns an iterator to the beginning of the flags.
begin() const412   const Flag *begin() const { return reinterpret_cast<const Flag *>(raw.data); }
413 
414   /// \brief Returns an iterator to the end of the flags.
end() const415   const Flag *end() const {
416     return reinterpret_cast<const Flag *>(raw.data + raw.size);
417   }
418 };
419 
420 /// \brief Class representing an entry in a map value.
421 class MapEntry {
422   friend class Map;
423 
424   wasmtime_component_valmap_entry_t entry;
425 
426   // This value can't be constructed or destructed, it's only used in iteration
427   // of `Map`.
428   MapEntry() = delete;
429   ~MapEntry() = delete;
430 
431   static const MapEntry *
from_capi(const wasmtime_component_valmap_entry_t * capi)432   from_capi(const wasmtime_component_valmap_entry_t *capi) {
433     return reinterpret_cast<const MapEntry *>(capi);
434   }
435 
436 public:
437   /// \brief Returns the key of this map entry.
key() const438   const Val &key() const { return *detail::val_from_capi(&entry.key); }
439 
440   /// \brief Returns the value of this map entry.
value() const441   const Val &value() const { return *detail::val_from_capi(&entry.value); }
442 };
443 
444 /// \brief Class representing a component model map, a collection of key/value
445 /// pairs.
446 class Map {
447   friend class Val;
448 
449   VAL_REPR(Map, wasmtime_component_valmap_t);
450 
transfer(Raw && from,Raw & to)451   static void transfer(Raw &&from, Raw &to) {
452     to = from;
453     from.size = 0;
454     from.data = nullptr;
455   }
456 
copy(const Raw & other)457   void copy(const Raw &other) { wasmtime_component_valmap_copy(&raw, &other); }
458 
destroy()459   void destroy() { wasmtime_component_valmap_delete(&raw); }
460 
461 public:
462   /// Creates a new map from the key/value pairs provided.
463   Map(std::vector<std::pair<Val, Val>> entries);
464 
465   /// \brief Returns the number of entries in the map.
size() const466   size_t size() const { return raw.size; }
467 
468   /// \brief Returns an iterator to the beginning of the map entries.
begin() const469   const MapEntry *begin() const { return MapEntry::from_capi(raw.data); }
470 
471   /// \brief Returns an iterator to the end of the map entries.
end() const472   const MapEntry *end() const {
473     return MapEntry::from_capi(raw.data + raw.size);
474   }
475 };
476 
477 class ResourceHost;
478 
479 /// Class representing a component model `resource` value which is either a
480 /// guest or host-defined resource.
481 class ResourceAny {
482   WASMTIME_CLONE_WRAPPER(ResourceAny, wasmtime_component_resource_any);
483 
484   /// \brief Returns whether this resource is owned.
owned() const485   bool owned() const { return wasmtime_component_resource_any_owned(capi()); }
486 
487   /// \brief Returns the type of this resource.
type() const488   ResourceType type() const {
489     wasmtime_component_resource_type_t *ty =
490         wasmtime_component_resource_any_type(capi());
491     return ResourceType(ty);
492   }
493 
494   /// \brief Drops this resource in the component-model sense, cleaning up
495   /// borrow state and executing the wasm destructor, if any.
drop(Store::Context cx) const496   Result<std::monostate> drop(Store::Context cx) const {
497     wasmtime_error_t *err =
498         wasmtime_component_resource_any_drop(cx.capi(), capi());
499     if (err)
500       return Error(err);
501     return std::monostate();
502   }
503 
504   /// \brief Attempts to convert this resource to a host-defined resource.
505   Result<ResourceHost> to_host(Store::Context cx) const;
506 };
507 
508 /// Class representing a component model `resource` value which is a host-owned
509 /// resource.
510 class ResourceHost {
511   WASMTIME_CLONE_WRAPPER(ResourceHost, wasmtime_component_resource_host);
512 
513   /// \brief Creates a new host-defined resource with the specified `owned`,
514   /// `rep`, and `ty` identifiers.
ResourceHost(bool owned,uint32_t rep,uint32_t ty)515   ResourceHost(bool owned, uint32_t rep, uint32_t ty)
516       : ptr(wasmtime_component_resource_host_new(owned, rep, ty)) {}
517 
518   /// \brief Returns whether this resource is owned.
owned() const519   bool owned() const { return wasmtime_component_resource_host_owned(capi()); }
520 
521   /// \brief Returns the "rep" identifier associated with this resource.
rep() const522   uint32_t rep() const { return wasmtime_component_resource_host_rep(capi()); }
523 
524   /// \brief Returns the "type" identifier associated with this resource.
type() const525   uint32_t type() const {
526     return wasmtime_component_resource_host_type(capi());
527   }
528 
529   /// \brief Converts this host-defined resource into a generic resource-any.
to_any(Store::Context cx) const530   Result<ResourceAny> to_any(Store::Context cx) const {
531     wasmtime_component_resource_any_t *out;
532     wasmtime_error_t *err =
533         wasmtime_component_resource_host_to_any(cx.capi(), capi(), &out);
534     if (err)
535       return Error(err);
536     return ResourceAny(out);
537   }
538 };
539 
to_host(Store::Context cx) const540 inline Result<ResourceHost> ResourceAny::to_host(Store::Context cx) const {
541   wasmtime_component_resource_host_t *out;
542   wasmtime_error_t *err =
543       wasmtime_component_resource_any_to_host(cx.capi(), capi(), &out);
544   if (err)
545     return Error(err);
546   return ResourceHost(out);
547 }
548 
549 /**
550  * \brief Class representing an instantiated WebAssembly component.
551  */
552 class Val {
553   friend class Variant;
554   friend class WitOption;
555   friend class WitResult;
556 
557   VAL_REPR(Val, wasmtime_component_val_t);
558 
transfer(Raw && from,Raw & to)559   static void transfer(Raw &&from, Raw &to) {
560     to = from;
561     from.kind = WASMTIME_COMPONENT_BOOL;
562     from.of.boolean = false;
563   }
564 
copy(const Raw & other)565   void copy(const Raw &other) { wasmtime_component_val_clone(&other, &raw); }
566 
destroy()567   void destroy() { wasmtime_component_val_delete(&raw); }
568 
569 public:
570   /// Creates a new boolean value.
Val(bool v)571   Val(bool v) {
572     raw.kind = WASMTIME_COMPONENT_BOOL;
573     raw.of.boolean = v;
574   }
575 
576   /// Creates a new u8 value.
Val(uint8_t v)577   Val(uint8_t v) {
578     raw.kind = WASMTIME_COMPONENT_U8;
579     raw.of.u8 = v;
580   }
581 
582   /// Creates a new s8 value.
Val(int8_t v)583   Val(int8_t v) {
584     raw.kind = WASMTIME_COMPONENT_S8;
585     raw.of.s8 = v;
586   }
587 
588   /// Creates a new u16 value.
Val(uint16_t v)589   Val(uint16_t v) {
590     raw.kind = WASMTIME_COMPONENT_U16;
591     raw.of.u16 = v;
592   }
593 
594   /// Creates a new s16 value.
Val(int16_t v)595   Val(int16_t v) {
596     raw.kind = WASMTIME_COMPONENT_S16;
597     raw.of.s16 = v;
598   }
599 
600   /// Creates a new u32 value.
Val(uint32_t v)601   Val(uint32_t v) {
602     raw.kind = WASMTIME_COMPONENT_U32;
603     raw.of.u32 = v;
604   }
605 
606   /// Creates a new s32 value.
Val(int32_t v)607   Val(int32_t v) {
608     raw.kind = WASMTIME_COMPONENT_S32;
609     raw.of.s32 = v;
610   }
611 
612   /// Creates a new u64 value.
Val(uint64_t v)613   Val(uint64_t v) {
614     raw.kind = WASMTIME_COMPONENT_U64;
615     raw.of.u64 = v;
616   }
617 
618   /// Creates a new s64 value.
Val(int64_t v)619   Val(int64_t v) {
620     raw.kind = WASMTIME_COMPONENT_S64;
621     raw.of.s64 = v;
622   }
623 
624   /// Creates a new f32 value.
Val(float v)625   Val(float v) {
626     raw.kind = WASMTIME_COMPONENT_F32;
627     raw.of.f32 = v;
628   }
629 
630   /// Creates a new f64 value.
Val(double v)631   Val(double v) {
632     raw.kind = WASMTIME_COMPONENT_F64;
633     raw.of.f64 = v;
634   }
635 
636   /// Creates a new char value.
char_(uint32_t v)637   static Val char_(uint32_t v) {
638     wasmtime_component_val_t raw = {
639         .kind = WASMTIME_COMPONENT_CHAR,
640         .of = {.character = v},
641     };
642     return Val(std::move(raw));
643   }
644 
645   /// Creates a new string value.
string(std::string_view v)646   static Val string(std::string_view v) {
647     wasmtime_component_val_t raw;
648     raw.kind = WASMTIME_COMPONENT_STRING;
649     wasm_byte_vec_new(&raw.of.string, v.size(), v.data());
650     return Val(std::move(raw));
651   }
652 
653   /// Creates a new list value.
Val(List v)654   Val(List v) {
655     raw.kind = WASMTIME_COMPONENT_LIST;
656     List::transfer(std::move(v.raw), raw.of.list);
657   }
658 
659   /// Creates a new record value.
Val(Record r)660   Val(Record r) {
661     raw.kind = WASMTIME_COMPONENT_RECORD;
662     Record::transfer(std::move(r.raw), raw.of.record);
663   }
664 
665   /// Creates a new tuple value.
Val(Tuple v)666   Val(Tuple v) {
667     raw.kind = WASMTIME_COMPONENT_TUPLE;
668     Tuple::transfer(std::move(v.raw), raw.of.tuple);
669   }
670 
671   /// Creates a new variant value.
Val(Variant v)672   Val(Variant v) {
673     raw.kind = WASMTIME_COMPONENT_VARIANT;
674     Variant::transfer(std::move(v.raw), raw.of.variant);
675   }
676 
677   /// Creates a new option value.
Val(WitOption v)678   Val(WitOption v) {
679     raw.kind = WASMTIME_COMPONENT_OPTION;
680     WitOption::transfer(std::move(v.raw), raw.of.option);
681   }
682 
683   /// Creates a new result value.
Val(WitResult r)684   Val(WitResult r) {
685     raw.kind = WASMTIME_COMPONENT_RESULT;
686     WitResult::transfer(std::move(r.raw), raw.of.result);
687   }
688 
689   /// Creates a new enum value.
enum_(std::string_view discriminant)690   static Val enum_(std::string_view discriminant) {
691     wasmtime_component_val_t raw;
692     raw.kind = WASMTIME_COMPONENT_ENUM;
693     wasm_byte_vec_new(&raw.of.enumeration, discriminant.size(),
694                       discriminant.data());
695     return Val(std::move(raw));
696   }
697 
698   /// Creates a new flags value.
Val(Flags f)699   Val(Flags f) {
700     raw.kind = WASMTIME_COMPONENT_FLAGS;
701     Flags::transfer(std::move(f.raw), raw.of.flags);
702   }
703 
704   /// Creates a new map value.
Val(Map m)705   Val(Map m) {
706     raw.kind = WASMTIME_COMPONENT_MAP;
707     Map::transfer(std::move(m.raw), raw.of.map);
708   }
709 
710   /// Creates a new resource value.
Val(ResourceAny r)711   Val(ResourceAny r) {
712     raw.kind = WASMTIME_COMPONENT_RESOURCE;
713     raw.of.resource = r.capi_release();
714   }
715 
716   /// \brief Returns whether this value is a boolean.
is_bool() const717   bool is_bool() const { return raw.kind == WASMTIME_COMPONENT_BOOL; }
718 
719   /// \brief Returns the boolean value, only valid if `is_bool()`.
get_bool() const720   bool get_bool() const {
721     assert(is_bool());
722     return raw.of.boolean;
723   }
724 
725   /// \brief Returns whether this value is a u8.
is_u8() const726   bool is_u8() const { return raw.kind == WASMTIME_COMPONENT_U8; }
727 
728   /// \brief Returns the u8 value, only valid if `is_u8()`.
get_u8() const729   uint8_t get_u8() const {
730     assert(is_u8());
731     return raw.of.u8;
732   }
733 
734   /// \brief Returns whether this value is a s8.
is_s8() const735   bool is_s8() const { return raw.kind == WASMTIME_COMPONENT_S8; }
736 
737   /// \brief Returns the s8 value, only valid if `is_s8()`.
get_s8() const738   int8_t get_s8() const {
739     assert(is_s8());
740     return raw.of.s8;
741   }
742 
743   /// \brief Returns whether this value is a u16.
is_u16() const744   bool is_u16() const { return raw.kind == WASMTIME_COMPONENT_U16; }
745 
746   /// \brief Returns the u16 value, only valid if `is_u16()`.
get_u16() const747   uint16_t get_u16() const {
748     assert(is_u16());
749     return raw.of.u16;
750   }
751 
752   /// \brief Returns whether this value is a s16.
is_s16() const753   bool is_s16() const { return raw.kind == WASMTIME_COMPONENT_S16; }
754 
755   /// \brief Returns the s16 value, only valid if `is_s16()`.
get_s16() const756   int16_t get_s16() const {
757     assert(is_s16());
758     return raw.of.s16;
759   }
760 
761   /// \brief Returns whether this value is a u32.
is_u32() const762   bool is_u32() const { return raw.kind == WASMTIME_COMPONENT_U32; }
763 
764   /// \brief Returns the u32 value, only valid if `is_u32()`.
get_u32() const765   uint32_t get_u32() const {
766     assert(is_u32());
767     return raw.of.u32;
768   }
769 
770   /// \brief Returns whether this value is a s32.
is_s32() const771   bool is_s32() const { return raw.kind == WASMTIME_COMPONENT_S32; }
772 
773   /// \brief Returns the s32 value, only valid if `is_s32()`.
get_s32() const774   int32_t get_s32() const {
775     assert(is_s32());
776     return raw.of.s32;
777   }
778 
779   /// \brief Returns whether this value is a u64.
is_u64() const780   bool is_u64() const { return raw.kind == WASMTIME_COMPONENT_U64; }
781 
782   /// \brief Returns the u64 value, only valid if `is_u64()`.
get_u64() const783   uint64_t get_u64() const {
784     assert(is_u64());
785     return raw.of.u64;
786   }
787 
788   /// \brief Returns whether this value is a s64.
is_s64() const789   bool is_s64() const { return raw.kind == WASMTIME_COMPONENT_S64; }
790 
791   /// \brief Returns the s64 value, only valid if `is_s64()`.
get_s64() const792   int64_t get_s64() const {
793     assert(is_s64());
794     return raw.of.s64;
795   }
796 
797   /// \brief Returns whether this value is a f32.
is_f32() const798   bool is_f32() const { return raw.kind == WASMTIME_COMPONENT_F32; }
799 
800   /// \brief Returns the f32 value, only valid if `is_f32()`.
get_f32() const801   float get_f32() const {
802     assert(is_f32());
803     return raw.of.f32;
804   }
805 
806   /// \brief Returns whether this value is a f64.
is_f64() const807   bool is_f64() const { return raw.kind == WASMTIME_COMPONENT_F64; }
808 
809   /// \brief Returns the f64 value, only valid if `is_f64()`.
get_f64() const810   double get_f64() const {
811     assert(is_f64());
812     return raw.of.f64;
813   }
814 
815   /// \brief Returns whether this value is a string.
is_string() const816   bool is_string() const { return raw.kind == WASMTIME_COMPONENT_STRING; }
817 
818   /// \brief Returns the string value, only valid if `is_string()`.
get_string() const819   std::string_view get_string() const {
820     assert(is_string());
821     return std::string_view(raw.of.string.data, raw.of.string.size);
822   }
823 
824   /// \brief Returns whether this value is a list.
is_list() const825   bool is_list() const { return raw.kind == WASMTIME_COMPONENT_LIST; }
826 
827   /// \brief Returns the list value, only valid if `is_list()`.
get_list() const828   const List &get_list() const {
829     assert(is_list());
830     return *List::from_capi(&raw.of.list);
831   }
832 
833   /// \brief Returns whether this value is a record.
is_record() const834   bool is_record() const { return raw.kind == WASMTIME_COMPONENT_RECORD; }
835 
836   /// \brief Returns the record value, only valid if `is_record()`.
get_record() const837   const Record &get_record() const {
838     assert(is_record());
839     return *Record::from_capi(&raw.of.record);
840   }
841 
842   /// \brief Returns whether this value is a tuple.
is_tuple() const843   bool is_tuple() const { return raw.kind == WASMTIME_COMPONENT_TUPLE; }
844 
845   /// \brief Returns the tuple value, only valid if `is_tuple()`.
get_tuple() const846   const Tuple &get_tuple() const {
847     assert(is_tuple());
848     return *Tuple::from_capi(&raw.of.tuple);
849   }
850 
851   /// \brief Returns whether this value is a variant.
is_variant() const852   bool is_variant() const { return raw.kind == WASMTIME_COMPONENT_VARIANT; }
853 
854   /// \brief Returns the variant value, only valid if `is_variant()`.
get_variant() const855   const Variant &get_variant() const {
856     assert(is_variant());
857     return *Variant::from_capi(&raw.of.variant);
858   }
859 
860   /// \brief Returns whether this value is an option.
is_option() const861   bool is_option() const { return raw.kind == WASMTIME_COMPONENT_OPTION; }
862 
863   /// \brief Returns the option value, only valid if `is_option()`.
get_option() const864   const WitOption &get_option() const {
865     assert(is_option());
866     return *WitOption::from_capi(&raw.of.option);
867   }
868 
869   /// \brief Returns whether this value is an enum.
is_enum() const870   bool is_enum() const { return raw.kind == WASMTIME_COMPONENT_ENUM; }
871 
872   /// \brief Returns the enum discriminant, only valid if `is_enum()`.
get_enum() const873   std::string_view get_enum() const {
874     assert(is_enum());
875     return std::string_view(raw.of.enumeration.data, raw.of.enumeration.size);
876   }
877 
878   /// \brief Returns whether this value is a result.
is_result() const879   bool is_result() const { return raw.kind == WASMTIME_COMPONENT_RESULT; }
880 
881   /// \brief Returns the result value, only valid if `is_result()`.
get_result() const882   const WitResult &get_result() const {
883     assert(is_result());
884     return *WitResult::from_capi(&raw.of.result);
885   }
886 
887   /// \brief Returns whether this value is flags.
is_flags() const888   bool is_flags() const { return raw.kind == WASMTIME_COMPONENT_FLAGS; }
889 
890   /// \brief Returns the flags value, only valid if `is_flags()`.
get_flags() const891   const Flags &get_flags() const {
892     assert(is_flags());
893     return *Flags::from_capi(&raw.of.flags);
894   }
895 
896   /// \brief Returns whether this value is a resource.
is_resource() const897   bool is_resource() const { return raw.kind == WASMTIME_COMPONENT_RESOURCE; }
898 
899   /// \brief Returns the resource value, only valid if `is_resource()`.
get_resource() const900   const ResourceAny &get_resource() const {
901     assert(is_resource());
902     return *ResourceAny::from_capi(&raw.of.resource);
903   }
904 
905   /// \brief Returns whether this value is a map.
is_map() const906   bool is_map() const { return raw.kind == WASMTIME_COMPONENT_MAP; }
907 
908   /// \brief Returns the map value, only valid if `is_map()`.
get_map() const909   const Map &get_map() const {
910     assert(is_map());
911     return *Map::from_capi(&raw.of.map);
912   }
913 };
914 
915 #undef VAL_REPR
916 
Record(std::vector<std::pair<std::string_view,Val>> entries)917 inline Record::Record(std::vector<std::pair<std::string_view, Val>> entries) {
918   wasmtime_component_valrecord_new_uninit(&raw, entries.size());
919   auto dst = raw.data;
920   for (auto &&[name, val] : entries) {
921     wasm_byte_vec_new(&dst->name, name.size(), name.data());
922     new (&dst->val) Val(std::move(val));
923     dst++;
924   }
925 }
926 
Map(std::vector<std::pair<Val,Val>> entries)927 inline Map::Map(std::vector<std::pair<Val, Val>> entries) {
928   wasmtime_component_valmap_new_uninit(&raw, entries.size());
929   auto dst = raw.data;
930   for (auto &&[key, val] : entries) {
931     new (&dst->key) Val(std::move(key));
932     new (&dst->value) Val(std::move(val));
933     dst++;
934   }
935 }
936 
List(std::vector<Val> values)937 inline List::List(std::vector<Val> values) {
938   wasmtime_component_vallist_new_uninit(&raw, values.size());
939   auto dst = raw.data;
940   for (auto &&val : values)
941     new (dst++) Val(std::move(val));
942 }
943 
Tuple(std::vector<Val> values)944 inline Tuple::Tuple(std::vector<Val> values) {
945   wasmtime_component_valtuple_new_uninit(&raw, values.size());
946   auto dst = raw.data;
947   for (auto &&val : values)
948     new (dst++) Val(std::move(val));
949 }
950 
Variant(std::string_view discriminant,std::optional<Val> x)951 inline Variant::Variant(std::string_view discriminant, std::optional<Val> x) {
952   wasm_name_new(&raw.discriminant, discriminant.size(), discriminant.data());
953   if (x) {
954     raw.val = wasmtime_component_val_new(&x->raw);
955   } else {
956     raw.val = nullptr;
957   }
958 }
959 
WitOption(std::optional<Val> v)960 inline WitOption::WitOption(std::optional<Val> v) {
961   if (v) {
962     raw = wasmtime_component_val_new(&v->raw);
963   } else {
964     raw = nullptr;
965   }
966 }
967 
ok(std::optional<Val> v)968 inline WitResult WitResult::ok(std::optional<Val> v) {
969   wasmtime_component_valresult_t raw;
970   raw.is_ok = true;
971   if (v) {
972     raw.val = wasmtime_component_val_new(&v->raw);
973   } else {
974     raw.val = nullptr;
975   }
976   return WitResult(std::move(raw));
977 }
978 
err(std::optional<Val> v)979 inline WitResult WitResult::err(std::optional<Val> v) {
980   wasmtime_component_valresult_t raw;
981   raw.is_ok = false;
982   if (v) {
983     raw.val = wasmtime_component_val_new(&v->raw);
984   } else {
985     raw.val = nullptr;
986   }
987   return WitResult(std::move(raw));
988 }
989 
990 } // namespace component
991 } // namespace wasmtime
992 
993 #endif // WASMTIME_FEATURE_COMPONENT_MODEL
994 
995 #endif // WASMTIME_COMPONENT_VAL_H
996