runtime

package
v1.2.5 Latest Latest
Warning

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

Go to latest
Published: May 10, 2025 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package runtime provides core functionality for loading, verifying, and executing WebAssembly modules.

The runtime package is the main interface for working with WASM plugins in Hookr. It handles loading modules from files, verifying their integrity, and facilitating communication between the runtime application and the plugins.

Creating a new Runtime

A Runtime is the central component that manages a WASM plugin:

ctx := context.Background()
rt, err := runtime.New(ctx, runtime.WithFile("./plugin.wasm"))
if err != nil {
	log.Fatalf("Failed to create engine: %v", err)
}
defer rt.Close(ctx)

Runtime Configuration

The Runtime can be configured with various options:

rt, err := runtime.New(ctx,
	// Load plugin from file
	runtime.WithFile("./plugin.wasm"),

	// Configure I/O
	runtime.WithStdout(os.Stdout),
	runtime.WithStderr(os.Stderr),

	// Set a custom logger
	runtime.WithLogger(func(msg string) {
		log.Printf("[PLUGIN] %s", msg)
	}),

	// Register host functions
	runtime.WithHostFns(myHostFn),

	// Set a custom random source for deterministic behavior
	runtime.WithRandSource(myRandSource),
)

Invoking Plugin Functions

Plugin functions can be invoked directly with byte slices:

result, err := rt.Invoke(ctx, "function_name", []byte("input data"))
if err != nil {
	log.Fatalf("Function call failed: %v", err)
}
fmt.Printf("Result: %s\n", result)

Type-Safe Function Calls

For type safety, you can create strongly-typed function wrappers:

// Define request/response types that implement msgp.Marshaler/Unmarshaler
type Request struct {
	Input string `msg:"input"`
}

type Response struct {
	Output string `msg:"output"`
}

// Create a type-safe function
fn, err := runtime.PluginFn[*Request, *Response](engine, "process")
if err != nil {
	log.Fatalf("Failed to create function wrapper: %v", err)
}

// Call the function
resp, err := fn.Call(&Request{Input: "test data"})
if err != nil {
	log.Fatalf("Function call failed: %v", err)
}
fmt.Printf("Output: %s\n", resp.Output)

Registering Host Functions

Host functions allow the plugin to call back into the host application:

// Define a runtime function
helloFn := func(input *HelloRequest) (*HelloResponse, error) {
	return &HelloResponse{
		Message: fmt.Sprintf("Hello, %s!", input.Name),
	}, nil
}

// Register the runtime function
hostFn := runtime.HostFn("hello", helloFn)

engine, err := runtime.New(ctx,
	runtime.WithFile("./plugin.wasm"),
	runtime.WithHostFns(hostFn),
)

File Integrity

To ensure the integrity of WASM files, you can use hashing:

engine, err := runtime.New(ctx,
	runtime.WithFile("./plugin.wasm",
		runtime.WithHash("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"),
		runtime.WithHasher(runtime.Sha256Hasher{}),
	),
)

Memory Management

You can query memory usage of the WASM module:

memSize := rt.MemorySize()
fmt.Printf("WASM module memory size: %d bytes\n", memSize)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultRuntime

func DefaultRuntime(ctx context.Context) (wazero.Runtime, error)

DefaultRuntime implements NewRuntime by returning a wazero runtime with WASI and AssemblyScript host functions instantiated.

Types

type CallFn

type CallFn func(ctx context.Context, payload []byte) ([]byte, error)

CallFn is a function to be called by the CallHandler. It takes a context, a payload, and a serializer. It returns a byte slice and an error.

func Fn

func Fn[In Unmarshaler, Out Marshaler](fn CallFnT[In, Out]) CallFn

Fn converts a strongly-typed GoFn to a byte-based CallFn allowing WASM plugins to call it. This allows for defining a strongly typed function, which can be called from WASM that will use a byte slice for input and output for communication.

type CallFnT

type CallFnT[In Unmarshaler, Out Marshaler] func(ctx context.Context, input In) (Out, error)

CallFnT is a generic function that accepts and returns specific types It handles marshaling/unmarshaling automatically

type CallFns

type CallFns = map[string]CallFn

type DefaultHasher

type DefaultHasher struct{}

DefaultHasher is a default implementation of the Hasher interface. It does not actually hash anything, but is a placeholder for future implementations. It is used when no specific hashing algorithm is provided and no verification is needed.

The Hash method always returns an empty string, and IsValid only returns true when the hash is empty.

Example:

hasher := DefaultHasher{}

// Always returns empty string
hash, _ := hasher.Hash([]byte("data"))

// Returns true only when hash is empty
isValid := hasher.IsValid("", []byte("data")) // true
isValid = hasher.IsValid("some-hash", []byte("data")) // false

func (DefaultHasher) Hash

func (h DefaultHasher) Hash(raw []byte) (string, error)

func (DefaultHasher) IsValid

func (h DefaultHasher) IsValid(hash string, raw []byte) bool

type File

type File struct {
	Path string
	Hash string
	Name string
	// contains filtered or unexported fields
}

File is a struct that represents a WebAssembly module that is stored in a file. We can possibly add more types of Wasm modules in the future, which have different sources.

func NewFile

func NewFile(path string, opts ...FileOption) (*File, error)

NewFile creates a new File instance and verifies it. If the file or name is invalid, an error is returned. Otherwise the *File is returned.

func (*File) GetData

func (f *File) GetData() ([]byte, error)

GetData returns the WasmData for WasmData if the data has already been loaded into memory somewhere else

func (*File) Verify

func (f *File) Verify() (*File, error)

Verify checks if the File has been configured correctly and returns it if it is. Otherwise will return a specific error

type FileOption

type FileOption func(*File)

func WithHash

func WithHash(hash string) FileOption

WithHash sets the expected Hash field of a File

func WithHasher

func WithHasher(hasher Hasher) FileOption

WithHasher sets the Hasher to use for validating the hash of the File

type Hasher

type Hasher interface {
	// Hash returns a hash for the provided data
	Hash(data []byte) (string, error)

	// IsValid checks if a hash and data match
	IsValid(hash string, data []byte) bool
}

Hasher hashes and validates byte arrays. It provides functionality for computing cryptographic hashes of data and validating data against a previously computed hash.

There are two built-in implementations:

  • Sha256Hasher: Uses the SHA-256 algorithm for secure hashing
  • DefaultHasher: A no-op implementation that performs no actual hashing

Example:

// Using Sha256Hasher
hasher := Sha256Hasher{}

// Compute hash of a file
data, _ := os.ReadFile("plugin.wasm")
hash, _ := hasher.Hash(data)
fmt.Println("SHA-256 hash:", hash)

// Verify file integrity
isValid := hasher.IsValid(hash, data)
fmt.Println("Is valid:", isValid)

type HostFunc

type HostFunc interface {
	// Fn returns the name and function to be called
	Fn() (name string, fn CallFn)
}

type HostFuncByte

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

HostFuncByte is a wrapper for CallFn that provides a name and a function

func HostFnByte

func HostFnByte(name string, fn CallFn) *HostFuncByte

HostFnByte is a function that takes a byte slice and returns a byte slice It is used to call a function that takes a byte slice and returns a byte slice

func (HostFuncByte) Fn

func (f HostFuncByte) Fn() (name string, fn CallFn)

Fn returns the name and function to be called This is used to register the function with the host

type HostFunction

type HostFunction[In Unmarshaler, Out Marshaler] struct {
	// contains filtered or unexported fields
}

HostFunction is a wrapper for CallFnT that provides a name and a function This is used to register the function with the host

func HostFnSerial

func HostFnSerial[In Unmarshaler, Out Marshaler](
	name string,
	fn CallFnT[In, Out],
) *HostFunction[In, Out]

func (*HostFunction[In, Out]) Fn

func (f *HostFunction[In, Out]) Fn() (name string, fn CallFn)

type Marshaler

type Marshaler interface {
	MarshalMsg([]byte) ([]byte, error)
}

type NewRuntime

type NewRuntime func(context.Context) (wazero.Runtime, error)

NewRuntime returns a new wazero runtime which is called when the New method on hookr.Runtime is called. The result is closed upon wapc.Module Close.

type Option

type Option func(*Runtime) error

func WithCallHandler

func WithCallHandler(callHandler module.CallHandler) Option

WithCallHandler sets the call handler for the engine.

func WithFile

func WithFile(file string, opts ...FileOption) Option

WithFile sets the file for the engine.

func WithHostFns

func WithHostFns(fns ...HostFunc) Option

WithHostFns sets the host functions which are callable from the plugin.

func WithLogger

func WithLogger(logger logger.Logger) Option

WithLogger sets the logger for the engine.

func WithRandSource

func WithRandSource(rand io.Reader) Option

WithRandSource sets the random source for the runtime.

func WithStderr

func WithStderr(stderr io.Writer) Option

WithStderr sets the stderr writer for the engine.

func WithStdout

func WithStdout(stdout io.Writer) Option

WithStdout sets the stdout writer for the engine.

type PluginFunc

type PluginFunc[In, Out any] interface {
	// Call takes an input of type In and returns an output of type Out
	// It returns an error if the call fails
	Call(ctx context.Context, input In) (Out, error)
}

type PluginFuncByte

type PluginFuncByte struct {
	Name string
	// contains filtered or unexported fields
}

PluginFuncByte is a function that takes a byte slice and returns a byte slice

func PluginFnByte

func PluginFnByte(
	rt *Runtime,
	name string,
) (*PluginFuncByte, error)

PluginFnByte creates a new PluginFunc with the given name and engine. This will always be a byte slice in and out.

func (PluginFuncByte) Call

func (p PluginFuncByte) Call(ctx context.Context, input []byte) ([]byte, error)

Call takes an input of type In and returns an output of type Out These will always be []byte in and out.

type PluginFuncSerial

type PluginFuncSerial[In Marshaler, Out Unmarshaler] struct {
	Name string
	// contains filtered or unexported fields
}

func PluginFnSerial

func PluginFnSerial[In Marshaler, Out Unmarshaler](
	rt *Runtime,
	name string,
) (*PluginFuncSerial[In, Out], error)

Will create a new PluginFunc with the given name and engine. This is used to register the function with the host

func (*PluginFuncSerial[In, Out]) Call

func (p *PluginFuncSerial[In, Out]) Call(ctx context.Context, input In) (Out, error)

type Runtime

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

func New

func New(ctx context.Context, opts ...Option) (*Runtime, error)

func (*Runtime) Close

func (e *Runtime) Close(ctx context.Context) error

func (*Runtime) Compile

func (e *Runtime) Compile() error

Compile compiles the plugin module. It must be called after the runtime is initialized and before the module is instantiated.

func (*Runtime) Init

func (e *Runtime) Init() error

Init initializes the engine by setting up the runtime, config, and hookr. It is called when the engine is created.

func (*Runtime) InitConfig

func (e *Runtime) InitConfig()

InitConfig initializes the wazero module config with the default settings.

func (*Runtime) InitHookr

func (e *Runtime) InitHookr() error

InitHookr initializes the hookr host module and sets it to the wazero runtime.

func (*Runtime) InitRuntime

func (e *Runtime) InitRuntime() error

Will initialize the wazero runtime

func (*Runtime) Instantiate

func (e *Runtime) Instantiate() error

Instantiate instantiates the compiled module. It must be called after the module is compiled. It will also call the WASI and hookr start functions if

func (*Runtime) Invoke

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

Invoke calls the plugin function with the given operation and payload.

func (*Runtime) MemorySize

func (e *Runtime) MemorySize() uint32

MemorySize returns the size of the memory for this instance. This is the size in bytes, not the number of pages.

func (*Runtime) RegisterFunction

func (e *Runtime) RegisterFunction(name string, fn CallFn)

RegisterFunction registers a host function with the engine.

type Sha256Hasher

type Sha256Hasher struct{}

Sha256Hasher is an implementation of the Hasher interface. It uses SHA-256 hashing algorithm to hash and validate data. This provides a secure way to verify the integrity of WebAssembly modules.

Example:

hasher := Sha256Hasher{}
hash, _ := hasher.Hash(wasmBytes)
fmt.Println("Use this hash for verification:", hash)

func (Sha256Hasher) Hash

func (h Sha256Hasher) Hash(data []byte) (string, error)

func (Sha256Hasher) IsValid

func (h Sha256Hasher) IsValid(hash string, data []byte) bool

type Unmarshaler

type Unmarshaler interface {
	UnmarshalMsg([]byte) ([]byte, error)
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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