Wasmtime
gc.hh
Go to the documentation of this file.
1
7#ifndef WASMTIME_GC_HH
8#define WASMTIME_GC_HH
9
10#include <wasmtime/config.hh>
11
12#ifdef WASMTIME_FEATURE_GC
13#include <vector>
14#include <wasmtime/gc.h>
15#include <wasmtime/val.hh>
16
17namespace wasmtime {
18
19class StructRef;
20class ArrayRef;
21
31class EqRef {
32 friend class Val;
33 friend class AnyRef;
34
35 wasmtime_eqref_t val;
36
37public:
39 explicit EqRef(wasmtime_eqref_t val) : val(val) {}
40
42 EqRef(const EqRef &other) { wasmtime_eqref_clone(&other.val, &val); }
43
45 EqRef &operator=(const EqRef &other) {
46 wasmtime_eqref_unroot(&val);
47 wasmtime_eqref_clone(&other.val, &val);
48 return *this;
49 }
50
52 EqRef(EqRef &&other) {
53 val = other.val;
54 wasmtime_eqref_set_null(&other.val);
55 }
56
58 EqRef &operator=(EqRef &&other) {
59 wasmtime_eqref_unroot(&val);
60 val = other.val;
61 wasmtime_eqref_set_null(&other.val);
62 return *this;
63 }
64
65 ~EqRef() { wasmtime_eqref_unroot(&val); }
66
68 static EqRef from_i31(Store::Context cx, uint32_t val) {
69 wasmtime_eqref_t out;
70 wasmtime_eqref_from_i31(cx.capi(), val, &out);
71 return EqRef(out);
72 }
73
75 bool is_i31(Store::Context cx) const {
76 return wasmtime_eqref_is_i31(cx.capi(), &val);
77 }
78
81 std::optional<uint32_t> i31_get_u(Store::Context cx) const {
82 uint32_t dst;
83 if (wasmtime_eqref_i31_get_u(cx.capi(), &val, &dst))
84 return dst;
85 return std::nullopt;
86 }
87
90 std::optional<int32_t> i31_get_s(Store::Context cx) const {
91 int32_t dst;
92 if (wasmtime_eqref_i31_get_s(cx.capi(), &val, &dst))
93 return dst;
94 return std::nullopt;
95 }
96
98 bool is_struct(Store::Context cx) const {
99 return wasmtime_eqref_is_struct(cx.capi(), &val);
100 }
101
103 bool is_array(Store::Context cx) const {
104 return wasmtime_eqref_is_array(cx.capi(), &val);
105 }
106
108 AnyRef to_anyref() const {
109 wasmtime_anyref_t out;
110 wasmtime_eqref_to_anyref(&val, &out);
111 return AnyRef(out);
112 }
113
115 //
116 // as_struct() defined after StructRef below.
117 inline StructRef as_struct(Store::Context cx) const;
118
120 //
121 // as_array() defined after ArrayRef below.
122 inline ArrayRef as_array(Store::Context cx) const;
123};
124
129struct FieldType {
131 wasmtime_storage_kind_t kind;
133 bool mutable_;
134
136 static FieldType mut_(wasmtime_storage_kind_t k) { return {k, true}; }
138 static FieldType const_(wasmtime_storage_kind_t k) { return {k, false}; }
139};
140
147class StructType {
148 struct Deleter {
149 void operator()(wasmtime_struct_type_t *p) const {
150 wasmtime_struct_type_delete(p);
151 }
152 };
153 std::unique_ptr<wasmtime_struct_type_t, Deleter> ptr;
154
155public:
157 static StructType create(const Engine &engine,
158 const std::vector<FieldType> &fields) {
159 static_assert(sizeof(FieldType) == sizeof(wasmtime_field_type_t));
160 auto *raw = wasmtime_struct_type_new(
161 engine.capi(),
162 reinterpret_cast<const wasmtime_field_type_t *>(fields.data()),
163 fields.size());
164 StructType ty;
165 ty.ptr.reset(raw);
166 return ty;
167 }
168
170 const wasmtime_struct_type_t *capi() const { return ptr.get(); }
171
172private:
173 StructType() = default;
174 friend class StructRefPre;
175};
176
183class StructRefPre {
184 friend class StructRef;
185 WASMTIME_OWN_WRAPPER(StructRefPre, wasmtime_struct_ref_pre)
186
187public:
189 static StructRefPre create(Store::Context cx, const StructType &ty) {
190 auto *raw = wasmtime_struct_ref_pre_new(cx.capi(), ty.capi());
191 StructRefPre pre(raw);
192 return pre;
193 }
194};
195
202class StructRef {
203 friend class EqRef;
204 friend class Val;
205 friend class AnyRef;
206
207 wasmtime_structref_t val;
208
209public:
211 explicit StructRef(wasmtime_structref_t val) : val(val) {}
212
214 StructRef(const StructRef &other) {
215 wasmtime_structref_clone(&other.val, &val);
216 }
217
219 StructRef &operator=(const StructRef &other) {
220 wasmtime_structref_unroot(&val);
221 wasmtime_structref_clone(&other.val, &val);
222 return *this;
223 }
224
226 StructRef(StructRef &&other) {
227 val = other.val;
228 wasmtime_structref_set_null(&other.val);
229 }
230
232 StructRef &operator=(StructRef &&other) {
233 wasmtime_structref_unroot(&val);
234 val = other.val;
235 wasmtime_structref_set_null(&other.val);
236 return *this;
237 }
238
240 ~StructRef() { wasmtime_structref_unroot(&val); }
241
243 static Result<StructRef> create(Store::Context cx, const StructRefPre &pre,
244 const std::vector<Val> &fields) {
245 std::vector<wasmtime_val_t> c_fields;
246 c_fields.reserve(fields.size());
247 for (auto &f : fields) {
248 c_fields.push_back(f.val);
249 }
250
251 wasmtime_structref_t out;
252 auto *err = wasmtime_structref_new(cx.capi(), pre.capi(), c_fields.data(),
253 c_fields.size(), &out);
254 if (err)
255 return Result<StructRef>(Error(err));
256 return Result<StructRef>(StructRef(out));
257 }
258
260 Result<Val> field(Store::Context cx, size_t index) const {
261 wasmtime_val_t out;
262 auto *err = wasmtime_structref_field(cx.capi(), &val, index, &out);
263 if (err)
264 return Result<Val>(Error(err));
265 return Result<Val>(Val(out));
266 }
267
269 Result<std::monostate> set_field(Store::Context cx, size_t index,
270 const Val &value) const {
271 auto *err =
272 wasmtime_structref_set_field(cx.capi(), &val, index, &value.val);
273 if (err)
274 return Result<std::monostate>(Error(err));
275 return Result<std::monostate>(std::monostate{});
276 }
277
279 AnyRef to_anyref() const {
280 wasmtime_anyref_t out;
281 wasmtime_structref_to_anyref(&val, &out);
282 return AnyRef(out);
283 }
284
286 EqRef to_eqref() const {
287 wasmtime_eqref_t out;
288 wasmtime_structref_to_eqref(&val, &out);
289 return EqRef(out);
290 }
291};
292
293inline StructRef EqRef::as_struct(Store::Context cx) const {
294 wasmtime_structref_t out;
295 wasmtime_eqref_as_struct(cx.capi(), &val, &out);
296 return StructRef(out);
297}
298
302class ArrayType {
303 struct Deleter {
304 void operator()(wasmtime_array_type_t *p) const {
305 wasmtime_array_type_delete(p);
306 }
307 };
308 std::unique_ptr<wasmtime_array_type_t, Deleter> ptr;
309
310public:
312 static ArrayType create(const Engine &engine, const FieldType &field) {
313 static_assert(sizeof(FieldType) == sizeof(wasmtime_field_type_t));
314 auto *raw = wasmtime_array_type_new(
315 engine.capi(), reinterpret_cast<const wasmtime_field_type_t *>(&field));
316 ArrayType ty;
317 ty.ptr.reset(raw);
318 return ty;
319 }
320
322 const wasmtime_array_type_t *capi() const { return ptr.get(); }
323
324private:
325 ArrayType() = default;
326 friend class ArrayRefPre;
327};
328
335class ArrayRefPre {
336 friend class ArrayRef;
337 WASMTIME_OWN_WRAPPER(ArrayRefPre, wasmtime_array_ref_pre)
338
339public:
341 static ArrayRefPre create(Store::Context cx, const ArrayType &ty) {
342 auto *raw = wasmtime_array_ref_pre_new(cx.capi(), ty.capi());
343 ArrayRefPre pre(raw);
344 return pre;
345 }
346};
347
354class ArrayRef {
355 friend class EqRef;
356 friend class Val;
357 friend class AnyRef;
358
359 wasmtime_arrayref_t val;
360
361public:
363 explicit ArrayRef(wasmtime_arrayref_t val) : val(val) {}
364
366 ArrayRef(const ArrayRef &other) { wasmtime_arrayref_clone(&other.val, &val); }
367
369 ArrayRef &operator=(const ArrayRef &other) {
370 wasmtime_arrayref_unroot(&val);
371 wasmtime_arrayref_clone(&other.val, &val);
372 return *this;
373 }
374
376 ArrayRef(ArrayRef &&other) {
377 val = other.val;
378 wasmtime_arrayref_set_null(&other.val);
379 }
380
382 ArrayRef &operator=(ArrayRef &&other) {
383 wasmtime_arrayref_unroot(&val);
384 val = other.val;
385 wasmtime_arrayref_set_null(&other.val);
386 return *this;
387 }
388
390 ~ArrayRef() { wasmtime_arrayref_unroot(&val); }
391
393 static Result<ArrayRef> create(Store::Context cx, const ArrayRefPre &pre,
394 const Val &elem, uint32_t len) {
395 wasmtime_arrayref_t out;
396 auto *err =
397 wasmtime_arrayref_new(cx.capi(), pre.capi(), &elem.val, len, &out);
398 if (err)
399 return Result<ArrayRef>(Error(err));
400 return Result<ArrayRef>(ArrayRef(out));
401 }
402
404 Result<uint32_t> len(Store::Context cx) const {
405 uint32_t out;
406 auto *err = wasmtime_arrayref_len(cx.capi(), &val, &out);
407 if (err)
408 return Result<uint32_t>(Error(err));
409 return Result<uint32_t>(out);
410 }
411
413 Result<Val> get(Store::Context cx, uint32_t index) const {
414 wasmtime_val_t out;
415 auto *err = wasmtime_arrayref_get(cx.capi(), &val, index, &out);
416 if (err)
417 return Result<Val>(Error(err));
418 return Result<Val>(Val(out));
419 }
420
422 Result<std::monostate> set(Store::Context cx, uint32_t index,
423 const Val &value) const {
424 auto *err = wasmtime_arrayref_set(cx.capi(), &val, index, &value.val);
425 if (err)
426 return Result<std::monostate>(Error(err));
427 return Result<std::monostate>(std::monostate{});
428 }
429
431 AnyRef to_anyref() const {
432 wasmtime_anyref_t out;
433 wasmtime_arrayref_to_anyref(&val, &out);
434 return AnyRef(out);
435 }
436
438 EqRef to_eqref() const {
439 wasmtime_eqref_t out;
440 wasmtime_arrayref_to_eqref(&val, &out);
441 return EqRef(out);
442 }
443};
444
445inline ArrayRef EqRef::as_array(Store::Context cx) const {
446 wasmtime_arrayref_t out;
447 wasmtime_eqref_as_array(cx.capi(), &val, &out);
448 return ArrayRef(out);
449}
450
451// AnyRef downcast method definitions (declared in val.hh)
452inline bool AnyRef::is_eqref(Store::Context cx) const {
453 return wasmtime_anyref_is_eqref(cx.capi(), &val);
454}
455inline bool AnyRef::is_struct(Store::Context cx) const {
456 return wasmtime_anyref_is_struct(cx.capi(), &val);
457}
458inline bool AnyRef::is_array(Store::Context cx) const {
459 return wasmtime_anyref_is_array(cx.capi(), &val);
460}
461inline std::optional<EqRef> AnyRef::as_eqref(Store::Context cx) const {
462 wasmtime_eqref_t out;
463 if (wasmtime_anyref_as_eqref(cx.capi(), &val, &out))
464 return EqRef(out);
465 return std::nullopt;
466}
467inline std::optional<StructRef> AnyRef::as_struct(Store::Context cx) const {
468 wasmtime_structref_t out;
469 if (wasmtime_anyref_as_struct(cx.capi(), &val, &out))
470 return StructRef(out);
471 return std::nullopt;
472}
473inline std::optional<ArrayRef> AnyRef::as_array(Store::Context cx) const {
474 wasmtime_arrayref_t out;
475 if (wasmtime_anyref_as_array(cx.capi(), &val, &out))
476 return ArrayRef(out);
477 return std::nullopt;
478}
479
480} // namespace wasmtime
481
482#endif // WASMTIME_FEATURE_GC
483
484#endif // WASMTIME_GC_HH
Container for different kinds of wasm values.
Definition: val.h:546
@ AnyRef
WebAssembly's anyref type.