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