#ifndef WASMTIME_TYPES_VAL_HH
#define WASMTIME_TYPES_VAL_HH
#include <memory>
#include <ostream>
#include <wasm.h>
#include <wasmtime/types/_structref_class.hh>
#include <wasmtime/types/_val_class.hh>
#include <wasmtime/types/arrayref.hh>
#include <wasmtime/types/exnref.hh>
#include <wasmtime/types/func.hh>
#include <wasmtime/types/val.h>
#include <wasmtime/val.h>
namespace wasmtime {
class HeapType {
wasmtime_heaptype_t ty;
HeapType(wasmtime_heaptype_kind_t ty) { this->ty.kind = ty; }
public:
HeapType(const HeapType &other) { wasmtime_heaptype_clone(&other.ty, &ty); }
HeapType &operator=(const HeapType &other) {
wasmtime_heaptype_delete(&ty);
wasmtime_heaptype_clone(&other.ty, &ty);
return *this;
}
~HeapType() {
if (is_concrete())
wasmtime_heaptype_delete(&ty);
}
HeapType(HeapType &&other) {
ty = other.ty;
other.ty.kind = WASMTIME_HEAPTYPE_KIND_NONE;
}
HeapType &operator=(HeapType &&other) {
wasmtime_heaptype_delete(&ty);
ty = other.ty;
other.ty.kind = WASMTIME_HEAPTYPE_KIND_NONE;
return *this;
}
static HeapType extern_() { return HeapType(WASMTIME_HEAPTYPE_KIND_EXTERN); }
static HeapType noextern() {
return HeapType(WASMTIME_HEAPTYPE_KIND_NOEXTERN);
}
static HeapType func() { return HeapType(WASMTIME_HEAPTYPE_KIND_FUNC); }
HeapType(const FuncType &ty) {
this->ty.kind = WASMTIME_HEAPTYPE_KIND_CONCRETE_FUNC;
this->ty.of.concrete_func = FuncType(ty).capi_release();
}
static HeapType nofunc() { return HeapType(WASMTIME_HEAPTYPE_KIND_NOFUNC); }
static HeapType any() { return HeapType(WASMTIME_HEAPTYPE_KIND_ANY); }
static HeapType none() { return HeapType(WASMTIME_HEAPTYPE_KIND_NONE); }
static HeapType eq() { return HeapType(WASMTIME_HEAPTYPE_KIND_EQ); }
static HeapType i31() { return HeapType(WASMTIME_HEAPTYPE_KIND_I31); }
static HeapType array() { return HeapType(WASMTIME_HEAPTYPE_KIND_ARRAY); }
HeapType(const ArrayType &ty) {
this->ty.kind = WASMTIME_HEAPTYPE_KIND_CONCRETE_ARRAY;
this->ty.of.concrete_array = ArrayType(ty).capi_release();
}
static HeapType struct_() { return HeapType(WASMTIME_HEAPTYPE_KIND_STRUCT); }
HeapType(const StructType &ty) {
this->ty.kind = WASMTIME_HEAPTYPE_KIND_CONCRETE_STRUCT;
this->ty.of.concrete_struct = StructType(ty).capi_release();
}
static HeapType exn() { return HeapType(WASMTIME_HEAPTYPE_KIND_EXN); }
HeapType(const ExnType &ty) {
this->ty.kind = WASMTIME_HEAPTYPE_KIND_CONCRETE_EXN;
this->ty.of.concrete_exn = ExnType(ty).capi_release();
}
static HeapType noexn() { return HeapType(WASMTIME_HEAPTYPE_KIND_NOEXN); }
bool is_concrete() const {
switch (ty.kind) {
case WASMTIME_HEAPTYPE_KIND_CONCRETE_FUNC:
case WASMTIME_HEAPTYPE_KIND_CONCRETE_ARRAY:
case WASMTIME_HEAPTYPE_KIND_CONCRETE_STRUCT:
case WASMTIME_HEAPTYPE_KIND_CONCRETE_EXN:
return true;
default:
return false;
}
}
bool is_extern() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_EXTERN; }
bool is_noextern() const {
return ty.kind == WASMTIME_HEAPTYPE_KIND_NOEXTERN;
}
bool is_func() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_FUNC; }
std::optional<FuncType::Ref> as_concrete_func() const {
if (ty.kind == WASMTIME_HEAPTYPE_KIND_CONCRETE_FUNC) {
return FuncType::Ref(ty.of.concrete_func);
}
return std::nullopt;
}
bool is_nofunc() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_NOFUNC; }
bool is_any() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_ANY; }
bool is_none() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_NONE; }
bool is_eq() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_EQ; }
bool is_i31() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_I31; }
bool is_array() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_ARRAY; }
const ArrayType *as_concrete_array() const {
static_assert(sizeof(ArrayType) == sizeof(wasmtime_array_type_t *));
if (ty.kind == WASMTIME_HEAPTYPE_KIND_CONCRETE_ARRAY) {
return reinterpret_cast<const ArrayType *>(&ty.of.concrete_array);
}
return nullptr;
}
bool is_struct() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_STRUCT; }
const StructType *as_concrete_struct() const {
static_assert(sizeof(StructType) == sizeof(wasmtime_struct_type_t *));
if (ty.kind == WASMTIME_HEAPTYPE_KIND_CONCRETE_STRUCT) {
return reinterpret_cast<const StructType *>(&ty.of.concrete_struct);
}
return nullptr;
}
bool is_exn() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_EXN; }
const ExnType *as_concrete_exn() const {
static_assert(sizeof(ExnType) == sizeof(wasmtime_exn_type_t *));
if (ty.kind == WASMTIME_HEAPTYPE_KIND_CONCRETE_EXN) {
return reinterpret_cast<const ExnType *>(&ty.of.concrete_exn);
}
return nullptr;
}
bool is_noexn() const { return ty.kind == WASMTIME_HEAPTYPE_KIND_NOEXN; }
const wasmtime_heaptype_t *capi() const { return &ty; }
};
class RefType {
wasmtime_reftype_t ty;
public:
RefType(const RefType &other) { wasmtime_reftype_clone(&other.ty, &ty); }
RefType &operator=(const RefType &other) {
wasmtime_reftype_delete(&ty);
wasmtime_reftype_clone(&other.ty, &ty);
return *this;
}
~RefType() { wasmtime_reftype_delete(&ty); }
RefType(RefType &&other) {
ty = other.ty;
other.ty.heaptype.kind = WASMTIME_HEAPTYPE_KIND_NONE;
}
RefType &operator=(RefType &&other) {
wasmtime_reftype_delete(&ty);
ty = other.ty;
other.ty.heaptype.kind = WASMTIME_HEAPTYPE_KIND_NONE;
return *this;
}
RefType(bool nullable, const HeapType &heaptype) {
ty.nullable = nullable;
wasmtime_heaptype_clone(heaptype.capi(), &ty.heaptype);
}
bool nullable() const { return ty.nullable; }
const HeapType &heaptype() const {
static_assert(sizeof(HeapType) == sizeof(wasmtime_heaptype_t));
return *reinterpret_cast<const HeapType *>(&ty.heaptype);
}
static RefType externref() { return RefType(true, HeapType::extern_()); }
static RefType nullexternref() { return RefType(true, HeapType::noextern()); }
static RefType funcref() { return RefType(true, HeapType::func()); }
static RefType nullfuncref() { return RefType(true, HeapType::nofunc()); }
static RefType anyref() { return RefType(true, HeapType::any()); }
static RefType eqref() { return RefType(true, HeapType::eq()); }
static RefType i31ref() { return RefType(true, HeapType::i31()); }
static RefType arrayref() { return RefType(true, HeapType::array()); }
static RefType structref() { return RefType(true, HeapType::struct_()); }
static RefType nullref() { return RefType(true, HeapType::none()); }
static RefType exnref() { return RefType(true, HeapType::exn()); }
static RefType nullexnref() { return RefType(true, HeapType::noexn()); }
const wasmtime_reftype_t *capi() const { return &ty; }
};
inline const RefType *ValType::as_ref() const {
static_assert(sizeof(RefType) == sizeof(wasmtime_reftype_t));
if (wasmtime_ty.kind == WASMTIME_VALTYPE_KIND_REF) {
return reinterpret_cast<const RefType *>(&wasmtime_ty.reftype);
}
return nullptr;
}
inline ValType::ValType(const Engine &engine, const RefType &ty)
: ref(nullptr) {
wasmtime_ty.kind = WASMTIME_VALTYPE_KIND_REF;
wasmtime_reftype_clone(ty.capi(), &wasmtime_ty.reftype);
ptr.reset(wasmtime_valtype_to_wasm(engine.capi(), &wasmtime_ty));
ref = ptr.get();
}
inline ValType ValType::anyref() {
wasmtime_valtype_t ty;
ty.kind = WASMTIME_VALTYPE_KIND_REF;
ty.reftype.nullable = true;
ty.reftype.heaptype.kind = WASMTIME_HEAPTYPE_KIND_ANY;
return ValType(&ty);
}
inline ValType ValType::exnref() {
wasmtime_valtype_t ty;
ty.kind = WASMTIME_VALTYPE_KIND_REF;
ty.reftype.nullable = true;
ty.reftype.heaptype.kind = WASMTIME_HEAPTYPE_KIND_EXN;
return ValType(&ty);
}
inline std::ostream &operator<<(std::ostream &os, const HeapType &e) {
const wasmtime_heaptype_t *ty = e.capi();
switch (ty->kind) {
case WASMTIME_HEAPTYPE_KIND_EXTERN:
os << "extern";
break;
case WASMTIME_HEAPTYPE_KIND_NOEXTERN:
os << "noextern";
break;
case WASMTIME_HEAPTYPE_KIND_FUNC:
os << "func";
break;
case WASMTIME_HEAPTYPE_KIND_CONCRETE_FUNC:
os << "$func";
break;
case WASMTIME_HEAPTYPE_KIND_NOFUNC:
os << "nofunc";
break;
case WASMTIME_HEAPTYPE_KIND_ANY:
os << "any";
break;
case WASMTIME_HEAPTYPE_KIND_NONE:
os << "none";
break;
case WASMTIME_HEAPTYPE_KIND_EQ:
os << "eq";
break;
case WASMTIME_HEAPTYPE_KIND_I31:
os << "i31";
break;
case WASMTIME_HEAPTYPE_KIND_ARRAY:
os << "array";
break;
case WASMTIME_HEAPTYPE_KIND_CONCRETE_ARRAY:
os << "$array";
break;
case WASMTIME_HEAPTYPE_KIND_STRUCT:
os << "struct";
break;
case WASMTIME_HEAPTYPE_KIND_CONCRETE_STRUCT:
os << "$struct";
break;
case WASMTIME_HEAPTYPE_KIND_EXN:
os << "exn";
break;
case WASMTIME_HEAPTYPE_KIND_NOEXN:
os << "noexn";
break;
default:
os << "unknown";
break;
}
return os;
}
inline std::ostream &operator<<(std::ostream &os, const RefType &e) {
os << "(ref ";
if (e.nullable())
os << "null ";
os << e.heaptype();
os << ")";
return os;
}
inline std::ostream &operator<<(std::ostream &os, const ValType &e) {
const wasmtime_valtype_t *ty = e.wasmtime_capi();
switch (ty->kind) {
case WASMTIME_VALTYPE_KIND_I32:
os << "i32";
break;
case WASMTIME_VALTYPE_KIND_I64:
os << "i64";
break;
case WASMTIME_VALTYPE_KIND_F32:
os << "f32";
break;
case WASMTIME_VALTYPE_KIND_F64:
os << "f64";
break;
case WASMTIME_VALTYPE_KIND_V128:
os << "v128";
break;
case WASMTIME_VALTYPE_KIND_REF:
os << *e.as_ref();
break;
default:
os << "unknown";
break;
}
return os;
}
};
#endif