wapc

package module
v0.2.2-0...-07d5963 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2021 License: Apache-2.0 Imports: 8 Imported by: 0

README

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/qluvio/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.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NoOpHostCallHandler

func NoOpHostCallHandler(ctx context.Context, binding, namespace, operation string, payload []byte) ([]byte, error)

NoOpHostCallHandler is an noop host call handler to use if your host does not need to support host calls.

func Print

func Print(message string)

func Println

func Println(message string)

Types

type HostCallHandler

type HostCallHandler func(ctx context.Context, binding, namespace, operation string, payload []byte) ([]byte, error)

HostCallHandler is a function to invoke to handle when a guest is performing a host call.

type Instance

type Instance struct {
	// contains filtered or unexported fields
}

Instance is a single instantiation of a module with its own memory.

func (*Instance) Close

func (i *Instance) Close()

Close closes the single instance. This should be called before calling `Close` on the Module itself.

func (*Instance) Invoke

func (i *Instance) Invoke(ctx context.Context, operation string, payload []byte) ([]byte, error)

Invoke calls `operation` with `payload` on the module and returns a byte slice payload.

func (*Instance) MemorySize

func (i *Instance) MemorySize() uint32

MemorySize returns the memory length of the underlying instance.

type Logger

type Logger func(msg string)

Logger is the function to call from consoleLog inside a waPC module.

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module represents a compile waPC module.

func New

func New(code []byte, hostCallHandler HostCallHandler) (*Module, error)

New compiles a `Module` from `code`.

func (*Module) Close

func (m *Module) Close()

Close closes the module. This should be called after calling `Close` on any instances that were created.

func (*Module) Instantiate

func (m *Module) Instantiate() (*Instance, error)

Instantiate creates a single instance of the module with its own memory.

func (*Module) SetLogger

func (m *Module) SetLogger(logger Logger)

SetLogger sets the waPC logger for __console_log calls.

func (*Module) SetWriter

func (m *Module) SetWriter(writer Logger)

SetWriter sets the writer for WASI fd_write calls to standard out.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool is a wrapper around a ringbuffer of WASM modules

func NewPool

func NewPool(module *Module, size uint64) (*Pool, error)

NewPool takes in compiled WASM module and a size and returns a pool containing `size` instances of that module.

func (*Pool) Close

func (p *Pool) Close()

Close closes down all the instances contained by the pool.

func (*Pool) Get

func (p *Pool) Get(timeout time.Duration) (*Instance, error)

Get returns a module from the pool if it can be retrieved within the passed timeout window, if not it returns an error

func (*Pool) Return

func (p *Pool) Return(inst *Instance) error

Return takes a module and adds it to the pool This should only be called using a module

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL