Skip to content

Commit fa89f32

Browse files
c-api: component-model: Enum and option values (#10858)
* c-api: component-model: Enum values * c-api: component-model: Option values
1 parent 0fabedf commit fa89f32

File tree

3 files changed

+163
-2
lines changed

3 files changed

+163
-2
lines changed

crates/c-api/include/wasmtime/component/val.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ typedef uint8_t wasmtime_component_valkind_t;
6565
/// \brief Value of #wasmtime_component_valkind_t meaning that
6666
/// #wasmtime_component_val_t is a variant
6767
#define WASMTIME_COMPONENT_VARIANT 16
68+
/// \brief Value of #wasmtime_component_valkind_t meaning that
69+
/// #wasmtime_component_val_t is a enum
70+
#define WASMTIME_COMPONENT_ENUM 17
71+
/// \brief Value of #wasmtime_component_valkind_t meaning that
72+
/// #wasmtime_component_val_t is a option
73+
#define WASMTIME_COMPONENT_OPTION 18
6874

6975
struct wasmtime_component_val;
7076
struct wasmtime_component_valrecord_entry;
@@ -144,6 +150,11 @@ typedef union {
144150
/// Field used if #wasmtime_component_val_t::kind is
145151
/// #WASMTIME_COMPONENT_VARIANT
146152
wasmtime_component_valvariant_t variant;
153+
/// Field used if #wasmtime_component_val_t::kind is #WASMTIME_COMPONENT_ENUM
154+
wasm_name_t enumeration;
155+
/// Field used if #wasmtime_component_val_t::kind is
156+
/// #WASMTIME_COMPONENT_OPTION
157+
struct wasmtime_component_val *option;
147158
} wasmtime_component_valunion_t;
148159

149160
/// \brief Represents possible runtime values which a component function can

crates/c-api/src/component/val.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ pub enum wasmtime_component_val_t {
166166
Record(wasmtime_component_valrecord_t),
167167
Tuple(wasmtime_component_valtuple_t),
168168
Variant(wasmtime_component_valvariant_t),
169+
Enum(wasm_name_t),
170+
Option(Option<Box<Self>>),
169171
}
170172

171173
impl Default for wasmtime_component_val_t {
@@ -199,6 +201,12 @@ impl From<&wasmtime_component_val_t> for Val {
199201
let (a, b) = x.into();
200202
Val::Variant(a, b)
201203
}
204+
wasmtime_component_val_t::Enum(x) => {
205+
Val::Enum(String::from_utf8(x.clone().take()).unwrap())
206+
}
207+
wasmtime_component_val_t::Option(x) => {
208+
Val::Option(x.as_ref().map(|x| Box::new(Val::from(x.as_ref()))))
209+
}
202210
}
203211
}
204212
}
@@ -225,8 +233,11 @@ impl From<&Val> for wasmtime_component_val_t {
225233
Val::Variant(discriminant, val) => {
226234
wasmtime_component_val_t::Variant((discriminant, val).into())
227235
}
228-
Val::Enum(_) => todo!(),
229-
Val::Option(_val) => todo!(),
236+
Val::Enum(x) => wasmtime_component_val_t::Enum(wasm_name_t::from_name(x.clone())),
237+
Val::Option(x) => wasmtime_component_val_t::Option(
238+
x.as_ref()
239+
.map(|x| Box::new(wasmtime_component_val_t::from(x.as_ref()))),
240+
),
230241
Val::Result(_val) => todo!(),
231242
Val::Flags(_items) => todo!(),
232243
Val::Resource(_resource_any) => todo!(),

crates/c-api/tests/component/values.cc

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <array>
77
#include <format>
8+
#include <optional>
89
#include <span>
910
#include <variant>
1011

@@ -546,6 +547,144 @@ local.get $res
546547
destroy(ctx);
547548
}
548549

550+
TEST(component, value_enum) {
551+
static const auto check = [](const wasmtime_component_val_t &val,
552+
std::string_view text) {
553+
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_ENUM);
554+
EXPECT_EQ(
555+
(std::string_view{val.of.enumeration.data, val.of.enumeration.size}),
556+
text);
557+
};
558+
559+
static const auto make =
560+
[](std::string_view text) -> wasmtime_component_val_t {
561+
auto ret = wasmtime_component_val_t{
562+
.kind = WASMTIME_COMPONENT_ENUM,
563+
};
564+
565+
wasm_name_new(&ret.of.enumeration, text.size(), text.data());
566+
567+
return ret;
568+
};
569+
570+
auto ctx = create(
571+
R"((enum "aa" "bb"))", R"(
572+
(param $x i32)
573+
(result i32)
574+
local.get $x
575+
call $do
576+
)",
577+
"(param i32) (result i32)",
578+
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
579+
size_t args_len, wasmtime_component_val_t *rets,
580+
size_t rets_len) -> wasmtime_error_t * {
581+
EXPECT_EQ(args_len, 1);
582+
check(args[0], "aa");
583+
584+
EXPECT_EQ(rets_len, 1);
585+
rets[0] = make("bb");
586+
587+
return nullptr;
588+
});
589+
590+
auto arg = make("aa");
591+
auto res = wasmtime_component_val_t{};
592+
593+
auto err =
594+
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
595+
CHECK_ERR(err);
596+
597+
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
598+
CHECK_ERR(err);
599+
600+
check(res, "bb");
601+
602+
wasmtime_component_val_delete(&arg);
603+
wasmtime_component_val_delete(&res);
604+
605+
destroy(ctx);
606+
}
607+
608+
TEST(component, value_option) {
609+
static const auto check = [](const wasmtime_component_val_t &val,
610+
std::optional<uint32_t> value) {
611+
EXPECT_EQ(val.kind, WASMTIME_COMPONENT_OPTION);
612+
613+
if (value.has_value()) {
614+
EXPECT_NE(val.of.option, nullptr);
615+
EXPECT_EQ(val.of.option->kind, WASMTIME_COMPONENT_U32);
616+
EXPECT_EQ(val.of.option->of.u32, *value);
617+
} else {
618+
EXPECT_EQ(val.of.option, nullptr);
619+
}
620+
};
621+
622+
static const auto make =
623+
[](std::optional<uint32_t> value) -> wasmtime_component_val_t {
624+
auto ret = wasmtime_component_val_t{
625+
.kind = WASMTIME_COMPONENT_OPTION,
626+
.of = {.option = nullptr},
627+
};
628+
629+
if (value.has_value()) {
630+
ret.of.option = wasmtime_component_val_new();
631+
*ret.of.option = wasmtime_component_val_t{
632+
.kind = WASMTIME_COMPONENT_U32,
633+
.of = {.u32 = *value},
634+
};
635+
}
636+
637+
return ret;
638+
};
639+
640+
auto ctx = create(
641+
R"((option u32))", R"(
642+
(param $x i32)
643+
(param $y i32)
644+
(result i32)
645+
(local $res i32)
646+
local.get $x
647+
local.get $y
648+
(call $realloc
649+
(i32.const 0)
650+
(i32.const 0)
651+
(i32.const 4)
652+
(i32.const 8))
653+
local.tee $res
654+
call $do
655+
local.get $res
656+
)",
657+
"(param i32 i32 i32)",
658+
+[](void *, wasmtime_context_t *, const wasmtime_component_val_t *args,
659+
size_t args_len, wasmtime_component_val_t *rets,
660+
size_t rets_len) -> wasmtime_error_t * {
661+
EXPECT_EQ(args_len, 1);
662+
check(args[0], 123);
663+
664+
EXPECT_EQ(rets_len, 1);
665+
rets[0] = make({});
666+
667+
return nullptr;
668+
});
669+
670+
auto arg = make(123);
671+
auto res = wasmtime_component_val_t{};
672+
673+
auto err =
674+
wasmtime_component_func_call(&ctx.func, ctx.context, &arg, 1, &res, 1);
675+
CHECK_ERR(err);
676+
677+
err = wasmtime_component_func_post_return(&ctx.func, ctx.context);
678+
CHECK_ERR(err);
679+
680+
check(res, {});
681+
682+
wasmtime_component_val_delete(&arg);
683+
wasmtime_component_val_delete(&res);
684+
685+
destroy(ctx);
686+
}
687+
549688
TEST(component, value_list_inner) {
550689
{
551690
auto x = wasmtime_component_val_t{

0 commit comments

Comments
 (0)