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