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.
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-semanitcs 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 *
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.
133   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.
138   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 
148   static void transfer(Raw &&from, Raw &to) {
149     to = from;
150     from.size = 0;
151     from.data = nullptr;
152   }
153 
154   void copy(const Raw &other) {
155     wasmtime_component_valrecord_copy(&raw, &other);
156   }
157 
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.
165   size_t size() const { return raw.size; }
166 
167   /// \brief Returns an iterator to the beginning of the record fields.
168   const RecordField *begin() const { return RecordField::from_capi(raw.data); }
169 
170   /// \brief Returns an iterator to the end of the record fields.
171   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 
182   static void transfer(Raw &&from, Raw &to) {
183     to = from;
184     from.size = 0;
185     from.data = nullptr;
186   }
187 
188   void copy(const Raw &other) { wasmtime_component_vallist_copy(&raw, &other); }
189 
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.
197   size_t size() const { return raw.size; }
198 
199   /// \brief Returns an iterator to the beginning of the list.
200   const Val *begin() const { return reinterpret_cast<const Val *>(raw.data); }
201 
202   /// \brief Returns an iterator to the end of the list.
203   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 
214   static void transfer(Raw &&from, Raw &to) {
215     to = from;
216     from.size = 0;
217     from.data = nullptr;
218   }
219 
220   void copy(const Raw &other) {
221     wasmtime_component_valtuple_copy(&raw, &other);
222   }
223 
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.
231   size_t size() const { return raw.size; }
232 
233   /// \brief Returns an iterator to the beginning of the tuple.
234   const Val *begin() const { return reinterpret_cast<const Val *>(raw.data); }
235 
236   /// \brief Returns an iterator to the end of the tuple.
237   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 
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 
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 
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.
277   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.
282   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 
291   static void transfer(Raw &&from, Raw &to) {
292     to = from;
293     from = nullptr;
294   }
295 
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 
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.
313   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 
322   static void transfer(Raw &&from, Raw &to) {
323     to = from;
324     from.val = nullptr;
325   }
326 
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 
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.
351   bool is_ok() const { return raw.is_ok; }
352 
353   /// Returns the optional payload value associated with this result.
354   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 
363   static void transfer(Raw &&from, Raw &to) {
364     to = from;
365     from.size = 0;
366     from.data = nullptr;
367   }
368 
369   void copy(const Raw &other) { wasm_name_copy(&raw, &other); }
370 
371   void destroy() { wasm_name_delete(&raw); }
372 
373 public:
374   /// Creates a new flag from the provided string.
375   Flag(std::string_view name) { wasm_name_new(&raw, name.size(), name.data()); }
376 
377   /// \brief Returns the name of this flag.
378   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 
387   static void transfer(Raw &&from, Raw &to) {
388     to = from;
389     from.size = 0;
390     from.data = nullptr;
391   }
392 
393   void copy(const Raw &other) {
394     wasmtime_component_valflags_copy(&raw, &other);
395   }
396 
397   void destroy() { wasmtime_component_valflags_delete(&raw); }
398 
399 public:
400   /// Creates a new flags value from the provided 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.
409   size_t size() const { return raw.size; }
410 
411   /// \brief Returns an iterator to the beginning of the flags.
412   const Flag *begin() const { return reinterpret_cast<const Flag *>(raw.data); }
413 
414   /// \brief Returns an iterator to the end of the flags.
415   const Flag *end() const {
416     return reinterpret_cast<const Flag *>(raw.data + raw.size);
417   }
418 };
419 
420 class ResourceHost;
421 
422 /// Class representing a component model `resource` value which is either a
423 /// guest or host-defined resource.
424 class ResourceAny {
425   WASMTIME_CLONE_WRAPPER(ResourceAny, wasmtime_component_resource_any);
426 
427   /// \brief Returns whether this resource is owned.
428   bool owned() const { return wasmtime_component_resource_any_owned(capi()); }
429 
430   /// \brief Returns the type of this resource.
431   ResourceType type() const {
432     wasmtime_component_resource_type_t *ty =
433         wasmtime_component_resource_any_type(capi());
434     return ResourceType(ty);
435   }
436 
437   /// \brief Drops this resource in the component-model sense, cleaning up
438   /// borrow state and executing the wasm destructor, if any.
439   Result<std::monostate> drop(Store::Context cx) const {
440     wasmtime_error_t *err =
441         wasmtime_component_resource_any_drop(cx.capi(), capi());
442     if (err)
443       return Error(err);
444     return std::monostate();
445   }
446 
447   /// \brief Attempts to convert this resource to a host-defined resource.
448   Result<ResourceHost> to_host(Store::Context cx) const;
449 };
450 
451 /// Class representing a component model `resource` value which is a host-owned
452 /// resource.
453 class ResourceHost {
454   WASMTIME_CLONE_WRAPPER(ResourceHost, wasmtime_component_resource_host);
455 
456   /// \brief Creates a new host-defined resource with the specified `owned`,
457   /// `rep`, and `ty` identifiers.
458   ResourceHost(bool owned, uint32_t rep, uint32_t ty)
459       : ptr(wasmtime_component_resource_host_new(owned, rep, ty)) {}
460 
461   /// \brief Returns whether this resource is owned.
462   bool owned() const { return wasmtime_component_resource_host_owned(capi()); }
463 
464   /// \brief Returns the "rep" identifier associated with this resource.
465   uint32_t rep() const { return wasmtime_component_resource_host_rep(capi()); }
466 
467   /// \brief Returns the "type" identifier associated with this resource.
468   uint32_t type() const {
469     return wasmtime_component_resource_host_type(capi());
470   }
471 
472   /// \brief Converts this host-defined resource into a generic resource-any.
473   Result<ResourceAny> to_any(Store::Context cx) const {
474     wasmtime_component_resource_any_t *out;
475     wasmtime_error_t *err =
476         wasmtime_component_resource_host_to_any(cx.capi(), capi(), &out);
477     if (err)
478       return Error(err);
479     return ResourceAny(out);
480   }
481 };
482 
483 inline Result<ResourceHost> ResourceAny::to_host(Store::Context cx) const {
484   wasmtime_component_resource_host_t *out;
485   wasmtime_error_t *err =
486       wasmtime_component_resource_any_to_host(cx.capi(), capi(), &out);
487   if (err)
488     return Error(err);
489   return ResourceHost(out);
490 }
491 
492 /**
493  * \brief Class representing an instantiated WebAssembly component.
494  */
495 class Val {
496   friend class Variant;
497   friend class WitOption;
498   friend class WitResult;
499 
500   VAL_REPR(Val, wasmtime_component_val_t);
501 
502   static void transfer(Raw &&from, Raw &to) {
503     to = from;
504     from.kind = WASMTIME_COMPONENT_BOOL;
505     from.of.boolean = false;
506   }
507 
508   void copy(const Raw &other) { wasmtime_component_val_clone(&other, &raw); }
509 
510   void destroy() { wasmtime_component_val_delete(&raw); }
511 
512 public:
513   /// Creates a new boolean value.
514   Val(bool v) {
515     raw.kind = WASMTIME_COMPONENT_BOOL;
516     raw.of.boolean = v;
517   }
518 
519   /// Creates a new u8 value.
520   Val(uint8_t v) {
521     raw.kind = WASMTIME_COMPONENT_U8;
522     raw.of.u8 = v;
523   }
524 
525   /// Creates a new s8 value.
526   Val(int8_t v) {
527     raw.kind = WASMTIME_COMPONENT_S8;
528     raw.of.s8 = v;
529   }
530 
531   /// Creates a new u16 value.
532   Val(uint16_t v) {
533     raw.kind = WASMTIME_COMPONENT_U16;
534     raw.of.u16 = v;
535   }
536 
537   /// Creates a new s16 value.
538   Val(int16_t v) {
539     raw.kind = WASMTIME_COMPONENT_S16;
540     raw.of.s16 = v;
541   }
542 
543   /// Creates a new u32 value.
544   Val(uint32_t v) {
545     raw.kind = WASMTIME_COMPONENT_U32;
546     raw.of.u32 = v;
547   }
548 
549   /// Creates a new s32 value.
550   Val(int32_t v) {
551     raw.kind = WASMTIME_COMPONENT_S32;
552     raw.of.s32 = v;
553   }
554 
555   /// Creates a new u64 value.
556   Val(uint64_t v) {
557     raw.kind = WASMTIME_COMPONENT_U64;
558     raw.of.u64 = v;
559   }
560 
561   /// Creates a new s64 value.
562   Val(int64_t v) {
563     raw.kind = WASMTIME_COMPONENT_S64;
564     raw.of.s64 = v;
565   }
566 
567   /// Creates a new f32 value.
568   Val(float v) {
569     raw.kind = WASMTIME_COMPONENT_F32;
570     raw.of.f32 = v;
571   }
572 
573   /// Creates a new f64 value.
574   Val(double v) {
575     raw.kind = WASMTIME_COMPONENT_F64;
576     raw.of.f64 = v;
577   }
578 
579   /// Creates a new char value.
580   static Val char_(uint32_t v) {
581     wasmtime_component_val_t raw = {
582         .kind = WASMTIME_COMPONENT_CHAR,
583         .of = {.character = v},
584     };
585     return Val(std::move(raw));
586   }
587 
588   /// Creates a new string value.
589   static Val string(std::string_view v) {
590     wasmtime_component_val_t raw;
591     raw.kind = WASMTIME_COMPONENT_STRING;
592     wasm_byte_vec_new(&raw.of.string, v.size(), v.data());
593     return Val(std::move(raw));
594   }
595 
596   /// Creates a new list value.
597   Val(List v) {
598     raw.kind = WASMTIME_COMPONENT_LIST;
599     List::transfer(std::move(v.raw), raw.of.list);
600   }
601 
602   /// Creates a new record value.
603   Val(Record r) {
604     raw.kind = WASMTIME_COMPONENT_RECORD;
605     Record::transfer(std::move(r.raw), raw.of.record);
606   }
607 
608   /// Creates a new tuple value.
609   Val(Tuple v) {
610     raw.kind = WASMTIME_COMPONENT_TUPLE;
611     Tuple::transfer(std::move(v.raw), raw.of.tuple);
612   }
613 
614   /// Creates a new variant value.
615   Val(Variant v) {
616     raw.kind = WASMTIME_COMPONENT_VARIANT;
617     Variant::transfer(std::move(v.raw), raw.of.variant);
618   }
619 
620   /// Creates a new option value.
621   Val(WitOption v) {
622     raw.kind = WASMTIME_COMPONENT_OPTION;
623     WitOption::transfer(std::move(v.raw), raw.of.option);
624   }
625 
626   /// Creates a new result value.
627   Val(WitResult r) {
628     raw.kind = WASMTIME_COMPONENT_RESULT;
629     WitResult::transfer(std::move(r.raw), raw.of.result);
630   }
631 
632   /// Creates a new enum value.
633   static Val enum_(std::string_view discriminant) {
634     wasmtime_component_val_t raw;
635     raw.kind = WASMTIME_COMPONENT_ENUM;
636     wasm_byte_vec_new(&raw.of.enumeration, discriminant.size(),
637                       discriminant.data());
638     return Val(std::move(raw));
639   }
640 
641   /// Creates a new flags value.
642   Val(Flags f) {
643     raw.kind = WASMTIME_COMPONENT_FLAGS;
644     Flags::transfer(std::move(f.raw), raw.of.flags);
645   }
646 
647   /// Creates a new resource value.
648   Val(ResourceAny r) {
649     raw.kind = WASMTIME_COMPONENT_RESOURCE;
650     raw.of.resource = r.capi_release();
651   }
652 
653   /// \brief Returns whether this value is a boolean.
654   bool is_bool() const { return raw.kind == WASMTIME_COMPONENT_BOOL; }
655 
656   /// \brief Returns the boolean value, only valid if `is_bool()`.
657   bool get_bool() const {
658     assert(is_bool());
659     return raw.of.boolean;
660   }
661 
662   /// \brief Returns whether this value is a u8.
663   bool is_u8() const { return raw.kind == WASMTIME_COMPONENT_U8; }
664 
665   /// \brief Returns the u8 value, only valid if `is_u8()`.
666   uint8_t get_u8() const {
667     assert(is_u8());
668     return raw.of.u8;
669   }
670 
671   /// \brief Returns whether this value is a s8.
672   bool is_s8() const { return raw.kind == WASMTIME_COMPONENT_S8; }
673 
674   /// \brief Returns the s8 value, only valid if `is_s8()`.
675   int8_t get_s8() const {
676     assert(is_s8());
677     return raw.of.s8;
678   }
679 
680   /// \brief Returns whether this value is a u16.
681   bool is_u16() const { return raw.kind == WASMTIME_COMPONENT_U16; }
682 
683   /// \brief Returns the u16 value, only valid if `is_u16()`.
684   uint16_t get_u16() const {
685     assert(is_u16());
686     return raw.of.u16;
687   }
688 
689   /// \brief Returns whether this value is a s16.
690   bool is_s16() const { return raw.kind == WASMTIME_COMPONENT_S16; }
691 
692   /// \brief Returns the s16 value, only valid if `is_s16()`.
693   int16_t get_s16() const {
694     assert(is_s16());
695     return raw.of.s16;
696   }
697 
698   /// \brief Returns whether this value is a u32.
699   bool is_u32() const { return raw.kind == WASMTIME_COMPONENT_U32; }
700 
701   /// \brief Returns the u32 value, only valid if `is_u32()`.
702   uint32_t get_u32() const {
703     assert(is_u32());
704     return raw.of.u32;
705   }
706 
707   /// \brief Returns whether this value is a s32.
708   bool is_s32() const { return raw.kind == WASMTIME_COMPONENT_S32; }
709 
710   /// \brief Returns the s32 value, only valid if `is_s32()`.
711   int32_t get_s32() const {
712     assert(is_s32());
713     return raw.of.s32;
714   }
715 
716   /// \brief Returns whether this value is a u64.
717   bool is_u64() const { return raw.kind == WASMTIME_COMPONENT_U64; }
718 
719   /// \brief Returns the u64 value, only valid if `is_u64()`.
720   uint64_t get_u64() const {
721     assert(is_u64());
722     return raw.of.u64;
723   }
724 
725   /// \brief Returns whether this value is a s64.
726   bool is_s64() const { return raw.kind == WASMTIME_COMPONENT_S64; }
727 
728   /// \brief Returns the s64 value, only valid if `is_s64()`.
729   int64_t get_s64() const {
730     assert(is_s64());
731     return raw.of.s64;
732   }
733 
734   /// \brief Returns whether this value is a f32.
735   bool is_f32() const { return raw.kind == WASMTIME_COMPONENT_F32; }
736 
737   /// \brief Returns the f32 value, only valid if `is_f32()`.
738   float get_f32() const {
739     assert(is_f32());
740     return raw.of.f32;
741   }
742 
743   /// \brief Returns whether this value is a f64.
744   bool is_f64() const { return raw.kind == WASMTIME_COMPONENT_F64; }
745 
746   /// \brief Returns the f64 value, only valid if `is_f64()`.
747   double get_f64() const {
748     assert(is_f64());
749     return raw.of.f64;
750   }
751 
752   /// \brief Returns whether this value is a string.
753   bool is_string() const { return raw.kind == WASMTIME_COMPONENT_STRING; }
754 
755   /// \brief Returns the string value, only valid if `is_string()`.
756   std::string_view get_string() const {
757     assert(is_string());
758     return std::string_view(raw.of.string.data, raw.of.string.size);
759   }
760 
761   /// \brief Returns whether this value is a list.
762   bool is_list() const { return raw.kind == WASMTIME_COMPONENT_LIST; }
763 
764   /// \brief Returns the list value, only valid if `is_list()`.
765   const List &get_list() const {
766     assert(is_list());
767     return *List::from_capi(&raw.of.list);
768   }
769 
770   /// \brief Returns whether this value is a record.
771   bool is_record() const { return raw.kind == WASMTIME_COMPONENT_RECORD; }
772 
773   /// \brief Returns the record value, only valid if `is_record()`.
774   const Record &get_record() const {
775     assert(is_record());
776     return *Record::from_capi(&raw.of.record);
777   }
778 
779   /// \brief Returns whether this value is a tuple.
780   bool is_tuple() const { return raw.kind == WASMTIME_COMPONENT_TUPLE; }
781 
782   /// \brief Returns the tuple value, only valid if `is_tuple()`.
783   const Tuple &get_tuple() const {
784     assert(is_tuple());
785     return *Tuple::from_capi(&raw.of.tuple);
786   }
787 
788   /// \brief Returns whether this value is a variant.
789   bool is_variant() const { return raw.kind == WASMTIME_COMPONENT_VARIANT; }
790 
791   /// \brief Returns the variant value, only valid if `is_variant()`.
792   const Variant &get_variant() const {
793     assert(is_variant());
794     return *Variant::from_capi(&raw.of.variant);
795   }
796 
797   /// \brief Returns whether this value is an option.
798   bool is_option() const { return raw.kind == WASMTIME_COMPONENT_OPTION; }
799 
800   /// \brief Returns the option value, only valid if `is_option()`.
801   const WitOption &get_option() const {
802     assert(is_option());
803     return *WitOption::from_capi(&raw.of.option);
804   }
805 
806   /// \brief Returns whether this value is an enum.
807   bool is_enum() const { return raw.kind == WASMTIME_COMPONENT_ENUM; }
808 
809   /// \brief Returns the enum discriminant, only valid if `is_enum()`.
810   std::string_view get_enum() const {
811     assert(is_enum());
812     return std::string_view(raw.of.enumeration.data, raw.of.enumeration.size);
813   }
814 
815   /// \brief Returns whether this value is a result.
816   bool is_result() const { return raw.kind == WASMTIME_COMPONENT_RESULT; }
817 
818   /// \brief Returns the result value, only valid if `is_result()`.
819   const WitResult &get_result() const {
820     assert(is_result());
821     return *WitResult::from_capi(&raw.of.result);
822   }
823 
824   /// \brief Returns whether this value is flags.
825   bool is_flags() const { return raw.kind == WASMTIME_COMPONENT_FLAGS; }
826 
827   /// \brief Returns the flags value, only valid if `is_flags()`.
828   const Flags &get_flags() const {
829     assert(is_flags());
830     return *Flags::from_capi(&raw.of.flags);
831   }
832 
833   /// \brief Returns whether this value is a resource.
834   bool is_resource() const { return raw.kind == WASMTIME_COMPONENT_RESOURCE; }
835 
836   /// \brief Returns the flags value, only valid if `is_flags()`.
837   const ResourceAny &get_resource() const {
838     assert(is_resource());
839     return *ResourceAny::from_capi(&raw.of.resource);
840   }
841 };
842 
843 #undef VAL_REPR
844 
845 inline Record::Record(std::vector<std::pair<std::string_view, Val>> entries) {
846   wasmtime_component_valrecord_new_uninit(&raw, entries.size());
847   auto dst = raw.data;
848   for (auto &&[name, val] : entries) {
849     wasm_byte_vec_new(&dst->name, name.size(), name.data());
850     new (&dst->val) Val(std::move(val));
851     dst++;
852   }
853 }
854 
855 inline List::List(std::vector<Val> values) {
856   wasmtime_component_vallist_new_uninit(&raw, values.size());
857   auto dst = raw.data;
858   for (auto &&val : values)
859     new (dst++) Val(std::move(val));
860 }
861 
862 inline Tuple::Tuple(std::vector<Val> values) {
863   wasmtime_component_valtuple_new_uninit(&raw, values.size());
864   auto dst = raw.data;
865   for (auto &&val : values)
866     new (dst++) Val(std::move(val));
867 }
868 
869 inline Variant::Variant(std::string_view discriminant, std::optional<Val> x) {
870   wasm_name_new(&raw.discriminant, discriminant.size(), discriminant.data());
871   if (x) {
872     raw.val = wasmtime_component_val_new(&x->raw);
873   } else {
874     raw.val = nullptr;
875   }
876 }
877 
878 inline WitOption::WitOption(std::optional<Val> v) {
879   if (v) {
880     raw = wasmtime_component_val_new(&v->raw);
881   } else {
882     raw = nullptr;
883   }
884 }
885 
886 inline WitResult WitResult::ok(std::optional<Val> v) {
887   wasmtime_component_valresult_t raw;
888   raw.is_ok = true;
889   if (v) {
890     raw.val = wasmtime_component_val_new(&v->raw);
891   } else {
892     raw.val = nullptr;
893   }
894   return WitResult(std::move(raw));
895 }
896 
897 inline WitResult WitResult::err(std::optional<Val> v) {
898   wasmtime_component_valresult_t raw;
899   raw.is_ok = false;
900   if (v) {
901     raw.val = wasmtime_component_val_new(&v->raw);
902   } else {
903     raw.val = nullptr;
904   }
905   return WitResult(std::move(raw));
906 }
907 
908 } // namespace component
909 } // namespace wasmtime
910 
911 #endif // WASMTIME_FEATURE_COMPONENT_MODEL
912 
913 #endif // WASMTIME_COMPONENT_VAL_H
914