feat: add a histrical wit-bindgen

This commit is contained in:
2023-01-01 00:25:48 +08:00
parent 01e8f5a959
commit aa50d63aec
419 changed files with 45283 additions and 1 deletions

View File

@@ -0,0 +1,31 @@
test-imports: func()
record list-in-record1 { a: string }
record list-in-record2 { a: string }
record list-in-record3 { a: string }
record list-in-record4 { a: string }
type list-in-alias = list-in-record4
list-in-record1: func(a: list-in-record1)
list-in-record2: func() -> list-in-record2
list-in-record3: func(a: list-in-record3) -> list-in-record3
list-in-record4: func(a: list-in-alias) -> list-in-alias
type list-in-variant1-v1 = option<string>
type list-in-variant1-v2 = expected<unit, string>
union list-in-variant1-v3 { string, float32 }
list-in-variant1: func(a: list-in-variant1-v1, b: list-in-variant1-v2, c: list-in-variant1-v3)
type list-in-variant2 = option<string>
list-in-variant2: func() -> list-in-variant2
type list-in-variant3 = option<string>
list-in-variant3: func(a: list-in-variant3) -> list-in-variant3
enum my-errno { success, a, b }
errno-result: func() -> expected<unit, my-errno>
type list-typedef = string
type list-typedef2 = list<u8>
type list-typedef3 = list<string>
list-typedefs: func(a: list-typedef, c: list-typedef3) -> tuple<list-typedef2, list-typedef3>

View File

@@ -0,0 +1,86 @@
from exports.bindings import Exports
from imports.bindings import add_imports_to_linker, Imports
from typing import Tuple, List
import exports.bindings as e
import imports.bindings as i
import sys
import wasmtime
class MyImports:
def list_in_record1(self, a: i.ListInRecord1) -> None:
pass
def list_in_record2(self) -> i.ListInRecord2:
return i.ListInRecord2('list_in_record2')
def list_in_record3(self, a: i.ListInRecord3) -> i.ListInRecord3:
assert(a.a == 'list_in_record3 input')
return i.ListInRecord3('list_in_record3 output')
def list_in_record4(self, a: i.ListInAlias) -> i.ListInAlias:
assert(a.a == 'input4')
return i.ListInRecord4('result4')
def list_in_variant1(self, a: i.ListInVariant1V1, b: i.ListInVariant1V2, c: i.ListInVariant1V3) -> None:
assert(a == 'foo')
assert(b == i.Err('bar'))
assert(c == 'baz')
def list_in_variant2(self) -> i.ListInVariant2:
return 'list_in_variant2'
def list_in_variant3(self, a: i.ListInVariant3) -> i.ListInVariant3:
assert(a == 'input3')
return 'output3'
def errno_result(self) -> i.Expected[None, i.MyErrno]:
return i.Err(i.MyErrno.B)
def list_typedefs(self, a: i.ListTypedef, c: i.ListTypedef3) -> Tuple[i.ListTypedef2, i.ListTypedef3]:
assert(a == 'typedef1')
assert(c == ['typedef2'])
return (b'typedef3', ['typedef4'])
def list_of_variants(self, a: List[bool], b: List[i.Expected[None, None]], c: List[i.MyErrno]) -> Tuple[List[bool], List[i.Expected[None, None]], List[i.MyErrno]]:
assert(a == [True, False])
assert(b == [i.Ok(None), i.Err(None)])
assert(c == [i.MyErrno.SUCCESS, i.MyErrno.A])
return (
[False, True],
[i.Err(None), i.Ok(None)],
[i.MyErrno.A, i.MyErrno.B],
)
def run(wasm_file: str) -> None:
store = wasmtime.Store()
module = wasmtime.Module.from_file(store.engine, wasm_file)
linker = wasmtime.Linker(store.engine)
linker.define_wasi()
wasi = wasmtime.WasiConfig()
wasi.inherit_stdout()
wasi.inherit_stderr()
store.set_wasi(wasi)
imports = MyImports()
add_imports_to_linker(linker, store, imports)
wasm = Exports(store, linker, module)
wasm.test_imports(store)
wasm.list_in_record1(store, e.ListInRecord1("list_in_record1"))
assert(wasm.list_in_record2(store) == e.ListInRecord2(a="list_in_record2"))
assert(wasm.list_in_record3(store, e.ListInRecord3("list_in_record3 input")).a == "list_in_record3 output")
assert(wasm.list_in_record4(store, e.ListInRecord4("input4")).a == "result4")
wasm.list_in_variant1(store, "foo", e.Err("bar"), 'baz')
assert(wasm.list_in_variant2(store) == "list_in_variant2")
assert(wasm.list_in_variant3(store, "input3") == "output3")
assert(isinstance(wasm.errno_result(store), e.Err))
r1, r2 = wasm.list_typedefs(store, "typedef1", ["typedef2"])
assert(r1 == b'typedef3')
assert(r2 == ['typedef4'])
if __name__ == '__main__':
run(sys.argv[1])

View File

@@ -0,0 +1,160 @@
use anyhow::Result;
wit_bindgen_wasmtime::export!("../../tests/runtime/flavorful/imports.wit");
use imports::*;
#[derive(Default)]
pub struct MyImports;
impl Imports for MyImports {
fn list_in_record1(&mut self, ty: ListInRecord1<'_>) {
assert_eq!(ty.a, "list_in_record1");
}
fn list_in_record2(&mut self) -> ListInRecord2 {
ListInRecord2 {
a: "list_in_record2".to_string(),
}
}
fn list_in_record3(&mut self, a: ListInRecord3Param<'_>) -> ListInRecord3Result {
assert_eq!(a.a, "list_in_record3 input");
ListInRecord3Result {
a: "list_in_record3 output".to_string(),
}
}
fn list_in_record4(&mut self, a: ListInAliasParam<'_>) -> ListInAliasResult {
assert_eq!(a.a, "input4");
ListInRecord4Result {
a: "result4".to_string(),
}
}
fn list_in_variant1(
&mut self,
a: ListInVariant1V1<'_>,
b: ListInVariant1V2<'_>,
c: ListInVariant1V3<'_>,
) {
assert_eq!(a.unwrap(), "foo");
assert_eq!(b.unwrap_err(), "bar");
match c {
ListInVariant1V3::String(s) => assert_eq!(s, "baz"),
ListInVariant1V3::F32(_) => panic!(),
}
}
fn list_in_variant2(&mut self) -> Option<String> {
Some("list_in_variant2".to_string())
}
fn list_in_variant3(&mut self, a: ListInVariant3Param<'_>) -> Option<String> {
assert_eq!(a.unwrap(), "input3");
Some("output3".to_string())
}
fn errno_result(&mut self) -> Result<(), MyErrno> {
MyErrno::A.to_string();
format!("{:?}", MyErrno::A);
fn assert_error<T: std::error::Error>() {}
assert_error::<MyErrno>();
Err(MyErrno::B)
}
fn list_typedefs(
&mut self,
a: ListTypedef<'_>,
b: ListTypedef3Param<'_>,
) -> (ListTypedef2, ListTypedef3Result) {
assert_eq!(a, "typedef1");
assert_eq!(b.len(), 1);
assert_eq!(b[0], "typedef2");
(b"typedef3".to_vec(), vec!["typedef4".to_string()])
}
fn list_of_variants(
&mut self,
bools: Vec<bool>,
results: Vec<Result<(), ()>>,
enums: Vec<MyErrno>,
) -> (Vec<bool>, Vec<Result<(), ()>>, Vec<MyErrno>) {
assert_eq!(bools, [true, false]);
assert_eq!(results, [Ok(()), Err(())]);
assert_eq!(enums, [MyErrno::Success, MyErrno::A]);
(
vec![false, true],
vec![Err(()), Ok(())],
vec![MyErrno::A, MyErrno::B],
)
}
}
wit_bindgen_wasmtime::import!("../../tests/runtime/flavorful/exports.wit");
fn run(wasm: &str) -> Result<()> {
use exports::*;
let (exports, mut store) = crate::instantiate(
wasm,
|linker| imports::add_to_linker(linker, |cx| -> &mut MyImports { &mut cx.imports }),
|store, module, linker| Exports::instantiate(store, module, linker, |cx| &mut cx.exports),
)?;
exports.test_imports(&mut store)?;
exports.list_in_record1(
&mut store,
ListInRecord1 {
a: "list_in_record1",
},
)?;
assert_eq!(exports.list_in_record2(&mut store)?.a, "list_in_record2");
assert_eq!(
exports
.list_in_record3(
&mut store,
ListInRecord3Param {
a: "list_in_record3 input"
}
)?
.a,
"list_in_record3 output"
);
assert_eq!(
exports
.list_in_record4(&mut store, ListInAliasParam { a: "input4" })?
.a,
"result4"
);
exports.list_in_variant1(
&mut store,
Some("foo"),
Err("bar"),
ListInVariant1V3::String("baz"),
)?;
assert_eq!(
exports.list_in_variant2(&mut store)?,
Some("list_in_variant2".to_string())
);
assert_eq!(
exports.list_in_variant3(&mut store, Some("input3"))?,
Some("output3".to_string())
);
assert!(exports.errno_result(&mut store)?.is_err());
MyErrno::A.to_string();
format!("{:?}", MyErrno::A);
fn assert_error<T: std::error::Error>() {}
assert_error::<MyErrno>();
let (a, b) = exports.list_typedefs(&mut store, "typedef1", &["typedef2"])?;
assert_eq!(a, b"typedef3");
assert_eq!(b.len(), 1);
assert_eq!(b[0], "typedef4");
Ok(())
}

View File

@@ -0,0 +1,85 @@
import { addImportsToImports, Imports, MyErrno } from "./imports.js";
import { Exports } from "./exports.js";
import * as exports from "./exports.js";
import { getWasm, addWasiToImports } from "./helpers.js";
// @ts-ignore
import * as assert from 'assert';
async function run() {
const importObj = {};
const imports: Imports = {
listInRecord1(x) {},
listInRecord2() { return { a: 'list_in_record2' }; },
listInRecord3(x) {
assert.strictEqual(x.a, 'list_in_record3 input');
return { a: 'list_in_record3 output' };
},
listInRecord4(x) {
assert.strictEqual(x.a, 'input4');
return { a: 'result4' };
},
listInVariant1(a, b, c) {
assert.strictEqual(a, 'foo');
assert.deepStrictEqual(b, { tag: 'err', val: 'bar' });
assert.deepStrictEqual(c, { tag: 0, val: 'baz' });
},
listInVariant2() { return 'list_in_variant2'; },
listInVariant3(x) {
assert.strictEqual(x, 'input3');
return 'output3';
},
errnoResult() { return { tag: 'err', val: "b" }; },
listTypedefs(x, y) {
assert.strictEqual(x, 'typedef1');
assert.deepStrictEqual(y, ['typedef2']);
return [(new TextEncoder).encode('typedef3'), ['typedef4']];
},
listOfVariants(bools, results, enums) {
assert.deepStrictEqual(bools, [true, false]);
assert.deepStrictEqual(results, [{ tag: 'ok', val: undefined }, { tag: 'err', val: undefined }]);
assert.deepStrictEqual(enums, ["success", "a"]);
return [
[false, true],
[{ tag: 'err', val: undefined }, { tag: 'ok', val: undefined }],
["a", "b"],
];
},
};
let instance: WebAssembly.Instance;
addImportsToImports(importObj, imports, name => instance.exports[name]);
const wasi = addWasiToImports(importObj);
const wasm = new Exports();
await wasm.instantiate(getWasm(), importObj);
wasi.start(wasm.instance);
instance = wasm.instance;
wasm.testImports();
wasm.listInRecord1({ a: "list_in_record1" });
assert.deepStrictEqual(wasm.listInRecord2(), { a: "list_in_record2" });
assert.deepStrictEqual(
wasm.listInRecord3({ a: "list_in_record3 input" }),
{ a: "list_in_record3 output" },
);
assert.deepStrictEqual(
wasm.listInRecord4({ a: "input4" }),
{ a: "result4" },
);
wasm.listInVariant1("foo", { tag: 'err', val: 'bar' }, { tag: 0, val: 'baz' });
assert.deepStrictEqual(wasm.listInVariant2(), "list_in_variant2");
assert.deepStrictEqual(wasm.listInVariant3("input3"), "output3");
assert.deepStrictEqual(wasm.errnoResult().tag, 'err');
const [r1, r2] = wasm.listTypedefs("typedef1", ["typedef2"]);
assert.deepStrictEqual(r1, (new TextEncoder()).encode('typedef3'));
assert.deepStrictEqual(r2, ['typedef4']);
}
await run()

View File

@@ -0,0 +1,31 @@
record list-in-record1 { a: string }
record list-in-record2 { a: string }
record list-in-record3 { a: string }
record list-in-record4 { a: string }
type list-in-alias = list-in-record4
list-in-record1: func(a: list-in-record1)
list-in-record2: func() -> list-in-record2
list-in-record3: func(a: list-in-record3) -> list-in-record3
list-in-record4: func(a: list-in-alias) -> list-in-alias
type list-in-variant1-v1 = option<string>
type list-in-variant1-v2 = expected<unit, string>
union list-in-variant1-v3 { string, float32 }
list-in-variant1: func(a: list-in-variant1-v1, b: list-in-variant1-v2, c: list-in-variant1-v3)
type list-in-variant2 = option<string>
list-in-variant2: func() -> list-in-variant2
type list-in-variant3 = option<string>
list-in-variant3: func(a: list-in-variant3) -> list-in-variant3
enum my-errno { success, a, b }
errno-result: func() -> expected<unit, my-errno>
type list-typedef = string
type list-typedef2 = list<u8>
type list-typedef3 = list<string>
list-typedefs: func(a: list-typedef, c: list-typedef3) -> tuple<list-typedef2, list-typedef3>
list-of-variants: func(a: list<bool>, b: list<expected<unit, unit>>, c: list<my-errno>) -> tuple<list<bool>, list<expected<unit, unit>>, list<my-errno>>

View File

@@ -0,0 +1,197 @@
#include <assert.h>
#include <imports.h>
#include <exports.h>
#include <stdlib.h>
#include <string.h>
void exports_test_imports() {
{
imports_list_in_record1_t a;
imports_string_set(&a.a, "list_in_record1");
imports_list_in_record1(&a);
imports_list_in_record2_t b;
imports_list_in_record2(&b);
assert(memcmp(b.a.ptr, "list_in_record2", b.a.len) == 0);
imports_list_in_record2_free(&b);
}
{
imports_list_in_record3_t a, b;
imports_string_set(&a.a, "list_in_record3 input");
imports_list_in_record3(&a, &b);
assert(memcmp(b.a.ptr, "list_in_record3 output", b.a.len) == 0);
imports_list_in_record3_free(&b);
}
{
imports_list_in_record4_t a, b;
imports_string_set(&a.a, "input4");
imports_list_in_record4(&a, &b);
assert(memcmp(b.a.ptr, "result4", b.a.len) == 0);
imports_list_in_record4_free(&b);
}
{
imports_list_in_variant1_v1_t a;
imports_list_in_variant1_v2_t b;
imports_list_in_variant1_v3_t c;
a.is_some = true;
imports_string_set(&a.val, "foo");
b.is_err = true;
imports_string_set(&b.val.err, "bar");
c.tag = 0;
imports_string_set(&c.val.f0, "baz");
imports_list_in_variant1(&a, &b, &c);
}
{
imports_string_t a;
assert(imports_list_in_variant2(&a));
assert(memcmp(a.ptr, "list_in_variant2", a.len) == 0);
imports_string_free(&a);
}
{
imports_list_in_variant3_t a;
a.is_some = true;
imports_string_set(&a.val, "input3");
imports_string_t b;
assert(imports_list_in_variant3(&a, &b));
assert(memcmp(b.ptr, "output3", b.len) == 0);
imports_string_free(&b);
}
assert(imports_errno_result() == IMPORTS_MY_ERRNO_B);
{
imports_string_t a;
imports_string_set(&a, "typedef1");
imports_string_t b_str;
imports_string_set(&b_str, "typedef2");
imports_list_typedef3_t b;
b.ptr = &b_str;
b.len = 1;
imports_list_typedef2_t c;
imports_list_typedef3_t d;
imports_list_typedefs(&a, &b, &c, &d);
assert(memcmp(c.ptr, "typedef3", c.len) == 0);
assert(d.len == 1);
assert(memcmp(d.ptr[0].ptr, "typedef4", d.ptr[0].len) == 0);
imports_list_typedef2_free(&c);
imports_list_typedef3_free(&d);
}
{
imports_list_bool_t a;
bool a_val[] = {true, false};
a.ptr = a_val;
a.len = 2;
imports_list_expected_unit_unit_t b;
imports_expected_unit_unit_t b_val[2];
b_val[0].is_err = false;
b_val[1].is_err = true;
b.ptr = b_val;
b.len = 2;
imports_list_my_errno_t c;
imports_my_errno_t c_val[2];
c_val[0] = IMPORTS_MY_ERRNO_SUCCESS;
c_val[1] = IMPORTS_MY_ERRNO_A;
c.ptr = c_val;
c.len = 2;
imports_list_bool_t d;
imports_list_expected_unit_unit_t e;
imports_list_my_errno_t f;
imports_list_of_variants(&a, &b, &c, &d, &e, &f);
assert(d.len == 2);
assert(d.ptr[0] == false);
assert(d.ptr[1] == true);
assert(e.len == 2);
assert(e.ptr[0].is_err == true);
assert(e.ptr[1].is_err == false);
assert(f.len == 2);
assert(f.ptr[0] == IMPORTS_MY_ERRNO_A);
assert(f.ptr[1] == IMPORTS_MY_ERRNO_B);
imports_list_bool_free(&d);
imports_list_expected_unit_unit_free(&e);
imports_list_my_errno_free(&f);
}
}
void exports_list_in_record1(exports_list_in_record1_t *a) {
assert(memcmp(a->a.ptr, "list_in_record1", a->a.len) == 0);
exports_list_in_record1_free(a);
}
void exports_list_in_record2(exports_list_in_record2_t *ret0) {
exports_string_dup(&ret0->a, "list_in_record2");
}
void exports_list_in_record3(exports_list_in_record3_t *a, exports_list_in_record3_t *ret0) {
assert(memcmp(a->a.ptr, "list_in_record3 input", a->a.len) == 0);
exports_list_in_record3_free(a);
exports_string_dup(&ret0->a, "list_in_record3 output");
}
void exports_list_in_record4(exports_list_in_alias_t *a, exports_list_in_alias_t *ret0) {
assert(memcmp(a->a.ptr, "input4", a->a.len) == 0);
exports_list_in_alias_free(a);
exports_string_dup(&ret0->a, "result4");
}
void exports_list_in_variant1(exports_list_in_variant1_v1_t *a, exports_list_in_variant1_v2_t *b, exports_list_in_variant1_v3_t *c) {
assert(a->is_some);
assert(memcmp(a->val.ptr, "foo", a->val.len) == 0);
exports_list_in_variant1_v1_free(a);
assert(b->is_err);
assert(memcmp(b->val.err.ptr, "bar", b->val.err.len) == 0);
exports_list_in_variant1_v2_free(b);
assert(c->tag == 0);
assert(memcmp(c->val.f0.ptr, "baz", c->val.f0.len) == 0);
exports_list_in_variant1_v3_free(c);
}
bool exports_list_in_variant2(exports_string_t *ret0) {
exports_string_dup(ret0, "list_in_variant2");
return true;
}
bool exports_list_in_variant3(exports_list_in_variant3_t *a, exports_string_t *ret0) {
assert(a->is_some);
assert(memcmp(a->val.ptr, "input3", a->val.len) == 0);
exports_list_in_variant3_free(a);
exports_string_dup(ret0, "output3");
return true;
}
exports_my_errno_t exports_errno_result(void) {
return EXPORTS_MY_ERRNO_B;
}
void exports_list_typedefs(exports_list_typedef_t *a, exports_list_typedef3_t *c, exports_list_typedef2_t *ret0, exports_list_typedef3_t *ret1) {
assert(memcmp(a->ptr, "typedef1", a->len) == 0);
exports_list_typedef_free(a);
assert(c->len == 1);
assert(memcmp(c->ptr[0].ptr, "typedef2", c->ptr[0].len) == 0);
exports_list_typedef3_free(c);
ret0->ptr = malloc(8);
ret0->len = 8;
memcpy(ret0->ptr, "typedef3", 8);
ret1->ptr = malloc(sizeof(exports_string_t));
ret1->len = 1;
exports_string_dup(&ret1->ptr[0], "typedef4");
}

View File

@@ -0,0 +1,116 @@
wit_bindgen_rust::import!("../../tests/runtime/flavorful/imports.wit");
wit_bindgen_rust::export!("../../tests/runtime/flavorful/exports.wit");
use exports::*;
struct Exports;
impl exports::Exports for Exports {
fn test_imports() {
use imports::*;
let _guard = test_rust_wasm::guard();
list_in_record1(ListInRecord1 {
a: "list_in_record1",
});
assert_eq!(list_in_record2().a, "list_in_record2");
assert_eq!(
list_in_record3(ListInRecord3Param {
a: "list_in_record3 input"
})
.a,
"list_in_record3 output"
);
assert_eq!(
list_in_record4(ListInAliasParam { a: "input4" }).a,
"result4"
);
list_in_variant1(Some("foo"), Err("bar"), ListInVariant1V3::String("baz"));
assert_eq!(list_in_variant2(), Some("list_in_variant2".to_string()));
assert_eq!(
list_in_variant3(Some("input3")),
Some("output3".to_string())
);
assert!(errno_result().is_err());
MyErrno::A.to_string();
format!("{:?}", MyErrno::A);
fn assert_error<T: std::error::Error>() {}
assert_error::<MyErrno>();
let (a, b) = list_typedefs("typedef1", &["typedef2"]);
assert_eq!(a, b"typedef3");
assert_eq!(b.len(), 1);
assert_eq!(b[0], "typedef4");
let (a, b, c) = list_of_variants(
&[true, false],
&[Ok(()), Err(())],
&[MyErrno::Success, MyErrno::A],
);
assert_eq!(a, [false, true]);
assert_eq!(b, [Err(()), Ok(())]);
assert_eq!(c, [MyErrno::A, MyErrno::B]);
}
fn list_in_record1(ty: ListInRecord1) {
assert_eq!(ty.a, "list_in_record1");
}
fn list_in_record2() -> ListInRecord2 {
ListInRecord2 {
a: "list_in_record2".to_string(),
}
}
fn list_in_record3(a: ListInRecord3) -> ListInRecord3 {
assert_eq!(a.a, "list_in_record3 input");
ListInRecord3 {
a: "list_in_record3 output".to_string(),
}
}
fn list_in_record4(a: ListInAlias) -> ListInAlias {
assert_eq!(a.a, "input4");
ListInRecord4 {
a: "result4".to_string(),
}
}
fn list_in_variant1(a: ListInVariant1V1, b: ListInVariant1V2, c: ListInVariant1V3) {
assert_eq!(a.unwrap(), "foo");
assert_eq!(b.unwrap_err(), "bar");
match c {
ListInVariant1V3::String(s) => assert_eq!(s, "baz"),
ListInVariant1V3::F32(_) => panic!(),
}
}
fn list_in_variant2() -> Option<String> {
Some("list_in_variant2".to_string())
}
fn list_in_variant3(a: ListInVariant3) -> Option<String> {
assert_eq!(a.unwrap(), "input3");
Some("output3".to_string())
}
fn errno_result() -> Result<(), MyErrno> {
MyErrno::A.to_string();
format!("{:?}", MyErrno::A);
fn assert_error<T: std::error::Error>() {}
assert_error::<MyErrno>();
Err(MyErrno::B)
}
fn list_typedefs(a: ListTypedef, b: ListTypedef3) -> (ListTypedef2, ListTypedef3) {
assert_eq!(a, "typedef1");
assert_eq!(b.len(), 1);
assert_eq!(b[0], "typedef2");
(b"typedef3".to_vec(), vec!["typedef4".to_string()])
}
}