diff --git a/crates/c-api/include/wasmtime/component.h b/crates/c-api/include/wasmtime/component.h index ccb41ca52e4e..0eadb270ca2c 100644 --- a/crates/c-api/include/wasmtime/component.h +++ b/crates/c-api/include/wasmtime/component.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #endif // WASMTIME_COMPONENT_H diff --git a/crates/c-api/include/wasmtime/component.hh b/crates/c-api/include/wasmtime/component.hh index 422671d2bf90..b0e86c2f09e4 100644 --- a/crates/c-api/include/wasmtime/component.hh +++ b/crates/c-api/include/wasmtime/component.hh @@ -7,6 +7,7 @@ #include #include #include +#include #include #endif // WASMTIME_COMPONENT_HH diff --git a/crates/c-api/include/wasmtime/component/component.h b/crates/c-api/include/wasmtime/component/component.h index 595c040ab622..de22e7fd2b7c 100644 --- a/crates/c-api/include/wasmtime/component/component.h +++ b/crates/c-api/include/wasmtime/component/component.h @@ -4,6 +4,7 @@ #define WASMTIME_COMPONENT_COMPONENT_H #include +#include #include #include @@ -102,6 +103,15 @@ wasmtime_component_deserialize_file(const wasm_engine_t *engine, WASM_API_EXTERN wasmtime_component_t * wasmtime_component_clone(const wasmtime_component_t *component); +/** + * \brief Returns the type of this component. + * + * The returned pointer must be deallocatd with + * `wasmtime_component_type_delete`. + */ +WASM_API_EXTERN wasmtime_component_type_t * +wasmtime_component_type(const wasmtime_component_t *component); + /** * \brief Deletes a #wasmtime_component_t created by #wasmtime_component_new * diff --git a/crates/c-api/include/wasmtime/component/component.hh b/crates/c-api/include/wasmtime/component/component.hh index fc08945eefd5..0463516d19fd 100644 --- a/crates/c-api/include/wasmtime/component/component.hh +++ b/crates/c-api/include/wasmtime/component/component.hh @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -159,6 +160,11 @@ class Component { } return std::nullopt; }; + + /// \brief Returns the type of this component. + ComponentType type() const { + return ComponentType(wasmtime_component_type(ptr.get())); + } }; } // namespace component diff --git a/crates/c-api/include/wasmtime/component/func.h b/crates/c-api/include/wasmtime/component/func.h index b4586e03f9d3..7c871ba224fb 100644 --- a/crates/c-api/include/wasmtime/component/func.h +++ b/crates/c-api/include/wasmtime/component/func.h @@ -3,6 +3,7 @@ #ifndef WASMTIME_COMPONENT_FUNC_H #define WASMTIME_COMPONENT_FUNC_H +#include #include #include #include @@ -33,6 +34,14 @@ typedef struct wasmtime_component_func { uint32_t __private2; } wasmtime_component_func_t; +/// \brief Returns the type of this function. +/// +/// The caller must deallocate the returned pointer with +/// `wasmtime_component_func_type_delete`. +WASM_API_EXTERN wasmtime_component_func_type_t * +wasmtime_component_func_type(const wasmtime_component_func_t *func, + wasmtime_context_t *context); + /** * \brief Invokes \p func with the \p args given and returns the result. * diff --git a/crates/c-api/include/wasmtime/component/func.hh b/crates/c-api/include/wasmtime/component/func.hh index e0ed99cb4782..12437787d2a8 100644 --- a/crates/c-api/include/wasmtime/component/func.hh +++ b/crates/c-api/include/wasmtime/component/func.hh @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -54,6 +55,11 @@ public: } return std::monostate(); } + + /// \brief Returns the type of this function. + FuncType type(Store::Context cx) const { + return FuncType(wasmtime_component_func_type(&func, cx.capi())); + } }; } // namespace component diff --git a/crates/c-api/include/wasmtime/component/linker.h b/crates/c-api/include/wasmtime/component/linker.h index 19eaeb03dd9a..5a125f655ffe 100644 --- a/crates/c-api/include/wasmtime/component/linker.h +++ b/crates/c-api/include/wasmtime/component/linker.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -134,8 +135,8 @@ WASM_API_EXTERN wasmtime_error_t *wasmtime_component_linker_instance_add_module( /// Type of the callback used in #wasmtime_component_linker_instance_add_func typedef wasmtime_error_t *(*wasmtime_component_func_callback_t)( - void *, wasmtime_context_t *, const wasmtime_component_val_t *, size_t, - wasmtime_component_val_t *, size_t); + void *, wasmtime_context_t *, const wasmtime_component_func_type_t *, + wasmtime_component_val_t *, size_t, wasmtime_component_val_t *, size_t); /** * \brief Define a function within this instance. diff --git a/crates/c-api/include/wasmtime/component/linker.hh b/crates/c-api/include/wasmtime/component/linker.hh index 5ddbcc20167f..5606e9cb349c 100644 --- a/crates/c-api/include/wasmtime/component/linker.hh +++ b/crates/c-api/include/wasmtime/component/linker.hh @@ -61,15 +61,20 @@ private: template static wasmtime_error_t * raw_callback(void *env, wasmtime_context_t *store, - const wasmtime_component_val_t *args, size_t nargs, + const wasmtime_component_func_type_t *ty_const, + wasmtime_component_val_t *args, size_t nargs, wasmtime_component_val_t *results, size_t nresults) { static_assert(alignof(Val) == alignof(wasmtime_component_val_t)); static_assert(sizeof(Val) == sizeof(wasmtime_component_val_t)); + wasmtime_component_func_type_t *ty = + const_cast(ty_const); F *func = reinterpret_cast(env); - Span args_span(Val::from_capi(args), nargs); + Span args_span(Val::from_capi(args), nargs); Span results_span(Val::from_capi(results), nresults); Result result = - (*func)(Store::Context(store), args_span, results_span); + (*func)(Store::Context(store), *FuncType::from_capi(&ty), args_span, + results_span); + if (!result) { return result.err().capi_release(); } @@ -85,7 +90,7 @@ public: template , F, Store::Context, - Span, Span>, + const FuncType &, Span, Span>, bool> = true> Result add_func(std::string_view name, F &&f) { auto *error = wasmtime_component_linker_instance_add_func( diff --git a/crates/c-api/include/wasmtime/component/types.h b/crates/c-api/include/wasmtime/component/types.h new file mode 100644 index 000000000000..33604e4d012c --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types.h @@ -0,0 +1,13 @@ +/// \file wasmtime/component/types.h + +#ifndef WASMTIME_COMPONENT_TYPES_H +#define WASMTIME_COMPONENT_TYPES_H + +#include +#include +#include +#include +#include +#include + +#endif // WASMTIME_COMPONENT_TYPES_H diff --git a/crates/c-api/include/wasmtime/component/types.hh b/crates/c-api/include/wasmtime/component/types.hh new file mode 100644 index 000000000000..ee78e857608c --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types.hh @@ -0,0 +1,12 @@ +/// \file wasmtime/component/types.hh + +#ifndef WASMTIME_COMPONENT_TYPES_HH +#define WASMTIME_COMPONENT_TYPES_HH + +#include +#include +#include +#include +#include + +#endif // WASMTIME_COMPONENT_TYPES_HH diff --git a/crates/c-api/include/wasmtime/component/types/component.h b/crates/c-api/include/wasmtime/component/types/component.h new file mode 100644 index 000000000000..246495ab10f8 --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/component.h @@ -0,0 +1,162 @@ +/// \file wasmtime/component/types/component.h + +#ifndef WASMTIME_COMPONENT_TYPES_COMPONENT_H +#define WASMTIME_COMPONENT_TYPES_COMPONENT_H + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// \brief Represents the type of a WebAssembly component. +typedef struct wasmtime_component_type_t wasmtime_component_type_t; + +/// \brief Clones a component type. +/// +/// The returned pointer must be deallocated wit +/// h`wasmtime_component_type_delete`. +WASM_API_EXTERN +wasmtime_component_type_t * +wasmtime_component_type_clone(const wasmtime_component_type_t *ty); + +/// \brief Deallocates a component type. +WASM_API_EXTERN +void wasmtime_component_type_delete(wasmtime_component_type_t *ty); + +/// \brief Returns the number of imports of a component type. +WASM_API_EXTERN +size_t wasmtime_component_type_import_count(const wasmtime_component_type_t *ty, + const wasm_engine_t *engine); + +/// \brief Retrieves the import with the specified name. +/// +/// The returned `wasmtime_component_item_t` must be deallocated with +/// `wasmtime_component_item_delete`. +WASM_API_EXTERN +bool wasmtime_component_type_import_get(const wasmtime_component_type_t *ty, + const wasm_engine_t *engine, + const char *name, size_t name_len, + struct wasmtime_component_item_t *ret); + +/// \brief Retrieves the nth import. +/// +/// The returned `wasmtime_component_item_t` must be deallocated with +/// `wasmtime_component_item_delete`. +WASM_API_EXTERN +bool wasmtime_component_type_import_nth( + const wasmtime_component_type_t *ty, const wasm_engine_t *engine, + size_t nth, const char **name_ret, size_t *name_len_ret, + struct wasmtime_component_item_t *type_ret); + +/// \brief Returns the number of exports of a component type. +WASM_API_EXTERN +size_t wasmtime_component_type_export_count(const wasmtime_component_type_t *ty, + const wasm_engine_t *engine); + +/// \brief Retrieves the export with the specified name. +/// +/// The returned `wasmtime_component_item_t` must be deallocated with +/// `wasmtime_component_item_delete`. +WASM_API_EXTERN +bool wasmtime_component_type_export_get(const wasmtime_component_type_t *ty, + const wasm_engine_t *engine, + const char *name, size_t name_len, + struct wasmtime_component_item_t *ret); + +/// \brief Retrieves the nth export. +/// +/// The returned `wasmtime_component_item_t` must be deallocated with +/// `wasmtime_component_item_delete`. +WASM_API_EXTERN +bool wasmtime_component_type_export_nth( + const wasmtime_component_type_t *ty, const wasm_engine_t *engine, + size_t nth, const char **name_ret, size_t *name_len_ret, + struct wasmtime_component_item_t *type_ret); + +/// \brief Value of #wasmtime_component_item_kind_t meaning that +/// #wasmtime_component_item_t is a component. +#define WASMTIME_COMPONENT_ITEM_COMPONENT 0 +/// \brief Value of #wasmtime_component_item_kind_t meaning that +/// #wasmtime_component_item_t is a component instance. +#define WASMTIME_COMPONENT_ITEM_COMPONENT_INSTANCE 1 +/// \brief Value of #wasmtime_component_item_kind_t meaning that +/// #wasmtime_component_item_t is a module. +#define WASMTIME_COMPONENT_ITEM_MODULE 2 +/// \brief Value of #wasmtime_component_item_kind_t meaning that +/// #wasmtime_component_item_t is a component function. +#define WASMTIME_COMPONENT_ITEM_COMPONENT_FUNC 3 +/// \brief Value of #wasmtime_component_item_kind_t meaning that +/// #wasmtime_component_item_t is a resource. +#define WASMTIME_COMPONENT_ITEM_RESOURCE 4 +/// \brief Value of #wasmtime_component_item_kind_t meaning that +/// #wasmtime_component_item_t is a core function. +#define WASMTIME_COMPONENT_ITEM_CORE_FUNC 5 +/// \brief Value of #wasmtime_component_item_kind_t meaning that +/// #wasmtime_component_item_t is a type. +#define WASMTIME_COMPONENT_ITEM_TYPE 6 + +/// \brief Discriminant used in #wasmtime_component_item_t::kind +typedef uint8_t wasmtime_component_item_kind_t; + +/// \brief Represents a single item in a component's import or export list. +typedef union wasmtime_component_item_union { + /// Field used if #wasmtime_component_item_t::kind is + /// #WASMTIME_COMPONENT_ITEM_COMPONENT + wasmtime_component_type_t *component; + /// Field used if #wasmtime_component_item_t::kind is + /// #WASMTIME_COMPONENT_ITEM_COMPONENT_INSTANCE + wasmtime_component_instance_type_t *component_instance; + /// Field used if #wasmtime_component_item_t::kind is + /// #WASMTIME_COMPONENT_ITEM_MODULE + wasmtime_module_type_t *module; + /// Field used if #wasmtime_component_item_t::kind is + /// #WASMTIME_COMPONENT_ITEM_COMPONENT_FUNC + wasmtime_component_func_type_t *component_func; + /// Field used if #wasmtime_component_item_t::kind is + /// #WASMTIME_COMPONENT_ITEM_RESOURCE + wasmtime_component_resource_type_t *resource; + /// Field used if #wasmtime_component_item_t::kind is + /// #WASMTIME_COMPONENT_ITEM_CORE_FUNC + wasm_functype_t *core_func; + /// Field used if #wasmtime_component_item_t::kind is + /// #WASMTIME_COMPONENT_ITEM_TYPE + wasmtime_component_valtype_t type; +} wasmtime_component_item_union_t; + +/// \brief Represents a single item in a component's import or export list. +typedef struct wasmtime_component_item_t { + /// The type discriminant for the `of` union. + wasmtime_component_item_kind_t kind; + /// The actual item. + wasmtime_component_item_union_t of; +} wasmtime_component_item_t; + +/// \brief Clones a component item. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_item_delete`. +WASM_API_EXTERN +void wasmtime_component_item_clone(const wasmtime_component_item_t *item, + wasmtime_component_item_t *out); + +/// \brief Deallocates a component item. +WASM_API_EXTERN +void wasmtime_component_item_delete(wasmtime_component_item_t *ptr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_COMPONENT_H diff --git a/crates/c-api/include/wasmtime/component/types/component.hh b/crates/c-api/include/wasmtime/component/types/component.hh new file mode 100644 index 000000000000..365cf74268df --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/component.hh @@ -0,0 +1,269 @@ +/** + * \file wasmtime/component/types/component.hh + */ + +#ifndef WASMTIME_COMPONENT_TYPES_COMPONENT_HH +#define WASMTIME_COMPONENT_TYPES_COMPONENT_HH + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include +#include +#include +#include +#include +#include + +namespace wasmtime { + +namespace component { + +class ComponentItem; + +/** + * \brief Represents the type of a WebAssembly component. + */ +class ComponentType { + WASMTIME_CLONE_WRAPPER(ComponentType, wasmtime_component_type); + + /// Returns the number of imports of this component type. + size_t import_count(const Engine &engine) const { + return wasmtime_component_type_import_count(capi(), engine.capi()); + } + + /// Retrieves the import with the specified name. + std::optional import_get(const Engine &engine, + std::string_view name) const; + + /// Retrieves the nth import. + std::optional> + import_nth(const Engine &engine, size_t nth) const; + + /// Returns the number of exports of this component type. + size_t export_count(const Engine &engine) const { + return wasmtime_component_type_export_count(capi(), engine.capi()); + } + + /// Retrieves the export with the specified name. + std::optional export_get(const Engine &engine, + std::string_view name) const; + + /// Retrieves the nth export. + std::optional> + export_nth(const Engine &engine, size_t nth) const; +}; + +class ComponentInstanceType; +class ModuleType; +class FuncType; +class ResourceType; +class ValType; + +/** + * \brief Represents a single item in a component's import or export list. + */ +class ComponentItem { + wasmtime_component_item_t item; + +public: + /// Creates a component item from the raw C API representation. + explicit ComponentItem(wasmtime_component_item_t &&item) : item(item) { + item.kind = WASMTIME_COMPONENT_ITEM_TYPE; + item.of.type.kind = WASMTIME_COMPONENT_VALTYPE_BOOL; + } + + /// Copies another item into this one. + ComponentItem(const ComponentItem &other) { + wasmtime_component_item_clone(&other.item, &item); + } + + /// Copies another item into this one. + ComponentItem &operator=(const ComponentItem &other) { + wasmtime_component_item_delete(&item); + wasmtime_component_item_clone(&other.item, &item); + return *this; + } + + /// Moves another item into this one. + ComponentItem(ComponentItem &&other) : item(other.item) { + other.item.kind = WASMTIME_COMPONENT_ITEM_TYPE; + other.item.of.type.kind = WASMTIME_COMPONENT_VALTYPE_BOOL; + } + + /// Moves another item into this one. + ComponentItem &operator=(ComponentItem &&other) { + wasmtime_component_item_delete(&item); + item = other.item; + other.item.kind = WASMTIME_COMPONENT_ITEM_TYPE; + other.item.of.type.kind = WASMTIME_COMPONENT_VALTYPE_BOOL; + return *this; + } + + ~ComponentItem() { wasmtime_component_item_delete(&item); } + + /// Returns true if this is a component. + bool is_component() const { + return item.kind == WASMTIME_COMPONENT_ITEM_COMPONENT; + } + + /// Returns true if this is a component instance. + bool is_component_instance() const { + return item.kind == WASMTIME_COMPONENT_ITEM_COMPONENT_INSTANCE; + } + + /// Returns true if this is a module. + bool is_module() const { return item.kind == WASMTIME_COMPONENT_ITEM_MODULE; } + + /// Returns true if this is a component function. + bool is_component_func() const { + return item.kind == WASMTIME_COMPONENT_ITEM_COMPONENT_FUNC; + } + + /// Returns true if this is a resource. + bool is_resource() const { + return item.kind == WASMTIME_COMPONENT_ITEM_RESOURCE; + } + + /// Returns true if this is a core function. + bool is_core_func() const { + return item.kind == WASMTIME_COMPONENT_ITEM_CORE_FUNC; + } + + /// Returns true if this is a type. + bool is_type() const { return item.kind == WASMTIME_COMPONENT_ITEM_TYPE; } + + /// Returns the component type this item represents, asserting that this is + /// indeed a component. + const ComponentType &component() const { + assert(is_component()); + return *ComponentType::from_capi(&item.of.component); + } + + /// Returns the component instance type this item represents, asserting that + /// this is indeed a component instance. + const ComponentInstanceType &component_instance() const; + + /// Returns the module type this item represents, asserting that this is + /// indeed a module. + const ModuleType &module() const; + + /// Returns the component function type this item represents, asserting that + /// this is indeed a component function. + const FuncType &component_func() const; + + /// Returns the resource type this item represents, asserting that this is + /// indeed a resource. + const ResourceType &resource() const; + + /// Returns the core function type this item represents, asserting that this + /// is indeed a core function. + wasmtime::FuncType::Ref core_func() const { + assert(is_core_func()); + return item.of.core_func; + } + + /// Returns the type this item represents, asserting that this is + /// indeed a type. + const ValType &type() const; +}; + +} // namespace component +} // namespace wasmtime + +#include +#include +#include +#include + +inline std::optional +wasmtime::component::ComponentType::import_get(const wasmtime::Engine &engine, + std::string_view name) const { + wasmtime_component_item_t item; + bool found = wasmtime_component_type_import_get( + capi(), engine.capi(), name.data(), name.size(), &item); + if (!found) { + return std::nullopt; + } + return wasmtime::component::ComponentItem(std::move(item)); +} + +inline std::optional< + std::pair> +wasmtime::component::ComponentType::import_nth(const wasmtime::Engine &engine, + size_t nth) const { + wasmtime_component_item_t item; + const char *name_data; + size_t name_size; + bool found = wasmtime_component_type_import_nth( + capi(), engine.capi(), nth, &name_data, &name_size, &item); + if (!found) { + return std::nullopt; + } + return std::make_pair(std::string_view(name_data, name_size), + wasmtime::component::ComponentItem(std::move(item))); +} + +inline std::optional +wasmtime::component::ComponentType::export_get(const wasmtime::Engine &engine, + std::string_view name) const { + wasmtime_component_item_t item; + bool found = wasmtime_component_type_export_get( + capi(), engine.capi(), name.data(), name.size(), &item); + if (!found) { + return std::nullopt; + } + return wasmtime::component::ComponentItem(std::move(item)); +} + +inline std::optional< + std::pair> +wasmtime::component::ComponentType::export_nth(const wasmtime::Engine &engine, + size_t nth) const { + wasmtime_component_item_t item; + const char *name_data; + size_t name_size; + bool found = wasmtime_component_type_export_nth( + capi(), engine.capi(), nth, &name_data, &name_size, &item); + if (!found) { + return std::nullopt; + } + return std::make_pair(std::string_view(name_data, name_size), + wasmtime::component::ComponentItem(std::move(item))); +} + +inline const wasmtime::component::ComponentInstanceType & +wasmtime::component::ComponentItem::component_instance() const { + assert(is_component_instance()); + return *ComponentInstanceType::from_capi(&item.of.component_instance); +} + +inline const wasmtime::component::ModuleType & +wasmtime::component::ComponentItem::module() const { + assert(is_module()); + return *ModuleType::from_capi(&item.of.module); +} + +inline const wasmtime::component::FuncType & +wasmtime::component::ComponentItem::component_func() const { + assert(is_component_func()); + return *FuncType::from_capi(&item.of.component_func); +} + +inline const wasmtime::component::ResourceType & +wasmtime::component::ComponentItem::resource() const { + assert(is_resource()); + return *ResourceType::from_capi(&item.of.resource); +} + +inline const wasmtime::component::ValType & +wasmtime::component::ComponentItem::type() const { + assert(is_type()); + return *ValType::from_capi(&item.of.type); +} + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_COMPONENT_HH diff --git a/crates/c-api/include/wasmtime/component/types/func.h b/crates/c-api/include/wasmtime/component/types/func.h new file mode 100644 index 000000000000..7fcc03706bef --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/func.h @@ -0,0 +1,61 @@ +/// \file wasmtime/component/types/func.h + +#ifndef WASMTIME_COMPONENT_TYPES_FUNC_H +#define WASMTIME_COMPONENT_TYPES_FUNC_H + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// \brief Opaque type representing a component function type. +typedef struct wasmtime_component_func_type_t wasmtime_component_func_type_t; + +/// \brief Clones a component function type. +/// +/// The pointer returned from this function must be deallocated with +/// `wasmtime_component_func_type_delete`. +WASM_API_EXTERN +wasmtime_component_func_type_t * +wasmtime_component_func_type_clone(const wasmtime_component_func_type_t *ty); + +/// \brief Deallocates a component instance type. +WASM_API_EXTERN +void wasmtime_component_func_type_delete(wasmtime_component_func_type_t *ty); + +/// \brief Returns the number of parameters of a component function type. +WASM_API_EXTERN +size_t wasmtime_component_func_type_param_count( + const wasmtime_component_func_type_t *ty); + +/// \brief Retrieves the nth parameter. +/// +/// The `type_ret` return value must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN +bool wasmtime_component_func_type_param_nth( + const wasmtime_component_func_type_t *ty, size_t nth, const char **name_ret, + size_t *name_len_ret, wasmtime_component_valtype_t *type_ret); + +/// \brief Returns the result, if any, of this component function type. +/// +/// The `type_ret` return value must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN +bool wasmtime_component_func_type_result( + const wasmtime_component_func_type_t *ty, + wasmtime_component_valtype_t *type_ret); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_FUNC_H diff --git a/crates/c-api/include/wasmtime/component/types/func.hh b/crates/c-api/include/wasmtime/component/types/func.hh new file mode 100644 index 000000000000..0b8ff5690e9c --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/func.hh @@ -0,0 +1,58 @@ +/** + * \file wasmtime/component/types/func.hh + */ + +#ifndef WASMTIME_COMPONENT_TYPES_FUNC_HH +#define WASMTIME_COMPONENT_TYPES_FUNC_HH + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include + +namespace wasmtime { +namespace component { + +/** + * \brief Type information about a component function. + */ +class FuncType { + WASMTIME_CLONE_WRAPPER(FuncType, wasmtime_component_func_type); + + /// Returns the number of parameters of this component function type. + size_t param_count() const { + return wasmtime_component_func_type_param_count(ptr.get()); + } + + /// Retrieves the nth parameter. + std::optional> + param_nth(size_t nth) const { + const char *name_ptr = nullptr; + size_t name_len = 0; + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_func_type_param_nth(ptr.get(), nth, &name_ptr, + &name_len, &type_ret)) { + return std::make_pair(std::string_view(name_ptr, name_len), + ValType(std::move(type_ret))); + } + return std::nullopt; + } + + /// Returns the result type of this component function type, if any. + std::optional result() const { + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_func_type_result(ptr.get(), &type_ret)) { + return ValType(std::move(type_ret)); + } + return std::nullopt; + } +}; + +} // namespace component +} // namespace wasmtime + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_FUNC_HH diff --git a/crates/c-api/include/wasmtime/component/types/instance.h b/crates/c-api/include/wasmtime/component/types/instance.h new file mode 100644 index 000000000000..1d5a99e4c0ca --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/instance.h @@ -0,0 +1,65 @@ +/// \file wasmtime/component/types/instance.h + +#ifndef WASMTIME_COMPONENT_TYPES_INSTANCE_H +#define WASMTIME_COMPONENT_TYPES_INSTANCE_H + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct wasmtime_component_item_t; + +/// \brief Represents the type of a component instance. +typedef struct wasmtime_component_instance_type + wasmtime_component_instance_type_t; + +/// \brief Clones a component instance type. +/// +/// The pointer returned from this function must be deallocated with +/// `wasmtime_component_instance_type_delete`. +WASM_API_EXTERN +wasmtime_component_instance_type_t *wasmtime_component_instance_type_clone( + const wasmtime_component_instance_type_t *ty); + +/// \brief Deallocates a component instance type. +WASM_API_EXTERN +void wasmtime_component_instance_type_delete( + wasmtime_component_instance_type_t *ty); + +/// \brief Returns the number of exports of a component instance type. +WASM_API_EXTERN +size_t wasmtime_component_instance_type_export_count( + const wasmtime_component_instance_type_t *ty, const wasm_engine_t *engine); + +/// \brief Retrieves the export with the specified name. +/// +/// The returned `wasmtime_component_item_t` must be deallocated with +/// `wasmtime_component_item_delete`. +WASM_API_EXTERN +bool wasmtime_component_instance_type_export_get( + const wasmtime_component_instance_type_t *ty, const wasm_engine_t *engine, + const char *name, size_t name_len, struct wasmtime_component_item_t *ret); + +/// \brief Retrieves the nth export. +/// +/// The returned `wasmtime_component_item_t` must be deallocated with +/// `wasmtime_component_item_delete`. +WASM_API_EXTERN +bool wasmtime_component_instance_type_export_nth( + const wasmtime_component_instance_type_t *ty, const wasm_engine_t *engine, + size_t nth, const char **name_ret, size_t *name_len_ret, + struct wasmtime_component_item_t *type_ret); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_INSTANCE_H diff --git a/crates/c-api/include/wasmtime/component/types/instance.hh b/crates/c-api/include/wasmtime/component/types/instance.hh new file mode 100644 index 000000000000..d66854164374 --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/instance.hh @@ -0,0 +1,80 @@ +/** + * \file wasmtime/component/types/instance.hh + */ + +#ifndef WASMTIME_COMPONENT_TYPES_INSTANCE_HH +#define WASMTIME_COMPONENT_TYPES_INSTANCE_HH + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include +#include +#include +#include +#include + +namespace wasmtime { +namespace component { + +class ComponentItem; + +/** + * \brief Represents the type of a component instance. + */ +class ComponentInstanceType { + WASMTIME_CLONE_WRAPPER(ComponentInstanceType, + wasmtime_component_instance_type); + + /// Returns the number of exports of this component instance type. + size_t export_count(const Engine &engine) const { + return wasmtime_component_instance_type_export_count(capi(), engine.capi()); + } + + /// Retrieves the export with the specified name. + std::optional export_get(const Engine &engine, + std::string_view name) const; + + /// Retrieves the nth export. + std::optional> + export_nth(const Engine &engine, size_t nth) const; +}; + +} // namespace component +} // namespace wasmtime + +#include + +inline std::optional +wasmtime::component::ComponentInstanceType::export_get( + const wasmtime::Engine &engine, std::string_view name) const { + wasmtime_component_item_t item; + bool found = wasmtime_component_instance_type_export_get( + capi(), engine.capi(), name.data(), name.size(), &item); + if (!found) { + return std::nullopt; + } + return wasmtime::component::ComponentItem(std::move(item)); +} + +inline std::optional< + std::pair> +wasmtime::component::ComponentInstanceType::export_nth( + const wasmtime::Engine &engine, size_t nth) const { + wasmtime_component_item_t item; + const char *name_data; + size_t name_size; + bool found = wasmtime_component_instance_type_export_nth( + capi(), engine.capi(), nth, &name_data, &name_size, &item); + if (!found) { + return std::nullopt; + } + return std::make_pair(std::string_view(name_data, name_size), + wasmtime::component::ComponentItem(std::move(item))); +} + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_INSTANCE_HH diff --git a/crates/c-api/include/wasmtime/component/types/module.h b/crates/c-api/include/wasmtime/component/types/module.h new file mode 100644 index 000000000000..117d9a413de0 --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/module.h @@ -0,0 +1,65 @@ +/// \file wasmtime/component/types/module.h + +#ifndef WASMTIME_COMPONENT_TYPES_MODULE_H +#define WASMTIME_COMPONENT_TYPES_MODULE_H + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// \brief Represents the type of a module. +typedef struct wasmtime_module_type wasmtime_module_type_t; + +/// \brief Clones a module type. +/// +/// The pointer returned from this function must be deallocated with +/// `wasmtime_module_type_delete`. +WASM_API_EXTERN +wasmtime_module_type_t * +wasmtime_module_type_clone(const wasmtime_module_type_t *ty); + +/// \brief Deallocates a component instance type. +WASM_API_EXTERN +void wasmtime_module_type_delete(wasmtime_module_type_t *ty); + +/// \brief Returns the number of imports of a module type. +WASM_API_EXTERN +size_t wasmtime_module_type_import_count(const wasmtime_module_type_t *ty, + const wasm_engine_t *engine); + +/// \brief Retrieves the nth import. +/// +/// The returned `type_ret` pointer must be deallocated with +/// `wasm_importtype_delete`. +WASM_API_EXTERN +wasm_importtype_t * +wasmtime_module_type_import_nth(const wasmtime_module_type_t *ty, + const wasm_engine_t *engine, size_t nth); + +/// \brief Returns the number of exports of a module type. +WASM_API_EXTERN +size_t wasmtime_module_type_export_count(const wasmtime_module_type_t *ty, + const wasm_engine_t *engine); + +/// \brief Retrieves the nth export. +/// +/// The returned `type_ret` pointer must be deallocated with +/// `wasm_exporttype_delete`. +WASM_API_EXTERN +wasm_exporttype_t * +wasmtime_module_type_export_nth(const wasmtime_module_type_t *ty, + const wasm_engine_t *engine, size_t nth); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_MODULE_H diff --git a/crates/c-api/include/wasmtime/component/types/module.hh b/crates/c-api/include/wasmtime/component/types/module.hh new file mode 100644 index 000000000000..31e953a3c84f --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/module.hh @@ -0,0 +1,64 @@ +/** + * \file wasmtime/component/types/module.hh + */ + +#ifndef WASMTIME_COMPONENT_TYPES_MODULE_HH +#define WASMTIME_COMPONENT_TYPES_MODULE_HH + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace wasmtime { +namespace component { + +/** + * \brief Represents the type of a module. + */ +class ModuleType { + WASMTIME_CLONE_WRAPPER(ModuleType, wasmtime_module_type) + + /// Returns the number of imports of this module type. + size_t import_count(const Engine &engine) const { + return wasmtime_module_type_import_count(ptr.get(), engine.capi()); + } + + /// Retrieves the nth import. + std::optional import_nth(const Engine &engine, size_t nth) const { + auto ret = wasmtime_module_type_import_nth(ptr.get(), engine.capi(), nth); + if (ret) + return ImportType(ret); + return std::nullopt; + } + + /// Returns the number of exports of this module type. + size_t export_count(const Engine &engine) const { + return wasmtime_module_type_export_count(ptr.get(), engine.capi()); + } + + /// Retrieves the nth export. + std::optional export_nth(const Engine &engine, size_t nth) const { + auto ret = wasmtime_module_type_export_nth(ptr.get(), engine.capi(), nth); + if (ret) + return ExportType(ret); + return std::nullopt; + } +}; + +} // namespace component +} // namespace wasmtime + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_MODULE_HH diff --git a/crates/c-api/include/wasmtime/component/types/resource.h b/crates/c-api/include/wasmtime/component/types/resource.h new file mode 100644 index 000000000000..b0b289229ed9 --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/resource.h @@ -0,0 +1,72 @@ +/// \file wasmtime/component/types/resource.h + +#ifndef WASMTIME_COMPONENT_TYPES_RESOURCE_H +#define WASMTIME_COMPONENT_TYPES_RESOURCE_H + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// \brief Represents the type of a component resource. +/// +/// This is an opaque structure which represents the type of a resource. This +/// can be used to equate the type of two resources together to see if they are +/// the same. +typedef struct wasmtime_component_resource_type + wasmtime_component_resource_type_t; + +/// \brief Creates a new resource type representing a host-defined resource. +/// +/// This function creates a new `wasmtime_component_resource_type_t` which +/// represents a host-defined resource identified by the `ty` integer argument +/// provided. Two host resources with different `ty` arguments are considered +/// not-equal in terms of resource types. Through this the host can create +/// distinct types of resources at runtime to ensure that components are also +/// required to keep resources distinct. +/// +/// The pointer returned from this function must be deallocated with +/// `wasmtime_component_resource_type_delete`. +WASM_API_EXTERN +wasmtime_component_resource_type_t * +wasmtime_component_resource_type_new_host(uint32_t ty); + +/// \brief Clones a resource type. +/// +/// Creates a new owned copy of a resource type. +/// +/// The pointer returned from this function must be deallocated with +/// `wasmtime_component_resource_type_delete`. +WASM_API_EXTERN +wasmtime_component_resource_type_t *wasmtime_component_resource_type_clone( + const wasmtime_component_resource_type_t *ty); + +/// \brief Compares two resource types for equality. +/// +/// Returns whether `a` and `b` point to logically the same resource type under +/// the hood. +WASM_API_EXTERN +bool wasmtime_component_resource_type_equal( + const wasmtime_component_resource_type_t *a, + const wasmtime_component_resource_type_t *b); + +/// \brief Deallocates a resource type. +/// +/// This will deallocate the pointer `resource` any any memory that it might +/// own. +WASM_API_EXTERN +void wasmtime_component_resource_type_delete( + wasmtime_component_resource_type_t *resource); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_RESOURCE_H diff --git a/crates/c-api/include/wasmtime/component/types/val.h b/crates/c-api/include/wasmtime/component/types/val.h new file mode 100644 index 000000000000..85301056ad6f --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/val.h @@ -0,0 +1,493 @@ +/// \file wasmtime/component/types/val.h + +#ifndef WASMTIME_COMPONENT_TYPES_VAL_H +#define WASMTIME_COMPONENT_TYPES_VAL_H + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct wasmtime_component_valtype_t; + +// ----------- lists ----------------------------------------------------------- + +/// \brief Opaque type representing a component list type. +typedef struct wasmtime_component_list_type wasmtime_component_list_type_t; + +/// \brief Clones a component list type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_list_type_delete`. +WASM_API_EXTERN wasmtime_component_list_type_t * +wasmtime_component_list_type_clone(const wasmtime_component_list_type_t *ty); + +/// \brief Compares two component list types for equality. +WASM_API_EXTERN bool +wasmtime_component_list_type_equal(const wasmtime_component_list_type_t *a, + const wasmtime_component_list_type_t *b); + +/// \brief Deallocates a component list type. +WASM_API_EXTERN void +wasmtime_component_list_type_delete(wasmtime_component_list_type_t *ptr); + +/// \brief Returns the element type of a component list type. +/// +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN void wasmtime_component_list_type_element( + const wasmtime_component_list_type_t *ty, + struct wasmtime_component_valtype_t *type_ret); + +// ----------- records --------------------------------------------------------- + +/// \brief Opaque type representing a component record type. +typedef struct wasmtime_component_record_type wasmtime_component_record_type_t; + +/// \brief Clones a component record type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_record_type_delete`. +WASM_API_EXTERN wasmtime_component_record_type_t * +wasmtime_component_record_type_clone( + const wasmtime_component_record_type_t *ty); + +/// \brief Compares two component record types for equality. +WASM_API_EXTERN bool +wasmtime_component_record_type_equal(const wasmtime_component_record_type_t *a, + const wasmtime_component_record_type_t *b); + +/// \brief Deallocates a component record type. +WASM_API_EXTERN void +wasmtime_component_record_type_delete(wasmtime_component_record_type_t *ptr); + +/// \brief Returns the number of fields in a component record type. +WASM_API_EXTERN size_t wasmtime_component_record_type_field_count( + const wasmtime_component_record_type_t *ty); + +/// \brief Returns the nth field in a component record type. +/// +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN bool wasmtime_component_record_type_field_nth( + const wasmtime_component_record_type_t *ty, size_t nth, + const char **name_ret, size_t *name_len_ret, + struct wasmtime_component_valtype_t *type_ret); + +// ----------- tuples --------------------------------------------------------- + +/// \brief Opaque type representing a component tuple type. +typedef struct wasmtime_component_tuple_type wasmtime_component_tuple_type_t; + +/// \brief Clones a component tuple type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_tuple_type_delete`. +WASM_API_EXTERN wasmtime_component_tuple_type_t * +wasmtime_component_tuple_type_clone(const wasmtime_component_tuple_type_t *ty); + +/// \brief Compares two component tuple types for equality. +WASM_API_EXTERN bool +wasmtime_component_tuple_type_equal(const wasmtime_component_tuple_type_t *a, + const wasmtime_component_tuple_type_t *b); + +/// \brief Deallocates a component tuple type. +WASM_API_EXTERN void +wasmtime_component_tuple_type_delete(wasmtime_component_tuple_type_t *ptr); + +/// \brief Returns the number of types in a component tuple type. +WASM_API_EXTERN size_t wasmtime_component_tuple_type_types_count( + const wasmtime_component_tuple_type_t *ty); + +/// \brief Returns the nth type in a component tuple type. +/// +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN bool wasmtime_component_tuple_type_types_nth( + const wasmtime_component_tuple_type_t *ty, size_t nth, + struct wasmtime_component_valtype_t *type_ret); + +// ----------- variants -------------------------------------------------------- + +/// \brief Opaque type representing a component variant type. +typedef struct wasmtime_component_variant_type + wasmtime_component_variant_type_t; + +/// \brief Clones a component variant type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_variant_type_delete`. +WASM_API_EXTERN wasmtime_component_variant_type_t * +wasmtime_component_variant_type_clone( + const wasmtime_component_variant_type_t *ty); + +/// \brief Compares two component variant types for equality. +WASM_API_EXTERN bool wasmtime_component_variant_type_equal( + const wasmtime_component_variant_type_t *a, + const wasmtime_component_variant_type_t *b); + +/// \brief Deallocates a component variant type. +WASM_API_EXTERN void +wasmtime_component_variant_type_delete(wasmtime_component_variant_type_t *ptr); + +/// \brief Returns the number of cases in a component variant type. +WASM_API_EXTERN size_t wasmtime_component_variant_type_case_count( + const wasmtime_component_variant_type_t *ty); + +/// \brief Returns the nth case in a component variant type. +/// The returned payload type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN bool wasmtime_component_variant_type_case_nth( + const wasmtime_component_variant_type_t *ty, size_t nth, + const char **name_ret, size_t *name_len_ret, bool *has_payload_ret, + struct wasmtime_component_valtype_t *payload_ret); + +// ----------- enums ----------------------------------------------------------- + +/// \brief Opaque type representing a component enum type. +typedef struct wasmtime_component_enum_type wasmtime_component_enum_type_t; + +/// \brief Clones a component enum type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_enum_type_delete`. +WASM_API_EXTERN wasmtime_component_enum_type_t * +wasmtime_component_enum_type_clone(const wasmtime_component_enum_type_t *ty); + +/// \brief Compares two component enum types for equality. +WASM_API_EXTERN bool +wasmtime_component_enum_type_equal(const wasmtime_component_enum_type_t *a, + const wasmtime_component_enum_type_t *b); + +/// \brief Deallocates a component enum type. +WASM_API_EXTERN void +wasmtime_component_enum_type_delete(wasmtime_component_enum_type_t *ptr); + +/// \brief Returns the number of names in a component enum type. +WASM_API_EXTERN size_t wasmtime_component_enum_type_names_count( + const wasmtime_component_enum_type_t *ty); + +/// \brief Returns the nth name in a component enum type. +WASM_API_EXTERN bool +wasmtime_component_enum_type_names_nth(const wasmtime_component_enum_type_t *ty, + size_t nth, const char **name_ret, + size_t *name_len_ret); + +// ----------- options --------------------------------------------------------- + +/// \brief Opaque type representing a component option type. +typedef struct wasmtime_component_option_type wasmtime_component_option_type_t; + +/// \brief Clones a component option type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_option_type_delete`. +WASM_API_EXTERN wasmtime_component_option_type_t * +wasmtime_component_option_type_clone( + const wasmtime_component_option_type_t *ty); + +/// \brief Compares two component option types for equality. +WASM_API_EXTERN bool +wasmtime_component_option_type_equal(const wasmtime_component_option_type_t *a, + const wasmtime_component_option_type_t *b); + +/// \brief Deallocates a component option type. +WASM_API_EXTERN void +wasmtime_component_option_type_delete(wasmtime_component_option_type_t *ptr); + +/// \brief Returns the inner type of a component option type. +/// +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN void wasmtime_component_option_type_ty( + const wasmtime_component_option_type_t *ty, + struct wasmtime_component_valtype_t *type_ret); + +// ----------- results --------------------------------------------------------- + +/// \brief Opaque type representing a component result type. +typedef struct wasmtime_component_result_type wasmtime_component_result_type_t; + +/// \brief Clones a component result type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_result_type_delete`. +WASM_API_EXTERN wasmtime_component_result_type_t * +wasmtime_component_result_type_clone( + const wasmtime_component_result_type_t *ty); + +/// \brief Compares two component result types for equality. +WASM_API_EXTERN bool +wasmtime_component_result_type_equal(const wasmtime_component_result_type_t *a, + const wasmtime_component_result_type_t *b); + +/// \brief Deallocates a component result type. +WASM_API_EXTERN void +wasmtime_component_result_type_delete(wasmtime_component_result_type_t *ptr); + +/// \brief Returns the `ok` type of a component result type. +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN bool wasmtime_component_result_type_ok( + const wasmtime_component_result_type_t *ty, + struct wasmtime_component_valtype_t *type_ret); + +/// \brief Returns the `err` type of a component result type. +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN bool wasmtime_component_result_type_err( + const wasmtime_component_result_type_t *ty, + struct wasmtime_component_valtype_t *type_ret); + +// ----------- flags ----------------------------------------------------------- + +/// \brief Opaque type representing a component flags type. +typedef struct wasmtime_component_flags_type wasmtime_component_flags_type_t; + +/// \brief Clones a component flags type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_flags_type_delete`. +WASM_API_EXTERN wasmtime_component_flags_type_t * +wasmtime_component_flags_type_clone(const wasmtime_component_flags_type_t *ty); + +/// \brief Compares two component flags types for equality. +WASM_API_EXTERN bool +wasmtime_component_flags_type_equal(const wasmtime_component_flags_type_t *a, + const wasmtime_component_flags_type_t *b); + +/// \brief Deallocates a component flags type. +WASM_API_EXTERN void +wasmtime_component_flags_type_delete(wasmtime_component_flags_type_t *ptr); + +/// \brief Returns the number of names in a component flags type. +WASM_API_EXTERN size_t wasmtime_component_flags_type_names_count( + const wasmtime_component_flags_type_t *ty); + +/// \brief Returns the nth name in a component flags type. +WASM_API_EXTERN bool wasmtime_component_flags_type_names_nth( + const wasmtime_component_flags_type_t *ty, size_t nth, + const char **name_ret, size_t *name_len_ret); + +// ----------- futures --------------------------------------------------------- + +/// \brief Opaque type representing a component future type. +typedef struct wasmtime_component_future_type wasmtime_component_future_type_t; + +/// \brief Clones a component future type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_future_type_delete`. +WASM_API_EXTERN wasmtime_component_future_type_t * +wasmtime_component_future_type_clone( + const wasmtime_component_future_type_t *ty); + +/// \brief Compares two component future types for equality. +WASM_API_EXTERN bool +wasmtime_component_future_type_equal(const wasmtime_component_future_type_t *a, + const wasmtime_component_future_type_t *b); + +/// \brief Deallocates a component future type. +WASM_API_EXTERN void +wasmtime_component_future_type_delete(wasmtime_component_future_type_t *ptr); + +/// \brief Returns the inner type of a component future type. +/// +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN bool wasmtime_component_future_type_ty( + const wasmtime_component_future_type_t *ty, + struct wasmtime_component_valtype_t *type_ret); + +// ----------- streams --------------------------------------------------------- + +/// \brief Opaque type representing a component stream type. +typedef struct wasmtime_component_stream_type wasmtime_component_stream_type_t; + +/// \brief Clones a component stream type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_stream_type_delete`. +WASM_API_EXTERN wasmtime_component_stream_type_t * +wasmtime_component_stream_type_clone( + const wasmtime_component_stream_type_t *ty); + +/// \brief Compares two component stream types for equality. +WASM_API_EXTERN bool +wasmtime_component_stream_type_equal(const wasmtime_component_stream_type_t *a, + const wasmtime_component_stream_type_t *b); + +/// \brief Deallocates a component stream type. +WASM_API_EXTERN void +wasmtime_component_stream_type_delete(wasmtime_component_stream_type_t *ptr); + +/// \brief Returns the inner type of a component stream type. +/// +/// The returned type must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN bool wasmtime_component_stream_type_ty( + const wasmtime_component_stream_type_t *ty, + struct wasmtime_component_valtype_t *type_ret); + +// ----------- valtype --------------------------------------------------------- + +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `bool` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_BOOL 0 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `s8` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_S8 1 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `s16` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_S16 2 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `s32` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_S32 3 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `s64` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_S64 4 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `u8` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_U8 5 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `u16` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_U16 6 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `u32` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_U32 7 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `u64` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_U64 8 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `f32` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_F32 9 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `f64` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_F64 10 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `char` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_CHAR 11 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `string` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_STRING 12 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `list` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_LIST 13 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `record` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_RECORD 14 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `tuple` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_TUPLE 15 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `variant` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_VARIANT 16 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `enum` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_ENUM 17 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `option` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_OPTION 18 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `result` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_RESULT 19 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `flags` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_FLAGS 20 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a resource `own` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_OWN 21 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a resource `borrow` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_BORROW 22 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `future` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_FUTURE 23 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is a `stream` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_STREAM 24 +/// \brief Value of #wasmtime_component_valtype_kind_t meaning that +/// #wasmtime_component_valtype_t is an `error context` WIT type. +#define WASMTIME_COMPONENT_VALTYPE_ERROR_CONTEXT 25 + +/// \brief Discriminant used in #wasmtime_component_valtype_t::kind +typedef uint8_t wasmtime_component_valtype_kind_t; + +/// \brief Represents a single value type in the component model. +typedef union wasmtime_component_valtype_union { + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_LIST + wasmtime_component_list_type_t *list; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_RECORD + wasmtime_component_record_type_t *record; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_TUPLE + wasmtime_component_tuple_type_t *tuple; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_VARIANT + wasmtime_component_variant_type_t *variant; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_ENUM + wasmtime_component_enum_type_t *enum_; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_OPTION + wasmtime_component_option_type_t *option; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_RESULT + wasmtime_component_result_type_t *result; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_FLAGS + wasmtime_component_flags_type_t *flags; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_OWN + wasmtime_component_resource_type_t *own; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_BORROW + wasmtime_component_resource_type_t *borrow; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_FUTURE + wasmtime_component_future_type_t *future; + /// Field used if #wasmtime_component_valtype_t::kind is + /// #WASMTIME_COMPONENT_VALTYPE_STREAM + wasmtime_component_stream_type_t *stream; +} wasmtime_component_valtype_union_t; + +/// \brief Represents a single value type in the component model. +typedef struct wasmtime_component_valtype_t { + /// The type discriminant for the `of` union. + wasmtime_component_valtype_kind_t kind; + /// The actual type. + wasmtime_component_valtype_union_t of; +} wasmtime_component_valtype_t; + +/// \brief Clones a component value type. +/// +/// The returned pointer must be deallocated with +/// `wasmtime_component_valtype_delete`. +WASM_API_EXTERN void +wasmtime_component_valtype_clone(const wasmtime_component_valtype_t *ty, + wasmtime_component_valtype_t *out); + +/// \brief Compares two component value types for equality. +WASM_API_EXTERN bool +wasmtime_component_valtype_equal(const wasmtime_component_valtype_t *a, + const wasmtime_component_valtype_t *b); + +/// \brief Deallocates a component value type. +WASM_API_EXTERN void +wasmtime_component_valtype_delete(wasmtime_component_valtype_t *ptr); + +#ifdef __cplusplus +} +#endif + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_VAL_H diff --git a/crates/c-api/include/wasmtime/component/types/val.hh b/crates/c-api/include/wasmtime/component/types/val.hh new file mode 100644 index 000000000000..8cf31b62f1c4 --- /dev/null +++ b/crates/c-api/include/wasmtime/component/types/val.hh @@ -0,0 +1,648 @@ +/** + * \file wasmtime/component/types/val.hh + */ + +#ifndef WASMTIME_COMPONENT_TYPES_VAL_HH +#define WASMTIME_COMPONENT_TYPES_VAL_HH + +#include + +#ifdef WASMTIME_FEATURE_COMPONENT_MODEL + +#include +#include +#include +#include +#include + +namespace wasmtime { +namespace component { + +class ValType; + +/** + * \brief Represents a component list type. + */ +class ListType { + WASMTIME_CLONE_EQUAL_WRAPPER(ListType, wasmtime_component_list_type); + + /// Returns the element type of this list type. + ValType element() const; +}; + +/** + * \brief Represents a component record type. + */ +class RecordType { + WASMTIME_CLONE_EQUAL_WRAPPER(RecordType, wasmtime_component_record_type); + + /// Returns the number of fields in this record type. + size_t field_count() const { + return wasmtime_component_record_type_field_count(ptr.get()); + } + + /// Retrieves the nth field. + std::optional> + field_nth(size_t nth) const; +}; + +/** + * \brief Represents a component tuple type. + */ +class TupleType { + WASMTIME_CLONE_EQUAL_WRAPPER(TupleType, wasmtime_component_tuple_type); + + /// Returns the number of types in this tuple type. + size_t types_count() const { + return wasmtime_component_tuple_type_types_count(ptr.get()); + } + + /// Retrieves the nth type. + std::optional types_nth(size_t nth) const; +}; + +/** + * \brief Represents a component variant type. + */ +class VariantType { + WASMTIME_CLONE_EQUAL_WRAPPER(VariantType, wasmtime_component_variant_type); + + /// Returns the number of cases in this variant type. + size_t case_count() const { + return wasmtime_component_variant_type_case_count(ptr.get()); + } + + /// Retrieves the nth case. + std::optional>> + case_nth(size_t nth) const; +}; + +/** + * \brief Represents a component enum type. + */ +class EnumType { + WASMTIME_CLONE_EQUAL_WRAPPER(EnumType, wasmtime_component_enum_type); + + /// Returns the number of names in this enum type. + size_t names_count() const { + return wasmtime_component_enum_type_names_count(ptr.get()); + } + + /// Retrieves the nth name. + std::optional names_nth(size_t nth) const { + const char *name_ptr = nullptr; + size_t name_len = 0; + if (wasmtime_component_enum_type_names_nth(ptr.get(), nth, &name_ptr, + &name_len)) { + return std::string_view(name_ptr, name_len); + } + return std::nullopt; + } +}; + +/** + * \brief Represents a component option type. + */ +class OptionType { + WASMTIME_CLONE_EQUAL_WRAPPER(OptionType, wasmtime_component_option_type); + + /// Returns the inner type of this option type. + ValType ty() const; +}; + +/** + * \brief Represents a component result type. + */ +class ResultType { + WASMTIME_CLONE_EQUAL_WRAPPER(ResultType, wasmtime_component_result_type); + + /// Returns the ok type of this result type, if any. + std::optional ok() const; + + /// Returns the err type of this result type, if any. + std::optional err() const; +}; + +/** + * \brief Represents a component flags type. + */ +class FlagsType { + WASMTIME_CLONE_EQUAL_WRAPPER(FlagsType, wasmtime_component_flags_type); + + /// Returns the number of names in this flags type. + size_t names_count() const { + return wasmtime_component_flags_type_names_count(ptr.get()); + } + + /// Retrieves the nth name. + std::optional names_nth(size_t nth) const { + const char *name_ptr = nullptr; + size_t name_len = 0; + if (wasmtime_component_flags_type_names_nth(ptr.get(), nth, &name_ptr, + &name_len)) { + return std::string_view(name_ptr, name_len); + } + return std::nullopt; + } +}; + +/// Class representing a component model `resource` value which is either a +/// guest or host-defined resource. +class ResourceType { + WASMTIME_CLONE_EQUAL_WRAPPER(ResourceType, wasmtime_component_resource_type); + +public: + /// \brief Creates a new host resource type with the specified `ty` + /// identifier. + explicit ResourceType(uint32_t ty) + : ptr(wasmtime_component_resource_type_new_host(ty)) {} +}; + +/** + * \brief Represents a component future type. + */ +class FutureType { + WASMTIME_CLONE_EQUAL_WRAPPER(FutureType, wasmtime_component_future_type); + + /// Returns the inner type of this future type, if any. + std::optional ty() const; +}; + +/** + * \brief Represents a component stream type. + */ +class StreamType { + WASMTIME_CLONE_EQUAL_WRAPPER(StreamType, wasmtime_component_stream_type); + + /// Returns the inner type of this stream type, if any. + std::optional ty() const; +}; + +/** + * \brief Represents a component value type. + */ +class ValType { + wasmtime_component_valtype_t ty; + + static ValType new_kind(wasmtime_component_valtype_kind_t kind) { + wasmtime_component_valtype_t ty; + ty.kind = kind; + return ValType(std::move(ty)); + } + +public: + /// Creates a component value type from the raw C API representation. + explicit ValType(wasmtime_component_valtype_t &&ty) { + this->ty = ty; + ty.kind = WASMTIME_COMPONENT_VALTYPE_BOOL; + } + + /// Copies another type into this one. + ValType(const ValType &other) { + wasmtime_component_valtype_clone(&other.ty, &ty); + } + + /// Copies another type into this one. + ValType &operator=(const ValType &other) { + wasmtime_component_valtype_delete(&ty); + wasmtime_component_valtype_clone(&other.ty, &ty); + return *this; + } + + /// Moves another type into this one. + ValType(ValType &&other) : ty(other.ty) { + other.ty.kind = WASMTIME_COMPONENT_VALTYPE_BOOL; + } + + /// Moves another type into this one. + ValType &operator=(ValType &&other) { + wasmtime_component_valtype_delete(&ty); + ty = other.ty; + other.ty.kind = WASMTIME_COMPONENT_VALTYPE_BOOL; + return *this; + } + + ~ValType() { wasmtime_component_valtype_delete(&ty); } + + /** + * Converts the raw C API representation to this class without taking + * ownership. + */ + static const ValType *from_capi(const wasmtime_component_valtype_t *capi) { + static_assert(sizeof(ValType) == sizeof(wasmtime_component_valtype_t)); + return reinterpret_cast(capi); + } + + /// \brief Compares two types to see if they're the same. + bool operator==(const ValType &other) const { + return wasmtime_component_valtype_equal(&ty, &other.ty); + } + + /// \brief Compares two types to see if they're different. + bool operator!=(const ValType &other) const { return !(*this == other); } + + /// Creates a bool value type. + static ValType new_bool() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_BOOL); + } + + /// Creates an s8 value type. + static ValType new_s8() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_S8); + } + + /// Creates an s16 value type. + static ValType new_s16() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_S16); + } + + /// Creates an s32 value type. + static ValType new_s32() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_S32); + } + + /// Creates an s64 value type. + static ValType new_s64() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_S64); + } + + /// Creates a u8 value type. + static ValType new_u8() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_U8); + } + + /// Creates a u16 value type. + static ValType new_u16() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_U16); + } + + /// Creates a u32 value type. + static ValType new_u32() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_U32); + } + + /// Creates a u64 value type. + static ValType new_u64() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_U64); + } + + /// Creates an f32 value type. + static ValType new_f32() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_F32); + } + + /// Creates an f64 value type. + static ValType new_f64() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_F64); + } + + /// Creates a char value type. + static ValType new_char() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_CHAR); + } + + /// Creates a string value type. + static ValType new_string() { + return ValType::new_kind(WASMTIME_COMPONENT_VALTYPE_STRING); + } + + /// Creates a list value type. + ValType(ListType list) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_LIST; + ty.of.list = list.capi_release(); + } + + /// Creates a record value type. + ValType(RecordType record) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_RECORD; + ty.of.record = record.capi_release(); + } + + /// Creates a tuple value type. + ValType(TupleType tuple) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_TUPLE; + ty.of.tuple = tuple.capi_release(); + } + + /// Creates a variant value type. + ValType(VariantType variant) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_VARIANT; + ty.of.variant = variant.capi_release(); + } + + /// Creates an enum value type. + ValType(EnumType enum_) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_ENUM; + ty.of.enum_ = enum_.capi_release(); + } + + /// Creates an option value type. + ValType(OptionType option) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_OPTION; + ty.of.option = option.capi_release(); + } + + /// Creates a result value type. + ValType(ResultType result) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_RESULT; + ty.of.result = result.capi_release(); + } + + /// Creates a flags value type. + ValType(FlagsType flags) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_FLAGS; + ty.of.flags = flags.capi_release(); + } + + /// Creates an own value type. + static ValType new_own(ResourceType own) { + wasmtime_component_valtype_t ty; + ty.kind = WASMTIME_COMPONENT_VALTYPE_OWN; + ty.of.own = own.capi_release(); + return ValType(std::move(ty)); + } + + /// Creates an borrow value type. + static ValType new_borrow(ResourceType borrow) { + wasmtime_component_valtype_t ty; + ty.kind = WASMTIME_COMPONENT_VALTYPE_BORROW; + ty.of.borrow = borrow.capi_release(); + return ValType(std::move(ty)); + } + + /// Creates a future value type. + ValType(FutureType future) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_FUTURE; + ty.of.future = future.capi_release(); + } + + /// Creates a stream value type. + ValType(StreamType stream) { + ty.kind = WASMTIME_COMPONENT_VALTYPE_STREAM; + ty.of.stream = stream.capi_release(); + } + + /// Returns the kind of this value type. + wasmtime_component_valtype_kind_t kind() const { return ty.kind; } + + /// Returns true if this is a bool type. + bool is_bool() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_BOOL; } + + /// Returns true if this is an s8 type. + bool is_s8() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_S8; } + + /// Returns true if this is an s16 type. + bool is_s16() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_S16; } + + /// Returns true if this is an s32 type. + bool is_s32() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_S32; } + + /// Returns true if this is an s64 type. + bool is_s64() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_S64; } + + /// Returns true if this is a u8 type. + bool is_u8() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_U8; } + + /// Returns true if this is a u16 type. + bool is_u16() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_U16; } + + /// Returns true if this is a u32 type. + bool is_u32() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_U32; } + + /// Returns true if this is a u64 type. + bool is_u64() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_U64; } + + /// Returns true if this is an f32 type. + bool is_f32() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_F32; } + + /// Returns true if this is an f64 type. + bool is_f64() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_F64; } + + /// Returns true if this is a char type. + bool is_char() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_CHAR; } + + /// Returns true if this is a string type. + bool is_string() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_STRING; + } + + /// Returns true if this is a list type. + bool is_list() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_LIST; } + + /// Returns true if this is a record type. + bool is_record() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_RECORD; + } + + /// Returns true if this is a tuple type. + bool is_tuple() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_TUPLE; } + + /// Returns true if this is a variant type. + bool is_variant() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_VARIANT; + } + + /// Returns true if this is an enum type. + bool is_enum() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_ENUM; } + + /// Returns true if this is an option type. + bool is_option() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_OPTION; + } + + /// Returns true if this is a result type. + bool is_result() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_RESULT; + } + + /// Returns true if this is a flags type. + bool is_flags() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_FLAGS; } + + /// Returns true if this is an own type. + bool is_own() const { return ty.kind == WASMTIME_COMPONENT_VALTYPE_OWN; } + + /// Returns true if this is a borrow type. + bool is_borrow() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_BORROW; + } + + /// Returns true if this is a future type. + bool is_future() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_FUTURE; + } + + /// Returns true if this is a stream type. + bool is_stream() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_STREAM; + } + + /// Returns true if this is an error context type. + bool is_error_context() const { + return ty.kind == WASMTIME_COMPONENT_VALTYPE_ERROR_CONTEXT; + } + + /// Returns the list type, asserting that this is indeed a list. + const ListType &list() const { + assert(is_list()); + return *ListType::from_capi(&ty.of.list); + } + + /// Returns the record type, asserting that this is indeed a record. + const RecordType &record() const { + assert(is_record()); + return *RecordType::from_capi(&ty.of.record); + } + + /// Returns the tuple type, asserting that this is indeed a tuple. + const TupleType &tuple() const { + assert(is_tuple()); + return *TupleType::from_capi(&ty.of.tuple); + } + + /// Returns the variant type, asserting that this is indeed a variant. + const VariantType &variant() const { + assert(is_variant()); + return *VariantType::from_capi(&ty.of.variant); + } + + /// Returns the enum type, asserting that this is indeed a enum. + const EnumType &enum_() const { + assert(is_enum()); + return *EnumType::from_capi(&ty.of.enum_); + } + + /// Returns the option type, asserting that this is indeed a option. + const OptionType &option() const { + assert(is_option()); + return *OptionType::from_capi(&ty.of.option); + } + + /// Returns the result type, asserting that this is indeed a result. + const ResultType &result() const { + assert(is_result()); + return *ResultType::from_capi(&ty.of.result); + } + + /// Returns the flags type, asserting that this is indeed a flags. + const FlagsType &flags() const { + assert(is_flags()); + return *FlagsType::from_capi(&ty.of.flags); + } + + /// Returns the own type, asserting that this is indeed a own. + const ResourceType &own() const { + assert(is_own()); + return *ResourceType::from_capi(&ty.of.own); + } + + /// Returns the borrow type, asserting that this is indeed a borrow. + const ResourceType &borrow() const { + assert(is_borrow()); + return *ResourceType::from_capi(&ty.of.borrow); + } + + /// Returns the future type, asserting that this is indeed a future. + const FutureType &future() const { + assert(is_future()); + return *FutureType::from_capi(&ty.of.future); + } + + /// Returns the stream type, asserting that this is indeed a stream. + const StreamType &stream() const { + assert(is_stream()); + return *StreamType::from_capi(&ty.of.stream); + } + + /// \brief Returns the underlying C API pointer. + const wasmtime_component_valtype_t *capi() const { return &ty; } + /// \brief Returns the underlying C API pointer. + wasmtime_component_valtype_t *capi() { return &ty; } +}; + +inline ValType ListType::element() const { + wasmtime_component_valtype_t type_ret; + wasmtime_component_list_type_element(ptr.get(), &type_ret); + return ValType(std::move(type_ret)); +} + +inline std::optional> +RecordType::field_nth(size_t nth) const { + const char *name_ptr = nullptr; + size_t name_len = 0; + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_record_type_field_nth(ptr.get(), nth, &name_ptr, + &name_len, &type_ret)) { + return std::make_pair(std::string_view(name_ptr, name_len), + ValType(std::move(type_ret))); + } + return std::nullopt; +} + +inline std::optional TupleType::types_nth(size_t nth) const { + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_tuple_type_types_nth(ptr.get(), nth, &type_ret)) { + return ValType(std::move(type_ret)); + } + return std::nullopt; +} + +inline std::optional>> +VariantType::case_nth(size_t nth) const { + const char *name_ptr = nullptr; + size_t name_len = 0; + bool has_payload = false; + wasmtime_component_valtype_t payload_ret; + if (!wasmtime_component_variant_type_case_nth( + ptr.get(), nth, &name_ptr, &name_len, &has_payload, &payload_ret)) { + return std::nullopt; + } + return std::make_pair( + std::string_view(name_ptr, name_len), + has_payload ? std::optional(ValType(std::move(payload_ret))) + : std::nullopt); +} + +inline ValType OptionType::ty() const { + wasmtime_component_valtype_t type_ret; + wasmtime_component_option_type_ty(ptr.get(), &type_ret); + return ValType(std::move(type_ret)); +} + +inline std::optional ResultType::ok() const { + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_result_type_ok(ptr.get(), &type_ret)) { + return ValType(std::move(type_ret)); + } + return std::nullopt; +} + +inline std::optional ResultType::err() const { + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_result_type_err(ptr.get(), &type_ret)) { + return ValType(std::move(type_ret)); + } + return std::nullopt; +} + +inline std::optional FutureType::ty() const { + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_future_type_ty(ptr.get(), &type_ret)) { + return ValType(std::move(type_ret)); + } + return std::nullopt; +} + +inline std::optional StreamType::ty() const { + wasmtime_component_valtype_t type_ret; + if (wasmtime_component_stream_type_ty(ptr.get(), &type_ret)) { + return ValType(std::move(type_ret)); + } + return std::nullopt; +} + +} // namespace component +} // namespace wasmtime + +#endif // WASMTIME_FEATURE_COMPONENT_MODEL + +#endif // WASMTIME_COMPONENT_TYPES_VAL_HH diff --git a/crates/c-api/include/wasmtime/component/val.h b/crates/c-api/include/wasmtime/component/val.h index bae8d94eb28e..2021651273f9 100644 --- a/crates/c-api/include/wasmtime/component/val.h +++ b/crates/c-api/include/wasmtime/component/val.h @@ -9,62 +9,13 @@ #include #include +#include #include #ifdef __cplusplus extern "C" { #endif -/// \brief Represents the type of a component resource. -/// -/// This is an opaque structure which represents the type of a resource. This -/// can be used to equate the type of two resources together to see if they are -/// the same. -typedef struct wasmtime_component_resource_type - wasmtime_component_resource_type_t; - -/// \brief Creates a new resource type representing a host-defined resource. -/// -/// This function creates a new `wasmtime_component_resource_type_t` which -/// represents a host-defined resource identified by the `ty` integer argument -/// provided. Two host resources with different `ty` arguments are considered -/// not-equal in terms of resource types. Through this the host can create -/// distinct types of resources at runtime to ensure that components are also -/// required to keep resources distinct. -/// -/// The pointer returned from this function must be deallocated with -/// `wasmtime_component_resource_type_delete`. -WASM_API_EXTERN -wasmtime_component_resource_type_t * -wasmtime_component_resource_type_new_host(uint32_t ty); - -/// \brief Clones a resource type. -/// -/// Creates a new owned copy of a resource type. -/// -/// The pointer returned from this function must be deallocated with -/// `wasmtime_component_resource_type_delete`. -WASM_API_EXTERN -wasmtime_component_resource_type_t *wasmtime_component_resource_type_clone( - const wasmtime_component_resource_type_t *ty); - -/// \brief Compares two resource types for equality. -/// -/// Returns whether `a` and `b` point to logically the same resource type under -/// the hood. -WASM_API_EXTERN -bool wasmtime_component_resource_type_equal( - const wasmtime_component_resource_type_t *a, - const wasmtime_component_resource_type_t *b); - -/// \brief Deallocates a resource type. -/// -/// This will deallocate the pointer `resource` any any memory that it might -/// own. -WASM_API_EXTERN -void wasmtime_component_resource_type_delete( - wasmtime_component_resource_type_t *resource); - /// \brief Represents a component resource which can be either guest-owned or /// host-owned. /// diff --git a/crates/c-api/include/wasmtime/component/val.hh b/crates/c-api/include/wasmtime/component/val.hh index 1f0dfe558ca1..ffc377ab2ee1 100644 --- a/crates/c-api/include/wasmtime/component/val.hh +++ b/crates/c-api/include/wasmtime/component/val.hh @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -416,27 +417,6 @@ public: } }; -/// Class representing a component model `resource` value which is either a -/// guest or host-defined resource. -class ResourceType { - WASMTIME_CLONE_WRAPPER(ResourceType, wasmtime_component_resource_type); - - /// \brief Creates a new host resource type with the specified `ty` - /// identifier. - explicit ResourceType(uint32_t ty) - : ptr(wasmtime_component_resource_type_new_host(ty)) {} - - /// \brief Compares two resource types for equality. - bool operator==(const ResourceType &b) const { - return wasmtime_component_resource_type_equal(capi(), b.capi()); - } - - /// \brief Compares two resource types for inequality. - bool operator!=(const ResourceType &b) const { - return !wasmtime_component_resource_type_equal(capi(), b.capi()); - } -}; - class ResourceHost; /// Class representing a component model `resource` value which is either a diff --git a/crates/c-api/include/wasmtime/helpers.hh b/crates/c-api/include/wasmtime/helpers.hh index 26f0d2f73bc6..6b7008658729 100644 --- a/crates/c-api/include/wasmtime/helpers.hh +++ b/crates/c-api/include/wasmtime/helpers.hh @@ -76,4 +76,19 @@ public: \ return *this; \ } +#define WASMTIME_CLONE_EQUAL_WRAPPER(name, capi_type) \ + WASMTIME_CLONE_WRAPPER(name, capi_type) \ + \ + /** \ + * \brief Compares two types for equality. \ + */ \ + bool operator==(const name &other) const { \ + return capi_type##_equal(ptr.get(), other.ptr.get()); \ + } \ + \ + /** \ + * \brief Compares two types for inequality. \ + */ \ + bool operator!=(const name &other) const { return !(*this == other); } + #endif // WASMTIME_HELPERS_HH diff --git a/crates/c-api/include/wasmtime/types/export.hh b/crates/c-api/include/wasmtime/types/export.hh index 85437e1d17d9..80d7ac957e3f 100644 --- a/crates/c-api/include/wasmtime/types/export.hh +++ b/crates/c-api/include/wasmtime/types/export.hh @@ -7,6 +7,7 @@ #include #include +#include namespace wasmtime { @@ -14,8 +15,11 @@ namespace wasmtime { * \brief Type information about a WebAssembly export */ class ExportType { +/// bridge between wasm.h and wasmtime.h conventions +#define wasm_exporttype_clone wasm_exporttype_copy + WASMTIME_CLONE_WRAPPER(ExportType, wasm_exporttype); +#undef wasm_exporttype_clone -public: /// \brief Non-owning reference to an `ExportType`. /// /// Note to get type information you can use `ExternType::from_export`. @@ -37,6 +41,9 @@ public: } }; + /// Returns the `Ref` describing this export. + Ref ref() const { return Ref(ptr.get()); } + /// An owned list of `ExportType` instances. class List { friend class Module; diff --git a/crates/c-api/include/wasmtime/types/import.hh b/crates/c-api/include/wasmtime/types/import.hh index c5c38efa56aa..efc20873f537 100644 --- a/crates/c-api/include/wasmtime/types/import.hh +++ b/crates/c-api/include/wasmtime/types/import.hh @@ -7,6 +7,7 @@ #include #include +#include namespace wasmtime { @@ -14,7 +15,11 @@ namespace wasmtime { * \brief Type information about a WebAssembly import. */ class ImportType { -public: +/// bridge between wasm.h and wasmtime.h conventions +#define wasm_importtype_clone wasm_importtype_copy + WASMTIME_CLONE_WRAPPER(ImportType, wasm_importtype); +#undef wasm_importtype_clone + /// Non-owning reference to an `ImportType`, must not be used after the /// original owner is deleted. class Ref { @@ -42,6 +47,9 @@ public: } }; + /// Returns the `Ref` describing this export. + Ref ref() const { return Ref(ptr.get()); } + /// An owned list of `ImportType` instances. class List { friend class Module; diff --git a/crates/c-api/src/component/component.rs b/crates/c-api/src/component/component.rs index 9cafd3ba33f0..4761ed71fb30 100644 --- a/crates/c-api/src/component/component.rs +++ b/crates/c-api/src/component/component.rs @@ -1,15 +1,12 @@ -use std::ffi::{CStr, c_char}; - +use crate::{ + wasm_byte_vec_t, wasm_config_t, wasm_engine_t, wasmtime_component_type_t, wasmtime_error_t, +}; use anyhow::Context; +use std::ffi::{CStr, c_char}; use wasmtime::component::{Component, ComponentExportIndex}; -use crate::{wasm_byte_vec_t, wasm_config_t, wasm_engine_t, wasmtime_error_t}; - #[unsafe(no_mangle)] -pub unsafe extern "C" fn wasmtime_config_wasm_component_model_set( - c: &mut wasm_config_t, - enable: bool, -) { +pub extern "C" fn wasmtime_config_wasm_component_model_set(c: &mut wasm_config_t, enable: bool) { c.config.wasm_component_model(enable); } @@ -35,7 +32,7 @@ pub unsafe extern "C" fn wasmtime_component_new( #[unsafe(no_mangle)] #[cfg(any(feature = "cranelift", feature = "winch"))] -pub unsafe extern "C" fn wasmtime_component_serialize( +pub extern "C" fn wasmtime_component_serialize( component: &wasmtime_component_t, ret: &mut wasm_byte_vec_t, ) -> Option> { @@ -77,14 +74,21 @@ pub unsafe extern "C" fn wasmtime_component_deserialize_file( } #[unsafe(no_mangle)] -pub unsafe extern "C" fn wasmtime_component_clone( +pub extern "C" fn wasmtime_component_type( + component: &wasmtime_component_t, +) -> Box { + Box::new(component.component.component_type().into()) +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_clone( component: &wasmtime_component_t, ) -> Box { Box::new(component.clone()) } #[unsafe(no_mangle)] -pub unsafe extern "C" fn wasmtime_component_delete(_component: Box) {} +pub extern "C" fn wasmtime_component_delete(_component: Box) {} #[repr(transparent)] pub struct wasmtime_component_export_index_t { @@ -116,7 +120,7 @@ pub unsafe extern "C" fn wasmtime_component_get_export_index( } #[unsafe(no_mangle)] -pub unsafe extern "C" fn wasmtime_component_export_index_clone( +pub extern "C" fn wasmtime_component_export_index_clone( export_index: &wasmtime_component_export_index_t, ) -> Box { Box::new(wasmtime_component_export_index_t { @@ -125,7 +129,7 @@ pub unsafe extern "C" fn wasmtime_component_export_index_clone( } #[unsafe(no_mangle)] -pub unsafe extern "C" fn wasmtime_component_export_index_delete( +pub extern "C" fn wasmtime_component_export_index_delete( _export_index: Box, ) { } diff --git a/crates/c-api/src/component/func.rs b/crates/c-api/src/component/func.rs index 104fde041270..0c5fcdaae8e8 100644 --- a/crates/c-api/src/component/func.rs +++ b/crates/c-api/src/component/func.rs @@ -1,8 +1,6 @@ -use wasmtime::component::{Func, Val}; - -use crate::{WasmtimeStoreContextMut, wasmtime_error_t}; - use super::wasmtime_component_val_t; +use crate::{WasmtimeStoreContextMut, wasmtime_component_func_type_t, wasmtime_error_t}; +use wasmtime::component::{Func, Val}; #[unsafe(no_mangle)] pub unsafe extern "C" fn wasmtime_component_func_call( @@ -37,3 +35,11 @@ pub unsafe extern "C" fn wasmtime_component_func_post_return( crate::handle_result(result, |_| {}) } + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_func_type( + func: &Func, + context: WasmtimeStoreContextMut<'_>, +) -> Box { + Box::new(func.ty(context).into()) +} diff --git a/crates/c-api/src/component/linker.rs b/crates/c-api/src/component/linker.rs index 165f145177fb..b17045a08101 100644 --- a/crates/c-api/src/component/linker.rs +++ b/crates/c-api/src/component/linker.rs @@ -1,6 +1,6 @@ use crate::{ - WasmtimeStoreContextMut, WasmtimeStoreData, wasm_engine_t, wasmtime_component_resource_type_t, - wasmtime_error_t, wasmtime_module_t, + WasmtimeStoreContextMut, WasmtimeStoreData, wasm_engine_t, wasmtime_component_func_type_t, + wasmtime_component_resource_type_t, wasmtime_error_t, wasmtime_module_t, }; use std::ffi::c_void; use wasmtime::component::{Instance, Linker, LinkerInstance, Val}; @@ -99,7 +99,8 @@ pub unsafe extern "C" fn wasmtime_component_linker_instance_add_module( pub type wasmtime_component_func_callback_t = extern "C" fn( *mut c_void, WasmtimeStoreContextMut<'_>, - *const wasmtime_component_val_t, + &wasmtime_component_func_type_t, + *mut wasmtime_component_val_t, usize, *mut wasmtime_component_val_t, usize, @@ -123,10 +124,10 @@ pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func( let result = linker_instance .linker_instance - .func_new(&name, move |ctx, _ty, args, rets| { + .func_new(&name, move |ctx, ty, args, rets| { let _ = &foreign; - let args = args + let mut args = args .iter() .map(|x| wasmtime_component_val_t::from(x)) .collect::>(); @@ -136,7 +137,8 @@ pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func( let res = callback( foreign.data, ctx, - args.as_ptr(), + &ty.into(), + args.as_mut_ptr(), args.len(), c_rets.as_mut_ptr(), c_rets.len(), diff --git a/crates/c-api/src/component/mod.rs b/crates/c-api/src/component/mod.rs index dd86c9dba2a4..15bfb642b8e2 100644 --- a/crates/c-api/src/component/mod.rs +++ b/crates/c-api/src/component/mod.rs @@ -2,10 +2,12 @@ mod component; mod func; mod instance; mod linker; +mod types; mod val; pub use component::*; pub use func::*; pub use instance::*; pub use linker::*; +pub use types::*; pub use val::*; diff --git a/crates/c-api/src/component/types.rs b/crates/c-api/src/component/types.rs new file mode 100644 index 000000000000..332a7394a5e5 --- /dev/null +++ b/crates/c-api/src/component/types.rs @@ -0,0 +1,51 @@ +macro_rules! type_wrapper { + ( + $(#[$attr:meta])* + pub struct $name:ident { pub(crate) ty: $ty:ty, } + + clone: $clone:ident, + delete: $delete:ident, + $(equal: $equal:ident,)? + ) => { + #[derive(Clone)] + $(#[$attr])* + pub struct $name { + pub(crate) ty: $ty, + } + + impl From<$ty> for $name { + fn from(ty: $ty) -> Self { + $name { ty } + } + } + + #[unsafe(no_mangle)] + pub extern "C" fn $clone(ty: &$name) -> Box<$name> { + Box::new(ty.clone()) + } + + $( + #[unsafe(no_mangle)] + pub extern "C" fn $equal(a: &$name, b: &$name) -> bool { + a.ty == b.ty + } + )? + + #[unsafe(no_mangle)] + pub extern "C" fn $delete(_ty: Option>) {} + }; +} + +mod component; +mod func; +mod instance; +mod module; +mod resource; +mod val; + +pub use component::*; +pub use func::*; +pub use instance::*; +pub use module::*; +pub use resource::*; +pub use val::*; diff --git a/crates/c-api/src/component/types/component.rs b/crates/c-api/src/component/types/component.rs new file mode 100644 index 000000000000..9079e69f2d4c --- /dev/null +++ b/crates/c-api/src/component/types/component.rs @@ -0,0 +1,167 @@ +use crate::{ + wasm_engine_t, wasm_functype_t, wasmtime_component_func_type_t, + wasmtime_component_instance_type_t, wasmtime_component_resource_type_t, + wasmtime_component_valtype_t, wasmtime_module_type_t, +}; +use std::mem::{ManuallyDrop, MaybeUninit}; +use wasmtime::component::types::{Component, ComponentItem}; + +type_wrapper! { + pub struct wasmtime_component_type_t { + pub(crate) ty: Component, + } + + clone: wasmtime_component_type_clone, + delete: wasmtime_component_type_delete, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_type_import_count( + ty: &wasmtime_component_type_t, + engine: &wasm_engine_t, +) -> usize { + ty.ty.imports(&engine.engine).len() +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn wasmtime_component_type_import_get( + ty: &wasmtime_component_type_t, + engine: &wasm_engine_t, + name: *const u8, + name_len: usize, + ret: &mut MaybeUninit, +) -> bool { + let name = unsafe { std::slice::from_raw_parts(name, name_len) }; + let Ok(name) = std::str::from_utf8(name) else { + return false; + }; + match ty.ty.get_import(&engine.engine, name) { + Some(item) => { + ret.write(item.into()); + true + } + None => false, + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_type_import_nth( + ty: &wasmtime_component_type_t, + engine: &wasm_engine_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, + type_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.imports(&engine.engine).nth(nth) { + Some((name, item)) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + type_ret.write(item.into()); + true + } + None => false, + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_type_export_count( + ty: &wasmtime_component_type_t, + engine: &wasm_engine_t, +) -> usize { + ty.ty.exports(&engine.engine).len() +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn wasmtime_component_type_export_get( + ty: &wasmtime_component_type_t, + engine: &wasm_engine_t, + name: *const u8, + name_len: usize, + ret: &mut MaybeUninit, +) -> bool { + let name = unsafe { std::slice::from_raw_parts(name, name_len) }; + let Ok(name) = std::str::from_utf8(name) else { + return false; + }; + match ty.ty.get_export(&engine.engine, name) { + Some(item) => { + ret.write(item.into()); + true + } + None => false, + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_type_export_nth( + ty: &wasmtime_component_type_t, + engine: &wasm_engine_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, + type_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.exports(&engine.engine).nth(nth) { + Some((name, item)) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + type_ret.write(item.into()); + true + } + None => false, + } +} + +#[derive(Clone)] +#[repr(C, u8)] +pub enum wasmtime_component_item_t { + Component(Box), + ComponentInstance(Box), + Module(Box), + ComponentFunc(Box), + Resource(Box), + CoreFunc(Box), + Type(wasmtime_component_valtype_t), +} + +impl From for wasmtime_component_item_t { + fn from(item: ComponentItem) -> Self { + match item { + ComponentItem::Component(ty) => { + wasmtime_component_item_t::Component(Box::new(ty.into())) + } + ComponentItem::ComponentInstance(ty) => { + wasmtime_component_item_t::ComponentInstance(Box::new(ty.into())) + } + ComponentItem::Module(ty) => wasmtime_component_item_t::Module(Box::new(ty.into())), + ComponentItem::ComponentFunc(ty) => { + wasmtime_component_item_t::ComponentFunc(Box::new(ty.into())) + } + ComponentItem::Resource(ty) => wasmtime_component_item_t::Resource(Box::new(ty.into())), + ComponentItem::CoreFunc(ty) => { + wasmtime_component_item_t::CoreFunc(Box::new(wasm_functype_t::new(ty))) + } + ComponentItem::Type(ty) => wasmtime_component_item_t::Type(ty.into()), + } + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_item_clone( + item: &wasmtime_component_item_t, + ret: &mut MaybeUninit, +) { + ret.write(item.clone()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_item_delete( + item: &mut ManuallyDrop, +) { + unsafe { + ManuallyDrop::drop(item); + } +} diff --git a/crates/c-api/src/component/types/func.rs b/crates/c-api/src/component/types/func.rs new file mode 100644 index 000000000000..6103a9e25bd5 --- /dev/null +++ b/crates/c-api/src/component/types/func.rs @@ -0,0 +1,54 @@ +use crate::wasmtime_component_valtype_t; +use std::mem::MaybeUninit; +use wasmtime::component::types::ComponentFunc; + +type_wrapper! { + pub struct wasmtime_component_func_type_t { + pub(crate) ty: ComponentFunc, + } + + clone: wasmtime_component_func_type_clone, + delete: wasmtime_component_func_type_delete, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_func_type_param_count( + ty: &wasmtime_component_func_type_t, +) -> usize { + ty.ty.params().len() +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn wasmtime_component_func_type_param_nth( + ty: &wasmtime_component_func_type_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, + type_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.params().nth(nth) { + Some((name, item)) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + type_ret.write(item.into()); + true + } + None => false, + } +} +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_func_type_result( + ty: &wasmtime_component_func_type_t, + type_ret: &mut MaybeUninit, +) -> bool { + let len = ty.ty.results().len(); + assert!(len <= 1); + match ty.ty.results().next() { + Some(item) => { + type_ret.write(item.into()); + true + } + None => false, + } +} diff --git a/crates/c-api/src/component/types/instance.rs b/crates/c-api/src/component/types/instance.rs new file mode 100644 index 000000000000..55ea85f09b44 --- /dev/null +++ b/crates/c-api/src/component/types/instance.rs @@ -0,0 +1,62 @@ +use crate::{wasm_engine_t, wasmtime_component_item_t}; +use std::mem::MaybeUninit; +use wasmtime::component::types::ComponentInstance; + +type_wrapper! { + pub struct wasmtime_component_instance_type_t { + pub(crate) ty: ComponentInstance, + } + + clone: wasmtime_component_instance_type_clone, + delete: wasmtime_component_instance_type_delete, +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn wasmtime_component_instance_type_export_count( + ty: &wasmtime_component_instance_type_t, + engine: &wasm_engine_t, +) -> usize { + ty.ty.exports(&engine.engine).count() +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn wasmtime_component_instance_type_export_get( + ty: &wasmtime_component_instance_type_t, + engine: &wasm_engine_t, + name: *const u8, + name_len: usize, + ret: &mut MaybeUninit, +) -> bool { + let name = unsafe { std::slice::from_raw_parts(name, name_len) }; + let Ok(name) = std::str::from_utf8(name) else { + return false; + }; + match ty.ty.get_export(&engine.engine, name) { + Some(item) => { + ret.write(item.into()); + true + } + None => false, + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_instance_type_export_nth( + ty: &wasmtime_component_instance_type_t, + engine: &wasm_engine_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, + type_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.exports(&engine.engine).nth(nth) { + Some((name, item)) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + type_ret.write(item.into()); + true + } + None => false, + } +} diff --git a/crates/c-api/src/component/types/module.rs b/crates/c-api/src/component/types/module.rs new file mode 100644 index 000000000000..2cf58aaae692 --- /dev/null +++ b/crates/c-api/src/component/types/module.rs @@ -0,0 +1,54 @@ +use crate::{CExternType, wasm_engine_t, wasm_exporttype_t, wasm_importtype_t}; +use wasmtime::component::types::Module; + +type_wrapper! { + pub struct wasmtime_module_type_t { + pub(crate) ty: Module, + } + + clone: wasmtime_module_type_clone, + delete: wasmtime_module_type_delete, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_module_type_import_count( + ty: &wasmtime_module_type_t, + engine: &wasm_engine_t, +) -> usize { + ty.ty.imports(&engine.engine).len() +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_module_type_import_nth<'a>( + ty: &'a wasmtime_module_type_t, + engine: &wasm_engine_t, + nth: usize, +) -> Option> { + let ((module, field), item) = ty.ty.imports(&engine.engine).nth(nth)?; + Some(Box::new(wasm_importtype_t::new( + module.to_string(), + field.to_string(), + CExternType::new(item), + ))) +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_module_type_export_count( + ty: &wasmtime_module_type_t, + engine: &wasm_engine_t, +) -> usize { + ty.ty.exports(&engine.engine).len() +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_module_type_export_nth<'a>( + ty: &'a wasmtime_module_type_t, + engine: &wasm_engine_t, + nth: usize, +) -> Option> { + let (name, item) = ty.ty.exports(&engine.engine).nth(nth)?; + Some(Box::new(wasm_exporttype_t::new( + name.to_string(), + CExternType::new(item), + ))) +} diff --git a/crates/c-api/src/component/types/resource.rs b/crates/c-api/src/component/types/resource.rs new file mode 100644 index 000000000000..9dd6a916e861 --- /dev/null +++ b/crates/c-api/src/component/types/resource.rs @@ -0,0 +1,21 @@ +use wasmtime::component::ResourceType; + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_resource_type_t { + pub(crate) ty: ResourceType, + } + + clone: wasmtime_component_resource_type_clone, + delete: wasmtime_component_resource_type_delete, + equal: wasmtime_component_resource_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_resource_type_new_host( + ty: u32, +) -> Box { + Box::new(wasmtime_component_resource_type_t { + ty: ResourceType::host_dynamic(ty), + }) +} diff --git a/crates/c-api/src/component/types/val.rs b/crates/c-api/src/component/types/val.rs new file mode 100644 index 000000000000..b705ada33031 --- /dev/null +++ b/crates/c-api/src/component/types/val.rs @@ -0,0 +1,398 @@ +use crate::wasmtime_component_resource_type_t; +use std::mem::{ManuallyDrop, MaybeUninit}; +use wasmtime::component::types::*; + +#[derive(Clone, PartialEq)] +#[repr(C, u8)] +pub enum wasmtime_component_valtype_t { + Bool, + S8, + S16, + S32, + S64, + U8, + U16, + U32, + U64, + F32, + F64, + Char, + String, + List(Box), + Record(Box), + Tuple(Box), + Variant(Box), + Enum(Box), + Option(Box), + Result(Box), + Flags(Box), + Own(Box), + Borrow(Box), + Future(Box), + Stream(Box), + ErrorContext, +} + +impl From for wasmtime_component_valtype_t { + fn from(item: Type) -> Self { + match item { + Type::Bool => Self::Bool, + Type::S8 => Self::S8, + Type::S16 => Self::S16, + Type::S32 => Self::S32, + Type::S64 => Self::S64, + Type::U8 => Self::U8, + Type::U16 => Self::U16, + Type::U32 => Self::U32, + Type::U64 => Self::U64, + Type::Float32 => Self::F32, + Type::Float64 => Self::F64, + Type::Char => Self::Char, + Type::String => Self::String, + Type::List(ty) => Self::List(Box::new(ty.into())), + Type::Record(ty) => Self::Record(Box::new(ty.into())), + Type::Tuple(ty) => Self::Tuple(Box::new(ty.into())), + Type::Variant(ty) => Self::Variant(Box::new(ty.into())), + Type::Enum(ty) => Self::Enum(Box::new(ty.into())), + Type::Option(ty) => Self::Option(Box::new(ty.into())), + Type::Result(ty) => Self::Result(Box::new(ty.into())), + Type::Flags(ty) => Self::Flags(Box::new(ty.into())), + Type::Own(ty) => Self::Own(Box::new(ty.into())), + Type::Borrow(ty) => Self::Borrow(Box::new(ty.into())), + Type::Future(ty) => Self::Future(Box::new(ty.into())), + Type::Stream(ty) => Self::Stream(Box::new(ty.into())), + Type::ErrorContext => Self::ErrorContext, + } + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_valtype_clone( + ty: &wasmtime_component_valtype_t, + ret: &mut MaybeUninit, +) { + ret.write(ty.clone()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_valtype_equal( + a: &wasmtime_component_valtype_t, + b: &wasmtime_component_valtype_t, +) -> bool { + a == b +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn wasmtime_component_valtype_delete( + ret: &mut ManuallyDrop, +) { + unsafe { ManuallyDrop::drop(ret) }; +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_list_type_t { + pub(crate) ty: List, + } + + clone: wasmtime_component_list_type_clone, + delete: wasmtime_component_list_type_delete, + equal: wasmtime_component_list_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_list_type_element( + ty: &wasmtime_component_list_type_t, + type_ret: &mut MaybeUninit, +) { + type_ret.write(ty.ty.ty().into()); +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_record_type_t { + pub(crate) ty: Record, + } + clone: wasmtime_component_record_type_clone, + delete: wasmtime_component_record_type_delete, + equal: wasmtime_component_record_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_record_type_field_count( + ty: &wasmtime_component_record_type_t, +) -> usize { + ty.ty.fields().len() +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_record_type_field_nth( + ty: &wasmtime_component_record_type_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, + type_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.fields().nth(nth) { + Some(Field { name, ty }) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + type_ret.write(ty.into()); + true + } + None => false, + } +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_tuple_type_t { + pub(crate) ty: Tuple, + } + clone: wasmtime_component_tuple_type_clone, + delete: wasmtime_component_tuple_type_delete, + equal: wasmtime_component_tuple_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_tuple_type_types_count( + ty: &wasmtime_component_tuple_type_t, +) -> usize { + ty.ty.types().len() +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_tuple_type_types_nth( + ty: &wasmtime_component_tuple_type_t, + nth: usize, + type_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.types().nth(nth) { + Some(item) => { + type_ret.write(item.into()); + true + } + None => false, + } +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_variant_type_t { + pub(crate) ty: Variant, + } + clone: wasmtime_component_variant_type_clone, + delete: wasmtime_component_variant_type_delete, + equal: wasmtime_component_variant_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_variant_type_case_count( + ty: &wasmtime_component_variant_type_t, +) -> usize { + ty.ty.cases().len() +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_variant_type_case_nth( + ty: &wasmtime_component_variant_type_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, + has_payload_ret: &mut MaybeUninit, + payload_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.cases().nth(nth) { + Some(Case { name, ty }) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + match ty { + Some(payload) => { + has_payload_ret.write(true); + payload_ret.write(payload.into()); + } + None => { + has_payload_ret.write(false); + } + } + true + } + None => false, + } +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_enum_type_t { + pub(crate) ty: Enum, + } + clone: wasmtime_component_enum_type_clone, + delete: wasmtime_component_enum_type_delete, + equal: wasmtime_component_enum_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_enum_type_names_count( + ty: &wasmtime_component_enum_type_t, +) -> usize { + ty.ty.names().len() +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_enum_type_names_nth( + ty: &wasmtime_component_enum_type_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.names().nth(nth) { + Some(name) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + true + } + None => false, + } +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_option_type_t { + pub(crate) ty: OptionType, + } + clone: wasmtime_component_option_type_clone, + delete: wasmtime_component_option_type_delete, + equal: wasmtime_component_option_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_option_type_ty( + ty: &wasmtime_component_option_type_t, + ret: &mut MaybeUninit, +) { + ret.write(ty.ty.ty().into()); +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_result_type_t { + pub(crate) ty: ResultType, + } + clone: wasmtime_component_result_type_clone, + delete: wasmtime_component_result_type_delete, + equal: wasmtime_component_result_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_result_type_ok( + ty: &wasmtime_component_result_type_t, + ret: &mut MaybeUninit, +) -> bool { + match ty.ty.ok() { + Some(ok) => { + ret.write(ok.into()); + true + } + None => false, + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_result_type_err( + ty: &wasmtime_component_result_type_t, + ret: &mut MaybeUninit, +) -> bool { + match ty.ty.err() { + Some(err) => { + ret.write(err.into()); + true + } + None => false, + } +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_flags_type_t { + pub(crate) ty: Flags, + } + clone: wasmtime_component_flags_type_clone, + delete: wasmtime_component_flags_type_delete, + equal: wasmtime_component_flags_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_flags_type_names_count( + ty: &wasmtime_component_flags_type_t, +) -> usize { + ty.ty.names().len() +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_flags_type_names_nth( + ty: &wasmtime_component_flags_type_t, + nth: usize, + name_ret: &mut MaybeUninit<*const u8>, + name_len_ret: &mut MaybeUninit, +) -> bool { + match ty.ty.names().nth(nth) { + Some(name) => { + let name: &str = name; + name_ret.write(name.as_ptr()); + name_len_ret.write(name.len()); + true + } + None => false, + } +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_future_type_t { + pub(crate) ty: FutureType, + } + clone: wasmtime_component_future_type_clone, + delete: wasmtime_component_future_type_delete, + equal: wasmtime_component_future_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_future_type_ty( + ty: &wasmtime_component_future_type_t, + ret: &mut MaybeUninit, +) -> bool { + match ty.ty.ty() { + Some(ty) => { + ret.write(ty.into()); + true + } + None => false, + } +} + +type_wrapper! { + #[derive(PartialEq)] + pub struct wasmtime_component_stream_type_t { + pub(crate) ty: StreamType, + } + clone: wasmtime_component_stream_type_clone, + delete: wasmtime_component_stream_type_delete, + equal: wasmtime_component_stream_type_equal, +} + +#[unsafe(no_mangle)] +pub extern "C" fn wasmtime_component_stream_type_ty( + ty: &wasmtime_component_stream_type_t, + ret: &mut MaybeUninit, +) -> bool { + match ty.ty.ty() { + Some(ty) => { + ret.write(ty.into()); + true + } + None => false, + } +} diff --git a/crates/c-api/src/component/val.rs b/crates/c-api/src/component/val.rs index fa7ccfd55661..00c2c6a63963 100644 --- a/crates/c-api/src/component/val.rs +++ b/crates/c-api/src/component/val.rs @@ -1,9 +1,12 @@ -use crate::{WasmtimeStoreContextMut, handle_result, wasm_name_t, wasmtime_error_t}; +use crate::{ + WasmtimeStoreContextMut, handle_result, wasm_name_t, wasmtime_component_resource_type_t, + wasmtime_error_t, +}; use std::mem; use std::mem::{ManuallyDrop, MaybeUninit}; use std::ptr; use std::slice; -use wasmtime::component::{ResourceAny, ResourceDynamic, ResourceType, Val}; +use wasmtime::component::{ResourceAny, ResourceDynamic, Val}; crate::declare_vecs! { ( @@ -345,41 +348,6 @@ pub unsafe extern "C" fn wasmtime_component_val_delete( } } -#[repr(C)] -pub struct wasmtime_component_resource_type_t { - pub(crate) ty: ResourceType, -} - -#[unsafe(no_mangle)] -pub extern "C" fn wasmtime_component_resource_type_new_host( - ty: u32, -) -> Box { - Box::new(wasmtime_component_resource_type_t { - ty: ResourceType::host_dynamic(ty), - }) -} - -#[unsafe(no_mangle)] -pub extern "C" fn wasmtime_component_resource_type_clone( - ty: &wasmtime_component_resource_type_t, -) -> Box { - Box::new(wasmtime_component_resource_type_t { ty: ty.ty }) -} - -#[unsafe(no_mangle)] -pub extern "C" fn wasmtime_component_resource_type_equal( - a: &wasmtime_component_resource_type_t, - b: &wasmtime_component_resource_type_t, -) -> bool { - a.ty == b.ty -} - -#[unsafe(no_mangle)] -pub extern "C" fn wasmtime_component_resource_type_delete( - _resource: Option>, -) { -} - #[repr(C)] #[derive(Clone)] pub struct wasmtime_component_resource_any_t { diff --git a/crates/c-api/tests/CMakeLists.txt b/crates/c-api/tests/CMakeLists.txt index 423ca3575245..b77c1e68bfcc 100644 --- a/crates/c-api/tests/CMakeLists.txt +++ b/crates/c-api/tests/CMakeLists.txt @@ -37,6 +37,7 @@ add_capi_test(tests FILES component/call_func.cc component/values.cc component/linker.cc + component/types.cc error.cc config.cc wat.cc diff --git a/crates/c-api/tests/component/types.cc b/crates/c-api/tests/component/types.cc new file mode 100644 index 000000000000..181f6131becb --- /dev/null +++ b/crates/c-api/tests/component/types.cc @@ -0,0 +1,330 @@ +#include +#include + +using namespace wasmtime::component; +using wasmtime::Engine; +using wasmtime::ExternType; +using wasmtime::Result; +using wasmtime::Span; +using wasmtime::Store; + +TEST(types, empty_component) { + Engine engine; + + auto component = Component::compile(engine, R"( +(component) + )") + .unwrap() + .type(); + + EXPECT_EQ(component.import_count(engine), 0); + EXPECT_EQ(component.export_count(engine), 0); +} + +TEST(types, component_resource) { + Engine engine; + + auto component = Component::compile(engine, R"( +(component + (import "x" (type $t (sub resource))) + (export "x" (type $t)) +) + )") + .unwrap() + .type(); + + EXPECT_EQ(component.import_count(engine), 1); + auto ty = component.import_get(engine, "x")->resource(); + auto i = *component.import_nth(engine, 0); + EXPECT_EQ(i.first, "x"); + EXPECT_EQ(ty, i.second.resource()); + + EXPECT_EQ(component.export_count(engine), 1); + + EXPECT_EQ(component.export_get(engine, "x")->resource(), ty); + auto e = *component.import_nth(engine, 0); + EXPECT_EQ(e.first, "x"); + EXPECT_EQ(ty, e.second.resource()); +} + +TEST(types, component_instance) { + Engine engine; + + auto component = Component::compile(engine, R"( +(component + (import "x" (instance $a (export "t" (type (sub resource))))) + (export "x" (instance $a)) +) + )") + .unwrap() + .type(); + + auto ty = component.import_get(engine, "x")->component_instance(); + EXPECT_EQ(ty.export_count(engine), 1); + auto resource_ty = ty.export_get(engine, "t")->resource(); + EXPECT_EQ(resource_ty, ty.export_nth(engine, 0)->second.resource()); + EXPECT_EQ("t", ty.export_nth(engine, 0)->first); + + auto ty2 = component.export_get(engine, "x")->component_instance(); + EXPECT_EQ(resource_ty, ty2.export_get(engine, "t")->resource()); +} + +TEST(types, component_func) { + Engine engine; + + auto component = Component::compile(engine, R"( +(component + (import "x" (func)) +) + )") + .unwrap() + .type(); + + auto ty = component.import_get(engine, "x")->component_func(); + EXPECT_EQ(ty.param_count(), 0); + EXPECT_FALSE(ty.result()); + + component = Component::compile(engine, R"( +(component + (import "x" (func (param "x" u32) (result string))) +) + )") + .unwrap() + .type(); + + ty = component.import_get(engine, "x")->component_func(); + EXPECT_EQ(ty.param_count(), 1); + EXPECT_EQ(ty.param_nth(0)->first, "x"); + EXPECT_TRUE(ty.param_nth(0)->second.is_u32()); + EXPECT_EQ(ty.param_nth(0)->second, ValType::new_u32()); + + EXPECT_TRUE(ty.result()->is_string()); + EXPECT_EQ(*ty.result(), ValType::new_string()); +} + +TEST(types, module_type) { + Engine engine; + + auto component = Component::compile(engine, R"( +(component + (import "x" (core module)) +) + )") + .unwrap(); + auto cty = component.type(); + + auto ty = cty.import_get(engine, "x")->module(); + EXPECT_EQ(ty.import_count(engine), 0); + EXPECT_EQ(ty.export_count(engine), 0); + + component = Component::compile(engine, R"( +(component + (import "x" (core module + (import "" "" (func)) + (export "x" (global (mut i32))) + )) +) + )") + .unwrap(); + cty = component.type(); + + ty = cty.import_get(engine, "x")->module(); + EXPECT_EQ(ty.import_count(engine), 1); + auto import = *ty.import_nth(engine, 0); + EXPECT_EQ(import.ref().module(), ""); + EXPECT_EQ(import.ref().name(), ""); + + auto import_item_ty = ExternType::from_import(import.ref()); + auto func_ty = std::get(import_item_ty); + EXPECT_EQ(func_ty.params().size(), 0); + EXPECT_EQ(func_ty.results().size(), 0); + + auto export_ty = ty.export_nth(engine, 0); + EXPECT_EQ(export_ty->ref().name(), "x"); + auto export_item_ty = ExternType::from_export(export_ty->ref()); + auto global_ty = std::get(export_item_ty); + EXPECT_EQ(global_ty.content().kind(), wasmtime::ValKind::I32); + EXPECT_TRUE(global_ty.is_mutable()); +} + +static ValType result(const char *wat) { + Engine engine; + auto component = Component::compile(engine, wat).unwrap(); + return *component.type().import_get(engine, "f")->component_func().result(); +} + +TEST(types, valtype_primitives) { + EXPECT_TRUE( + result("(component (import \"f\" (func (result bool))))").is_bool()); + EXPECT_TRUE(result("(component (import \"f\" (func (result u8))))").is_u8()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result u16))))").is_u16()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result u32))))").is_u32()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result u64))))").is_u64()); + EXPECT_TRUE(result("(component (import \"f\" (func (result s8))))").is_s8()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result s16))))").is_s16()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result s32))))").is_s32()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result s64))))").is_s64()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result f32))))").is_f32()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result f64))))").is_f64()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result char))))").is_char()); + EXPECT_TRUE( + result("(component (import \"f\" (func (result string))))").is_string()); +} + +TEST(types, valtype_list) { + auto ty = result("(component (import \"f\" (func (result (list u8)))))"); + EXPECT_TRUE(ty.is_list()); + auto elem = ty.list().element(); + EXPECT_TRUE(elem.is_u8()); +} + +TEST(types, valtype_record) { + auto ty = result(R"( + (component + (type $t' (record (field "a" u8) (field "b" u16))) + (import "t" (type $t (eq $t'))) + (import "f" (func (result $t))) + ) + )"); + EXPECT_TRUE(ty.is_record()); + EXPECT_EQ(ty.record().field_count(), 2); + auto [name, field_ty] = *ty.record().field_nth(0); + EXPECT_EQ(name, "a"); + EXPECT_TRUE(field_ty.is_u8()); + auto [name2, field_ty2] = *ty.record().field_nth(1); + EXPECT_EQ(name2, "b"); + EXPECT_TRUE(field_ty2.is_u16()); +} + +TEST(types, valtype_tuple) { + auto ty = result("(component (import \"f\" (func (result (tuple u16 u8)))))"); + EXPECT_TRUE(ty.is_tuple()); + EXPECT_EQ(ty.tuple().types_count(), 2); + EXPECT_TRUE(ty.tuple().types_nth(0)->is_u16()); + EXPECT_TRUE(ty.tuple().types_nth(1)->is_u8()); +} + +TEST(types, valtype_variant) { + auto ty = result(R"( + (component + (type $t' (variant (case "a") (case "b" u16))) + (import "t" (type $t (eq $t'))) + (import "f" (func (result $t))) + ) + )"); + EXPECT_TRUE(ty.is_variant()); + EXPECT_EQ(ty.variant().case_count(), 2); + auto [name, case_ty] = *ty.variant().case_nth(0); + EXPECT_EQ(name, "a"); + EXPECT_FALSE(case_ty.has_value()); + auto [name2, case_ty2] = *ty.variant().case_nth(1); + EXPECT_EQ(name2, "b"); + EXPECT_TRUE(case_ty2->is_u16()); +} + +TEST(types, valtype_enum) { + auto ty = result(R"( + (component + (type $t' (enum "a" "b" "c")) + (import "t" (type $t (eq $t'))) + (import "f" (func (result $t))) + ) + )"); + EXPECT_TRUE(ty.is_enum()); + auto enum_ = ty.enum_(); + EXPECT_EQ(enum_.names_count(), 3); + EXPECT_EQ(enum_.names_nth(0), "a"); + EXPECT_EQ(enum_.names_nth(1), "b"); + EXPECT_EQ(enum_.names_nth(2), "c"); +} + +TEST(types, valtype_flags) { + auto ty = result(R"( + (component + (type $t' (flags "a" "b" "c")) + (import "t" (type $t (eq $t'))) + (import "f" (func (result $t))) + ) + )"); + EXPECT_TRUE(ty.is_flags()); + auto flags = ty.flags(); + EXPECT_EQ(flags.names_count(), 3); + EXPECT_EQ(flags.names_nth(0), "a"); + EXPECT_EQ(flags.names_nth(1), "b"); + EXPECT_EQ(flags.names_nth(2), "c"); +} + +TEST(types, valtype_option) { + auto ty = result(R"( + (component (import "f" (func (result (option u8))))) + )"); + EXPECT_TRUE(ty.is_option()); + EXPECT_TRUE(ty.option().ty().is_u8()); +} + +TEST(types, valtype_result) { + auto ty = result(R"( + (component (import "f" (func (result (result u8))))) + )"); + EXPECT_TRUE(ty.is_result()); + EXPECT_TRUE(ty.result().ok()->is_u8()); + EXPECT_FALSE(ty.result().err().has_value()); + + ty = result(R"( + (component (import "f" (func (result (result (error u8)))))) + )"); + EXPECT_TRUE(ty.is_result()); + EXPECT_FALSE(ty.result().ok().has_value()); + EXPECT_TRUE(ty.result().err()->is_u8()); + + ty = result(R"( + (component (import "f" (func (result (result))))) + )"); + EXPECT_TRUE(ty.is_result()); + EXPECT_FALSE(ty.result().ok().has_value()); + EXPECT_FALSE(ty.result().err().has_value()); +} + +TEST(types, func_result) { + Engine engine; + auto wat = R"( +(component + (core module $m + (func (export "f1")) + (func (export "f2") (param i32) (result i32) unreachable) + ) + (core instance $i (instantiate $m)) + (func (export "f1") (canon lift (core func $i "f1"))) + (func (export "f2") (param "x" u32) (result u32) + (canon lift (core func $i "f2"))) +) +)"; + auto component = Component::compile(engine, wat).unwrap(); + Store store(engine); + auto instance = Linker(engine).instantiate(store, component).unwrap(); + auto f1_index = *instance.get_export_index(store, nullptr, "f1"); + auto f2_index = *instance.get_export_index(store, nullptr, "f2"); + auto f1 = *instance.get_func(store, f1_index); + auto f2 = *instance.get_func(store, f2_index); + + EXPECT_EQ(f1.type(store).param_count(), 0); + EXPECT_FALSE(f1.type(store).result().has_value()); + + const auto &ty = f2.type(store); + EXPECT_EQ(ty.param_count(), 1); + const auto [name, param_ty] = *ty.param_nth(0); + EXPECT_EQ(name, "x"); + EXPECT_TRUE(param_ty.is_u32()); + auto result = ty.result(); + ASSERT_TRUE(result.has_value()); + EXPECT_TRUE(result->is_u32()); +} diff --git a/crates/c-api/tests/component/values.cc b/crates/c-api/tests/component/values.cc index dbc8db096080..be9a562f1252 100644 --- a/crates/c-api/tests/component/values.cc +++ b/crates/c-api/tests/component/values.cc @@ -88,8 +88,8 @@ struct Context { } }; -typedef Result (*host_func_t)(Store::Context, Span, - Span); +typedef Result (*host_func_t)(Store::Context, const FuncType &, + Span, Span); static Context create(std::string_view type, std::string_view body, std::string_view host_params, host_func_t callback) { @@ -144,7 +144,7 @@ call $do local.get $res )", "(param i64 i64 i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &_ty, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], 1, 2); @@ -193,7 +193,7 @@ call $do local.get $res )", "(param i32 i32 i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], "hello from A!"); @@ -249,7 +249,7 @@ call $do local.get $res )", "(param i32 i32 i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], {1, 2, 3}); @@ -306,7 +306,7 @@ call $do local.get $res )", "(param i32 i32 i32 i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], {1, 2, 3}); @@ -380,7 +380,7 @@ call $do local.get $res )", "(param i32 i32 i32 i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check_aa(args[0], 123); @@ -419,7 +419,7 @@ local.get $x call $do )", "(param i32) (result i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], "aa"); @@ -478,7 +478,7 @@ call $do local.get $res )", "(param i32 i32 i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], 123); @@ -535,7 +535,7 @@ call $do local.get $res )", "(param i32 i32 i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], true, 123); @@ -579,7 +579,7 @@ local.get $x call $do )", "(param i32) (result i32)", - +[](Store::Context, Span args, + +[](Store::Context, const FuncType &, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(args[0], {"aa"}); @@ -882,7 +882,7 @@ TEST(component, value_host_resource) { i.add_func( "f", - +[](Store::Context cx, Span args, + +[](Store::Context cx, const FuncType &_ty, Span args, Span rets) -> Result { EXPECT_EQ(args.size(), 1); check(cx, args[0], 42);