Skip to content
forked from wapc/wapc-go

Golang-based WebAssembly Host Runtime for waPC-compliant modules

License

Notifications You must be signed in to change notification settings

teamlint/wapc-go

 
 

Repository files navigation

waPC Host for Go

This is the Golang implementation of the waPC standard for WebAssembly host runtimes. It allows any WebAssembly module to be loaded as a guest and receive requests for invocation as well as to make its own function requests of the host.

Example

The following is a simple example of synchronous, bi-directional procedure calls between a WebAssembly host runtime and the guest module.

package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/wapc/wapc-go"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("usage: hello <name>")
		return
	}
	name := os.Args[1]
	ctx := context.Background()
	code, err := ioutil.ReadFile("testdata/hello.wasm")
	if err != nil {
		panic(err)
	}

	module, err := wapc.New(code, hostCall)
	if err != nil {
		panic(err)
	}
	module.SetLogger(wapc.Println) // Send __console_log calls to stardard out
	module.SetWriter(wapc.Print) // Send WASI fd_write calls to stardard out
	defer module.Close()

	instance, err := module.Instantiate()
	if err != nil {
		panic(err)
	}
	defer instance.Close()

	result, err := instance.Invoke(ctx, "hello", []byte(name))
	if err != nil {
		panic(err)
	}

	fmt.Println(string(result))
}

func consoleLog(msg string) {
	fmt.Println(msg)
}

func hostCall(ctx context.Context, binding, namespace, operation string, payload []byte) ([]byte, error) {
	// Route the payload to any custom functionality accordingly.
	// You can even route to other waPC modules!!!
	switch namespace {
	case "foo":
		switch operation {
		case "echo":
			return payload, nil // echo
		}
	}
	return []byte("default"), nil
}

To see this in action, enter the following in your shell:

$ go run example/main.go waPC!
logging something
Hello, waPC!

Alternatively you can use a Pool to manage a pool of instances.

	pool, err := wapc.NewPool(module, 10)
	if err != nil {
		panic(err)
	}
	defer pool.Close()

	for i := 0; i < 100; i++ {
		instance, err := pool.Get(10 * time.Millisecond)
		if err != nil {
			panic(err)
		}

		result, err := instance.Invoke(ctx, "hello", []byte("waPC"))
		if err != nil {
			panic(err)
		}

		fmt.Println(string(result))

		err = pool.Return(instance)
		if err != nil {
			panic(err)
		}
	}

There are currently some differences in this library compared to the Rust implementation:

  • Uses Wasmer and its Go wrapper for hosting WebAssembly. We are looking into the new Wasmtime Go wrapper.
  • No support WASI... yet.
  • Separate compilation (New) and instantiation (Instantiate) steps. This is to incur the cost of compilation once in a multi-instance scenario.
  • Pool for creating a pool of instances for a given Module.

About

Golang-based WebAssembly Host Runtime for waPC-compliant modules

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 100.0%