wypes

package module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Mar 8, 2024 License: MIT Imports: 6 Imported by: 18

README

wypes

Go library to define type-safe host functions in wazero and other WebAssembly runtimes.

Features:

  • 🛡 Type safe
  • 🐎 Fast
  • 🔨 Works with any WebAssmebly runtime, like wazero or wasman
  • 🧠 Handles for you memory operations
  • 👉 Manages external references
  • 🧼 Simple and clean API
  • 🐜 Can be compiled with TinyGo
  • 😎 No reflect, no unsafe, only generics and dedication.

📦 Installation

go get github.com/orsinium-labs/wypes

🔧 Usage

Define a function using provided types:

func addI32(a wypes.Int32, b wypes.Int32) wypes.Int32 {
    return a + b
}

Define a mapping of module and function names to function definitions:

modules := wypes.Modules{
    "env": {
        "add_i32": wypes.H2(addI32),
    },
}

Link the modules to the runtime. We provide a convenience method to do this for wazero:

err := modules.DefineWazero(r, nil)

That's it! Now the wasm module can call the env.add_i32 function.

🛹 Tricks

The library provides lots of useful types that you can use in your functions. Make sure to check the docs. A few highlights:

  1. Context provides access to the context.Context passed into the guest function call in wazero.
  2. Store provides access to all the state: memory, stack, references.
  3. Duration and Time to pass time.Duration and time.Time (as UNIX timestamp).
  4. HostRef can hold a reference to the Refs store of host objects.
  5. Void is used as the return type for functions that return no value.

See documentation for more.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrRefNotFound = errors.New("HostRef with the given ID is not found in Refs")
	ErrMemRead     = errors.New("Memory.Read is out of bounds")
	ErrMemWrite    = errors.New("Memory.Write is out of bounds")
	ErrRefCast     = errors.New("Reference returned by Refs.Get is not of the type expected by HostRef")
)

Functions

This section is empty.

Types

type Addr

type Addr = uint32

type Bool

type Bool bool

Bool wraps [bool].

func (Bool) Lift

func (Bool) Lift(s Store) Bool

Lift implements Lift interface.

func (Bool) Lower

func (v Bool) Lower(s Store)

Lower implements Lower interface.

func (Bool) Unwrap

func (v Bool) Unwrap() bool

Unwrap returns the wrapped value.

func (Bool) ValueTypes

func (Bool) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Byte

type Byte = UInt8

Byte is an alias for UInt8.

type Bytes

type Bytes struct {
	Offset uint32
	Raw    []byte
}

Bytes wraps a slice of bytes.

The bytes are passed through the linear memory. Since the memory is controlled and allocated by the guest module, you have to provide the Offset to be able to Lower the value into the memory. The offset should be obtained from the guest module, either as an explicit function argument or by calling its allocator.

func (Bytes) Lift

func (Bytes) Lift(s Store) Bytes

Lift implements Lift interface.

func (Bytes) Lower

func (v Bytes) Lower(s Store)

Lower implements Lower interface.

func (Bytes) Unwrap

func (v Bytes) Unwrap() []byte

Unwrap returns the wrapped value.

func (Bytes) ValueTypes

func (v Bytes) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Complex128

type Complex128 complex128

Complex128 wraps [complex128].

func (Complex128) Lift

func (Complex128) Lift(s Store) Complex128

Lift implements Lift interface.

func (Complex128) Lower

func (v Complex128) Lower(s Store)

Lower implements Lower interface.

func (Complex128) Unwrap

func (v Complex128) Unwrap() complex128

Unwrap returns the wrapped value.

func (Complex128) ValueTypes

func (Complex128) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Complex64

type Complex64 complex64

Complex64 wraps [complex64].

func (Complex64) Lift

func (Complex64) Lift(s Store) Complex64

Lift implements Lift interface.

func (Complex64) Lower

func (v Complex64) Lower(s Store)

Lower implements Lower interface.

func (Complex64) Unwrap

func (v Complex64) Unwrap() complex64

Unwrap returns the wrapped value.

func (Complex64) ValueTypes

func (Complex64) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Context

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

Context wraps context.Context.

func (Context) Lift

func (Context) Lift(s Store) Context

Lift implements Lift interface.

func (Context) Unwrap

func (v Context) Unwrap() context.Context

Unwrap returns the wrapped value.

func (Context) ValueTypes

func (Context) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Duration

type Duration time.Duration

Duration wraps time.Duration.

func (Duration) Lift

func (Duration) Lift(s Store) Duration

Lift implements Lift interface.

func (Duration) Lower

func (v Duration) Lower(s Store)

Lower implements Lower interface.

func (Duration) Unwrap

func (v Duration) Unwrap() time.Duration

Unwrap returns the wrapped value.

func (Duration) ValueTypes

func (Duration) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Float32

type Float32 float32

Float32 wraps [float32].

func (Float32) Lift

func (Float32) Lift(s Store) Float32

Lift implements Lift interface.

func (Float32) Lower

func (v Float32) Lower(s Store)

Lower implements Lower interface.

func (Float32) Unwrap

func (v Float32) Unwrap() float32

Unwrap returns the wrapped value.

func (Float32) ValueTypes

func (Float32) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Float64

type Float64 float64

Float64 wraps [float64].

func (Float64) Lift

func (Float64) Lift(s Store) Float64

Lift implements Lift interface.

func (Float64) Lower

func (v Float64) Lower(s Store)

Lower implements Lower interface.

func (Float64) Unwrap

func (v Float64) Unwrap() float64

Unwrap returns the wrapped value.

func (Float64) ValueTypes

func (Float64) ValueTypes() []ValueType

ValueTypes implements Value interface.

type HostFunc

type HostFunc struct {
	Params  []Value
	Results []Value
	Call    func(Store)
}

HostFunc is a wrapped host-defined function.

It is constructed with functions from H0 to H8 where the number is how many arguments it accepts. If you need more, use Pair.

There is always exactly one result. If you need to return nothing, use Void. If you want to return 2 or more values, use Pair, but make sure that the guest and the runtime support multi-value returns.

func H0

func H0[Z Lower](
	fn func() Z,
) HostFunc

H0 defines a HostFunc that accepts no arguments.

func H1

func H1[A Lift[A], Z Lower](
	fn func(A) Z,
) HostFunc

H1 defines a HostFunc that accepts 1 high-level argument.

func H2

func H2[A Lift[A], B Lift[B], Z Lower](
	fn func(A, B) Z,
) HostFunc

H2 defines a HostFunc that accepts 2 high-level arguments.

func H3

func H3[A Lift[A], B Lift[B], C Lift[C], Z Lower](
	fn func(A, B, C) Z,
) HostFunc

H3 defines a HostFunc that accepts 3 high-level arguments.

func H4

func H4[A Lift[A], B Lift[B], C Lift[C], D Lift[D], Z Lower](
	fn func(A, B, C, D) Z,
) HostFunc

H4 defines a HostFunc that accepts 4 high-level arguments.

func H5

func H5[A Lift[A], B Lift[B], C Lift[C], D Lift[D], E Lift[E], Z Lower](
	fn func(A, B, C, D, E) Z,
) HostFunc

H5 defines a HostFunc that accepts 5 high-level arguments.

func H6

func H6[A Lift[A], B Lift[B], C Lift[C], D Lift[D], E Lift[E], F Lift[F], Z Lower](
	fn func(A, B, C, D, E, F) Z,
) HostFunc

H6 defines a HostFunc that accepts 6 high-level arguments.

func H7

func H7[A Lift[A], B Lift[B], C Lift[C], D Lift[D], E Lift[E], F Lift[F], G Lift[G], Z Lower](
	fn func(A, B, C, D, E, F, G) Z,
) HostFunc

H7 defines a HostFunc that accepts 7 high-level arguments.

func H8

func H8[A Lift[A], B Lift[B], C Lift[C], D Lift[D], E Lift[E], F Lift[F], G Lift[G], H Lift[H], Z Lower](
	fn func(A, B, C, D, E, F, G, H) Z,
) HostFunc

H8 defines a HostFunc that accepts 8 high-level arguments.

If you need more than 8 arguments, think again. If you still do, use Pair.

func (*HostFunc) NumParams

func (f *HostFunc) NumParams() int

func (*HostFunc) NumResults

func (f *HostFunc) NumResults() int

func (*HostFunc) ParamValueTypes

func (f *HostFunc) ParamValueTypes() []ValueType

func (*HostFunc) ResultValueTypes

func (f *HostFunc) ResultValueTypes() []ValueType

type HostRef

type HostRef[T any] struct {
	Raw T
	// contains filtered or unexported fields
}

HostRef is a reference to a Go object stored on the host side in Refs.

References created this way are never collected by GC because there is no way to know if the wasm module still needs it. So it is important to explicitly clean references by calling HostRef.Drop.

A common usage pattern is to create a reference in one host-defined function, return it into the wasm module, and then clean it up in another host-defined function caled from wasm when the guest doesn't need the value anymore. In this scenario, the latter function accepts HostRef as an argument and calls its HostRef.Drop method. After that, the reference is removed from Refs in the Store and will be eventually collected by GC.

func (HostRef[T]) Drop added in v0.1.3

func (v HostRef[T]) Drop()

Drop remove the reference from Refs in Store.

Can be called only on lifted references (passed as an argument into a host-defined function).

func (HostRef[T]) Lift

func (HostRef[T]) Lift(s Store) HostRef[T]

Lift implements Lift interface.

func (HostRef[T]) Lower

func (v HostRef[T]) Lower(s Store)

Lower implements Lower interface.

func (HostRef[T]) Unwrap

func (v HostRef[T]) Unwrap() T

Unwrap returns the wrapped value.

func (HostRef[T]) ValueTypes

func (HostRef[T]) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Int

type Int int

Int wraps [int], a signed 32-bit integer.

func (Int) Lift

func (Int) Lift(s Store) Int

Lift implements Lift interface.

func (Int) Lower

func (v Int) Lower(s Store)

Lower implements Lower interface.

func (Int) Unwrap

func (v Int) Unwrap() int

Unwrap returns the wrapped value.

func (Int) ValueTypes

func (Int) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Int16

type Int16 int16

Int16 wraps [int16], a signed 16-bit integer.

func (Int16) Lift

func (Int16) Lift(s Store) Int16

Lift implements Lift interface.

func (Int16) Lower

func (v Int16) Lower(s Store)

Lower implements Lower interface.

func (Int16) Unwrap

func (v Int16) Unwrap() int16

Unwrap returns the wrapped value.

func (Int16) ValueTypes

func (Int16) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Int32

type Int32 int32

Int32 wraps [int32], a signed 32-bit integer.

func (Int32) Lift

func (Int32) Lift(s Store) Int32

Lift implements Lift interface.

func (Int32) Lower

func (v Int32) Lower(s Store)

Lower implements Lower interface.

func (Int32) Unwrap

func (v Int32) Unwrap() int32

Unwrap returns the wrapped value.

func (Int32) ValueTypes

func (Int32) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Int64

type Int64 int64

Int64 wraps [int64], a signed 64-bit integer.

func (Int64) Lift

func (Int64) Lift(s Store) Int64

Lift implements Lift interface.

func (Int64) Lower

func (v Int64) Lower(s Store)

Lower implements Lower interface.

func (Int64) Unwrap

func (v Int64) Unwrap() int64

Unwrap returns the wrapped value.

func (Int64) ValueTypes

func (Int64) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Int8

type Int8 int8

Int8 wraps [int8], a signed 8-bit integer.

func (Int8) Lift

func (Int8) Lift(s Store) Int8

Lift implements Lift interface.

func (Int8) Lower

func (v Int8) Lower(s Store)

Lower implements Lower interface.

func (Int8) Unwrap

func (v Int8) Unwrap() int8

Unwrap returns the wrapped value.

func (Int8) ValueTypes

func (Int8) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Lift

type Lift[T any] interface {
	Value
	Lift(Store) T
}

Lift reads values from Store into a native Go value.

type LiftLower

type LiftLower[T any] interface {
	Lift[T]
	Lower
}

LiftLower is a type that implements both Lift and Lower.

type Lower

type Lower interface {
	Value
	Lower(Store)
}

Lower writes a native Go value into the Store.

type MapRefs

type MapRefs struct {
	Raw map[uint32]any
	// contains filtered or unexported fields
}

MapRefs is a simple Refs implementation powered by a map.

Must be constructed with NewMapRefs.

func NewMapRefs

func NewMapRefs() MapRefs

func (MapRefs) Drop

func (r MapRefs) Drop(idx uint32)

func (MapRefs) Get

func (r MapRefs) Get(idx uint32, def any) (any, bool)

func (MapRefs) Put

func (r MapRefs) Put(val any) uint32

func (MapRefs) Set

func (r MapRefs) Set(idx uint32, val any)

type Memory

type Memory interface {
	// Read is used to [Lift] values of memory-backed types, like [Bytes] and [String].
	Read(offset Addr, count uint32) ([]byte, bool)

	// Read is used to [Lower] values of memory-backed types, like [Bytes] and [String].
	Write(offset Addr, v []byte) bool
}

Memory provides access to the linear memory of the wasm runtime.

The interface is compatible with wazero memory.

type Module

type Module map[string]HostFunc

Module is a collection of host-defined functions in a module with the same name.

It maps function names to function definitions.

func (Module) DefineWazero

func (m Module) DefineWazero(runtime wazero.Runtime, modName string, refs Refs) error

DefineWazero registers the host module in the given wazero runtime.

type Modules

type Modules map[string]Module

Modules is a collection of host-defined modules.

It maps module names to the module definitions.

func (Modules) DefineWazero

func (ms Modules) DefineWazero(runtime wazero.Runtime, refs Refs) error

DefineWazero registers all the host modules in the given wazero runtime.

type Pair

type Pair[L LiftLower[L], R LiftLower[R]] struct {
	Left  L
	Right R
}

Pair wraps two values of arbitrary types.

You can combine multiple pairs to pass more than 2 values at once. All values are passed through the stack, not memory.

func (Pair[L, R]) Lift

func (Pair[L, R]) Lift(s Store) Pair[L, R]

Lift implements Lift interface.

func (Pair[L, R]) Lower

func (v Pair[L, R]) Lower(s Store)

Lower implements Lower interface.

func (Pair[L, R]) ValueTypes

func (v Pair[L, R]) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Raw

type Raw = uint64

type Refs

type Refs interface {
	Get(idx uint32, def any) (any, bool)
	Set(idx uint32, val any)
	Put(val any) uint32
	Drop(idx uint32)
}

Refs holds references to Go values that you want to reference from wasm using HostRef.

type Rune

type Rune = UInt32

Rune is an alias for UInt32.

type SliceMemory added in v0.1.2

type SliceMemory []byte

Wraps a slice of bytes to be used as Memory.

func NewSliceMemory added in v0.1.2

func NewSliceMemory(size int) *SliceMemory

Create new memory instance that internally stores data in a slice.

func (*SliceMemory) Len added in v0.1.2

func (s *SliceMemory) Len() int

func (*SliceMemory) Read added in v0.1.2

func (m *SliceMemory) Read(offset Addr, count uint32) ([]byte, bool)

Read implements the Memory interface.

func (*SliceMemory) Write added in v0.1.2

func (m *SliceMemory) Write(offset Addr, v []byte) bool

Write implements the Memory interface.

type SliceStack

type SliceStack []uint64

SliceStack adapts a slice of raw values into a Stack.

func NewSliceStack

func NewSliceStack(cap int) *SliceStack

func (*SliceStack) Len

func (s *SliceStack) Len() int

func (*SliceStack) Pop

func (s *SliceStack) Pop() uint64

func (*SliceStack) Push

func (s *SliceStack) Push(v uint64)

type Stack

type Stack interface {
	Push(Raw)
	Pop() Raw
}

type Store

type Store struct {
	// Stack is where [Lift] takes the values from and [Lower] puts values to.
	Stack Stack

	// Memory is used by [Lift] and [Lower] of memory-based types,
	// like [Bytes] and [String].
	Memory Memory

	// Refs is used by [HostRef] to pass through the gues module references
	// to complex objects in the host environment that cannot be lowered into wasm.
	Refs Refs

	// Context can be retrieved by the [Context] type.
	Context context.Context

	// Error holds the latest error that happened during [Lift] or [Lower].
	Error error
}

Store provides access for host-defined functions to the runtime data.

Store itself implements Lift and so can be used as a host-defined function argument.

func (Store) Lift

func (Store) Lift(s Store) Store

Lift implements Lift interface.

func (Store) ValueTypes

func (Store) ValueTypes() []ValueType

ValueTypes implements Value interface.

type String

type String struct {
	Offset uint32
	Raw    string
}

String wraps [string].

The string is passed through the linear memory. Since the memory is controlled and allocated by the guest module, you have to provide the Offset to be able to Lower the value into the memory. The offset should be obtained from the guest module, either as an explicit function argument or by calling its allocator.

func (String) Lift

func (String) Lift(s Store) String

Lift implements Lift interface.

func (String) Lower

func (v String) Lower(s Store)

Lower implements Lower interface.

func (String) Unwrap

func (v String) Unwrap() string

Unwrap returns the wrapped value.

func (String) ValueTypes

func (v String) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Time

type Time time.Time

Time wraps time.Time.

func (Time) Lift

func (Time) Lift(s Store) Time

Lift implements Lift interface.

func (Time) Lower

func (v Time) Lower(s Store)

Lower implements Lower interface.

func (Time) Unwrap

func (v Time) Unwrap() time.Time

Unwrap returns the wrapped value.

func (Time) ValueTypes

func (Time) ValueTypes() []ValueType

ValueTypes implements Value interface.

type UInt

type UInt uint

UInt wraps uint, 32-bit unsigned integer.

func (UInt) Lift

func (UInt) Lift(s Store) UInt

Lift implements Lift interface.

func (UInt) Lower

func (v UInt) Lower(s Store)

Lower implements Lower interface.

func (UInt) Unwrap

func (v UInt) Unwrap() uint

Unwrap returns the wrapped value.

func (UInt) ValueTypes

func (UInt) ValueTypes() []ValueType

ValueTypes implements Value interface.

type UInt16

type UInt16 uint16

UInt16 wraps uint16, 16-bit unsigned integer.

func (UInt16) Lift

func (UInt16) Lift(s Store) UInt16

Lift implements Lift interface.

func (UInt16) Lower

func (v UInt16) Lower(s Store)

Lower implements Lower interface.

func (UInt16) Unwrap

func (v UInt16) Unwrap() uint16

Unwrap returns the wrapped value.

func (UInt16) ValueTypes

func (UInt16) ValueTypes() []ValueType

ValueTypes implements Value interface.

type UInt32

type UInt32 uint32

UInt32 wraps uint32, 32-bit unsigned integer.

func (UInt32) Lift

func (UInt32) Lift(s Store) UInt32

Lift implements Lift interface.

func (UInt32) Lower

func (v UInt32) Lower(s Store)

Lower implements Lower interface.

func (UInt32) Unwrap

func (v UInt32) Unwrap() uint32

Unwrap returns the wrapped value.

func (UInt32) ValueTypes

func (UInt32) ValueTypes() []ValueType

ValueTypes implements Value interface.

type UInt64

type UInt64 uint64

UInt64 wraps uint64, 64-bit unsigned integer.

func (UInt64) Lift

func (UInt64) Lift(s Store) UInt64

Lift implements Lift interface.

func (UInt64) Lower

func (v UInt64) Lower(s Store)

Lower implements Lower interface.

func (UInt64) Unwrap

func (v UInt64) Unwrap() uint64

Unwrap returns the wrapped value.

func (UInt64) ValueTypes

func (UInt64) ValueTypes() []ValueType

ValueTypes implements Value interface.

type UInt8

type UInt8 uint8

UInt8 wraps uint8, 8-bit unsigned integer.

func (UInt8) Lift

func (UInt8) Lift(s Store) UInt8

Lift implements Lift interface.

func (UInt8) Lower

func (v UInt8) Lower(s Store)

Lower implements Lower interface.

func (UInt8) Unwrap

func (v UInt8) Unwrap() uint8

Unwrap returns the wrapped value.

func (UInt8) ValueTypes

func (UInt8) ValueTypes() []ValueType

ValueTypes implements Value interface.

type UIntPtr

type UIntPtr uintptr

UIntPtr wraps uintptr, pointer-sized unsigned integer.

func (UIntPtr) Lift

func (UIntPtr) Lift(s Store) UIntPtr

Lift implements Lift interface.

func (UIntPtr) Lower

func (v UIntPtr) Lower(s Store)

Lower implements Lower interface.

func (UIntPtr) Unwrap

func (v UIntPtr) Unwrap() uintptr

Unwrap returns the wrapped value.

func (UIntPtr) ValueTypes

func (UIntPtr) ValueTypes() []ValueType

ValueTypes implements Value interface.

type Value

type Value interface {
	ValueTypes() []ValueType
}

Value is an interface implemented by all the types in wypes.

type ValueType

type ValueType = byte
const (
	// ValueTypeI32 is a 32-bit integer.
	ValueTypeI32 ValueType = 0x7f

	// ValueTypeI64 is a 64-bit integer.
	ValueTypeI64 ValueType = 0x7e

	// ValueTypeF32 is a 32-bit floating point number.
	ValueTypeF32 ValueType = 0x7d

	// ValueTypeF64 is a 64-bit floating point number.
	ValueTypeF64 ValueType = 0x7c

	// ValueTypeExternref is an externref type.
	//
	// Not supported by many guests including TinyGo, so we don't use it.
	// https://github.com/tinygo-org/tinygo/issues/2702
	ValueTypeExternref ValueType = 0x6f
)

type Void

type Void struct{}

Void is a return type of a function that returns nothing.

func (Void) Lower

func (Void) Lower(s Store)

Lower implements Lower interface.

func (Void) ValueTypes

func (Void) ValueTypes() []ValueType

ValueTypes implements Value interface.

Jump to

Keyboard shortcuts

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