In Development Package, API may change between versions.

import "github.com/egdaemon/eg/runtime/x/wasi/egmatrix"

Package egmatrix generates every permutation of provided options by assigning values to their respective fields on a struct type T.

The package provides a fluent builder API for defining mutation groups, where each group represents different possible values for a field. The Perm() method generates the cartesian product of all mutation groups, yielding every possible combination.

Basic Usage

Define a struct and use the builder to specify options for each field:

type Config struct {
	Debug   bool
	Timeout string
}

m := egmatrix.New[Config]().
	Boolean(func(c *Config, v bool) { c.Debug = v }).
	String(func(c *Config, v string) { c.Timeout = v }, "30s", "60s")

for config := range m.Perm() {
	// Yields 4 permutations: all combinations of Debug (true/false) and Timeout (30s/60s)
	fmt.Printf("Debug=%t Timeout=%s\n", config.Debug, config.Timeout)
}

Type\-Specific Methods

The builder provides convenience methods for common types:

  • Boolean(fn): Generates permutations for true and false
  • String(fn, options...): Generates permutations for each string option
  • Int64(fn, options...): Generates permutations for each int64 option
  • Float64(fn, options...): Generates permutations for each float64 option

Custom Types

For custom types, use the Assign function directly:

type LogLevel int
const (
	Info LogLevel = iota
	Warning
	Error
)

type Config struct {
	Level LogLevel
}

m := egmatrix.New[Config]()
egmatrix.Assign(m, func(c *Config, v LogLevel) { c.Level = v }, Info, Warning, Error)

Cartesian Product

The Perm() method generates the cartesian product of all mutation groups:

m := egmatrix.New[BuildConfig]().
	Boolean(func(c *BuildConfig, v bool) { c.Optimize = v }).      // 2 options
	String(func(c *BuildConfig, v string) { c.Target = v }, "linux", "darwin"). // 2 options
	Int64(func(c *BuildConfig, v int64) { c.Workers = v }, 2, 4)   // 2 options

// Yields 2 × 2 × 2 = 8 permutations
for config := range m.Perm() {
	// Process each unique combination
}

<a name="Op"></a>

func Op

func Op[T any](b Builder[T], mkop func(*T) eg.OpFn) eg.OpFn

execute each variation of the matrix using the generating function.

<a name="Builder"></a>

type Builder

generates every permutation of provided options by assigning the values to their respective fields on T. example:

type Foo struct{
	Field1 string
	Field2 bool
}

egmatrix.New(Foo{}).

Boolean(func(d *Foo, v bool) {d.Field2 = v}).
String(func(d*Foo, v string) {d.Field1 = v},)
type Builder[T any] interface {
    Boolean(func(dst *T, v bool)) Builder[T]
    String(m func(dst *T, v string), options ...string) Builder[T]
    Int(m func(dst *T, v int), options ...int) Builder[T]
    Int8(m func(dst *T, v int8), options ...int8) Builder[T]
    Int16(m func(dst *T, v int16), options ...int16) Builder[T]
    Int32(m func(dst *T, v int32), options ...int32) Builder[T]
    Int64(m func(dst *T, v int64), options ...int64) Builder[T]
    Uint(m func(dst *T, v uint), options ...uint) Builder[T]
    Uint8(m func(dst *T, v uint8), options ...uint8) Builder[T]
    Uint16(m func(dst *T, v uint16), options ...uint16) Builder[T]
    Uint32(m func(dst *T, v uint32), options ...uint32) Builder[T]
    Uint64(m func(dst *T, v uint64), options ...uint64) Builder[T]
    Float32(m func(dst *T, v float32), options ...float32) Builder[T]
    Float64(m func(dst *T, v float64), options ...float64) Builder[T]
    Duration(m func(dst *T, v time.Duration), options ...time.Duration) Builder[T]
    Time(m func(dst *T, v time.Time), options ...time.Time) Builder[T]
    Addr(m func(dst *T, v netip.Addr), options ...netip.Addr) Builder[T]
    Prefix(m func(dst *T, v netip.Prefix), options ...netip.Prefix) Builder[T]
    Perm() iter.Seq[T]
}

<a name="M"></a>

type M

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

<a name="Assign"></a>

func Assign

func Assign[T any, V any](m *M[T], fn func(dst *T, v V), options ...V) *M[T]
<details><summary>Example</summary> <p>
package main

import (
	"fmt"

	"github.com/egdaemon/eg/runtime/x/wasi/egmatrix"
)

func main() {
	type Server struct {
		Port int64
	}

	m := egmatrix.New[Server]()
	egmatrix.Assign(m, func(s *Server, v int64) { s.Port = v }, 8080, 8443, 9000)

	for server := range m.Perm() {
		fmt.Printf("Port=%d\n", server.Port)
	}

}

Output

Port=8080
Port=8443
Port=9000
</p> </details> <details><summary>Example (Custom Type)</summary> <p>
package main

import (
	"fmt"

	"github.com/egdaemon/eg/runtime/x/wasi/egmatrix"
)

func main() {
	type LogLevel int

	const (
		Info LogLevel = iota
		Warning
		Error
	)

	type Config struct {
		Level LogLevel
	}

	m := egmatrix.New[Config]()
	egmatrix.Assign(
		m,
		func(c *Config, v LogLevel) { c.Level = v },
		Info, Warning, Error,
	)

	for config := range m.Perm() {
		fmt.Printf("LogLevel=%d\n", config.Level)
	}

}

Output

LogLevel=0
LogLevel=1
LogLevel=2
</p> </details>

<a name="New"></a>

func New

func New[T any]() *M[T]
<details><summary>Example</summary> <p>
package main

import (
	"fmt"

	"github.com/egdaemon/eg/runtime/x/wasi/egmatrix"
)

func main() {
	type Config struct {
		Debug   bool
		Timeout string
	}

	m := egmatrix.New[Config]().
		Boolean(func(c *Config, v bool) { c.Debug = v }).
		String(func(c *Config, v string) { c.Timeout = v }, "30s", "60s")

	for config := range m.Perm() {
		fmt.Printf("Debug=%t Timeout=%s\n", config.Debug, config.Timeout)
	}

}

Output

Debug=true Timeout=30s
Debug=true Timeout=60s
Debug=false Timeout=30s
Debug=false Timeout=60s
</p> </details>

<a name="M[T].Addr"></a>

func (*M[T]) Addr

func (m *M[T]) Addr(fn func(dst *T, v netip.Addr), options ...netip.Addr) Builder[T]

<a name="M[T].Boolean"></a>

func (*M[T]) Boolean

func (m *M[T]) Boolean(fn func(dst *T, v bool)) Builder[T]
<details><summary>Example</summary> <p>
package main

import (
	"fmt"

	"github.com/egdaemon/eg/runtime/x/wasi/egmatrix"
)

func main() {
	type Feature struct {
		Enabled bool
	}

	m := egmatrix.New[Feature]().
		Boolean(func(f *Feature, v bool) { f.Enabled = v })

	for feature := range m.Perm() {
		fmt.Printf("Enabled=%t\n", feature.Enabled)
	}

}

Output

Enabled=true
Enabled=false
</p> </details>

<a name="M[T].Duration"></a>

func (*M[T]) Duration

func (m *M[T]) Duration(fn func(dst *T, v time.Duration), options ...time.Duration) Builder[T]

<a name="M[T].Float32"></a>

func (*M[T]) Float32

func (m *M[T]) Float32(fn func(dst *T, v float32), options ...float32) Builder[T]

<a name="M[T].Float64"></a>

func (*M[T]) Float64

func (m *M[T]) Float64(fn func(dst *T, v float64), options ...float64) Builder[T]

<a name="M[T].Int"></a>

func (*M[T]) Int

func (m *M[T]) Int(fn func(dst *T, v int), options ...int) Builder[T]

<a name="M[T].Int16"></a>

func (*M[T]) Int16

func (m *M[T]) Int16(fn func(dst *T, v int16), options ...int16) Builder[T]

<a name="M[T].Int32"></a>

func (*M[T]) Int32

func (m *M[T]) Int32(fn func(dst *T, v int32), options ...int32) Builder[T]

<a name="M[T].Int64"></a>

func (*M[T]) Int64

func (m *M[T]) Int64(fn func(dst *T, v int64), options ...int64) Builder[T]

<a name="M[T].Int8"></a>

func (*M[T]) Int8

func (m *M[T]) Int8(fn func(dst *T, v int8), options ...int8) Builder[T]

<a name="M[T].Perm"></a>

func (*M[T]) Perm

func (m *M[T]) Perm() iter.Seq[T]
<details><summary>Example</summary> <p>
package main

import (
	"fmt"

	"github.com/egdaemon/eg/runtime/x/wasi/egmatrix"
)

func main() {
	type BuildConfig struct {
		Optimize bool
		Target   string
		Workers  int64
	}

	m := egmatrix.New[BuildConfig]().
		Boolean(func(c *BuildConfig, v bool) { c.Optimize = v }).
		String(func(c *BuildConfig, v string) { c.Target = v }, "linux", "darwin").
		Int64(func(c *BuildConfig, v int64) { c.Workers = v }, 2, 4)

	count := 0
	for config := range m.Perm() {
		count++
		fmt.Printf("%d: Optimize=%t Target=%s Workers=%d\n",
			count, config.Optimize, config.Target, config.Workers)
	}

}

Output

1: Optimize=true Target=linux Workers=2
2: Optimize=true Target=linux Workers=4
3: Optimize=true Target=darwin Workers=2
4: Optimize=true Target=darwin Workers=4
5: Optimize=false Target=linux Workers=2
6: Optimize=false Target=linux Workers=4
7: Optimize=false Target=darwin Workers=2
8: Optimize=false Target=darwin Workers=4
</p> </details>

<a name="M[T].Prefix"></a>

func (*M[T]) Prefix

func (m *M[T]) Prefix(fn func(dst *T, v netip.Prefix), options ...netip.Prefix) Builder[T]

<a name="M[T].String"></a>

func (*M[T]) String

func (m *M[T]) String(fn func(dst *T, v string), options ...string) Builder[T]
<details><summary>Example</summary> <p>
package main

import (
	"fmt"

	"github.com/egdaemon/eg/runtime/x/wasi/egmatrix"
)

func main() {
	type Request struct {
		Method string
	}

	m := egmatrix.New[Request]().
		String(func(r *Request, v string) { r.Method = v }, "GET", "POST", "PUT")

	for req := range m.Perm() {
		fmt.Printf("Method=%s\n", req.Method)
	}

}

Output

Method=GET
Method=POST
Method=PUT
</p> </details>

<a name="M[T].Time"></a>

func (*M[T]) Time

func (m *M[T]) Time(fn func(dst *T, v time.Time), options ...time.Time) Builder[T]

<a name="M[T].Uint"></a>

func (*M[T]) Uint

func (m *M[T]) Uint(fn func(dst *T, v uint), options ...uint) Builder[T]

<a name="M[T].Uint16"></a>

func (*M[T]) Uint16

func (m *M[T]) Uint16(fn func(dst *T, v uint16), options ...uint16) Builder[T]

<a name="M[T].Uint32"></a>

func (*M[T]) Uint32

func (m *M[T]) Uint32(fn func(dst *T, v uint32), options ...uint32) Builder[T]

<a name="M[T].Uint64"></a>

func (*M[T]) Uint64

func (m *M[T]) Uint64(fn func(dst *T, v uint64), options ...uint64) Builder[T]

<a name="M[T].Uint8"></a>

func (*M[T]) Uint8

func (m *M[T]) Uint8(fn func(dst *T, v uint8), options ...uint8) Builder[T]