Package govalue

import "github.com/ornew/hff/adapters/govalue"

Generated from this checkout's Go source. Released versions are also on pkg.go.dev.

Overview

Package govalue adapts Go records to HFF while keeping reflection out of the compiler and backend contracts.

Choose NewBinding[T] when the Go type is the input contract. It infers the HFF schema once and provides Binding.Build and Filter.Match for typed Go records. Struct names prefer hff tags, then json tags, then exported Go field names; omitempty permits missing fields. Recursive Go types and ambiguous promoted field names are rejected during construction.

Binding object roots are nonnullable: a pointer to a struct or a string-keyed map can configure an engine, but a nil root record is rejected as invalid input. Nested nil pointers, maps, and slices become explicit HFF nulls. Other root types can be inferred for conversion-only use without an engine.

Choose New with WithSchema and WithStructs when an externally defined HFF schema should stay independent of Go structs. Explicit StructMapping maps HFF keys to direct exported Go field names; tags and embedded promotion are not inferred by this converter. String-keyed maps need no struct mapping.

Conversion preserves numeric kinds and distinguishes missing keys from null. It creates owned immutable HFF values, validates the resulting schema, and returns typed errors without partial output. Keep source records unchanged during conversion or matching; a shared Binding or Converter may otherwise be used concurrently. There is no conversion back into mutable Go records.

Index

Types

type Binding

Source

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

Binding derives an immutable HFF schema and conversion plan from static Go type T. It can build typed local filters for repeated matching. Source values must not be mutated during conversion or evaluation.

func NewBinding

Source

func NewBinding[T any](options ...Option) (*Binding[T], error)

NewBinding derives a schema from static Go type T. Engine use requires an object root (struct or string-keyed map). Pointers to object roots and map roots are inferred as nonnullable objects, so a nil object root is an InputError. Other root types can be used for conversion without an engine and retain their inferred nullability. Nil nested pointers, maps, and slices remain explicit nulls. Struct field names use an hff tag, then a json tag, then the Go name; omitempty makes a field optional and '-' skips it. Anonymous structs are promoted, and ambiguous promoted names, recursive types, unsupported fields, and unrecognized tag options are ConfigurationErrors. Options may set input limits; explicit schema and struct-mapping options are not accepted.

Example

{
	type Record struct {
		Name	string	`json:"name"`
		Age	int	`json:"age"`
	}
	binding, err := govalue.NewBinding[*Record]()
	if err != nil {
		panic(err)
	}
	e, err := engine.New(
		engine.WithSchema(binding.Schema()),
		engine.WithCapabilities(capabilities.Standard()),
	)
	if err != nil {
		panic(err)
	}
	ctx := context.Background()
	program, err := e.Compile(ctx, `name age>=18`)
	if err != nil {
		panic(err)
	}
	filter, err := binding.Build(ctx, program)
	if err != nil {
		panic(err)
	}
	for _, record := range []*Record{{Name: "Alice", Age: 25}, {Name: "Bob", Age: 16}} {
		matched, err := filter.Match(ctx, record)
		if err != nil {
			panic(err)
		}
		if matched {
			fmt.Println(record.Name)
		}
	}

}
Complete runnable example
package main

import (
	"context"
	"fmt"

	"github.com/ornew/hff/adapters/govalue"
	"github.com/ornew/hff/capabilities"
	"github.com/ornew/hff/engine"
)

func main() {
	type Record struct {
		Name	string	`json:"name"`
		Age	int	`json:"age"`
	}
	binding, err := govalue.NewBinding[*Record]()
	if err != nil {
		panic(err)
	}
	e, err := engine.New(
		engine.WithSchema(binding.Schema()),
		engine.WithCapabilities(capabilities.Standard()),
	)
	if err != nil {
		panic(err)
	}
	ctx := context.Background()
	program, err := e.Compile(ctx, `name age>=18`)
	if err != nil {
		panic(err)
	}
	filter, err := binding.Build(ctx, program)
	if err != nil {
		panic(err)
	}
	for _, record := range []*Record{{Name: "Alice", Age: 25}, {Name: "Bob", Age: 16}} {
		matched, err := filter.Match(ctx, record)
		if err != nil {
			panic(err)
		}
		if matched {
			fmt.Println(record.Name)
		}
	}
}

Output:

Alice

func (*Binding[T]) Build

Source

func (b *Binding[T]) Build(ctx context.Context, program hff.Program, options ...local.Option) (*Filter[T], error)

Build constructs a typed local filter only when program carries the exact inferred schema. The Program must still have an engine-compatible object root. Options configure local evaluation; local Build errors are returned.

func (*Binding[T]) Convert

Source

func (b *Binding[T]) Convert(ctx context.Context, source T) (hff.Value, error)

Convert maps source to an immutable HFF Value and checks the inferred schema. It returns no partial value on cancellation, input-limit, or validation errors. Keep source unchanged for the duration of the call.

func (*Binding[T]) Schema

Source

func (b *Binding[T]) Schema() hff.Type

Schema returns the immutable inferred HFF schema, or an invalid Type for a nil Binding.

type Config

Source

type Config struct {
	// Schema is the required explicit HFF schema for New.
	Schema	hff.Type
	// Structs maps concrete Go struct types to HFF object keys.
	Structs	[]StructMapping
	// MaxInputDepth and MaxInputValues bound both Go traversal (including
	// pointer/interface wrappers) and subsequent HFF validation independently.
	Limits	hff.Limits
	// UnlimitedLimits explicitly disables the adapter's input depth/value limits.
	UnlimitedLimits	bool
}

Config describes an explicit Go-to-HFF conversion. Schema is required; Structs maps Go structs to HFF object fields. Only input depth/value limits are used, both while traversing Go wrappers and while validating the HFF result. Other Limits fields do not impose conversion budgets.

type Converter

Source

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

Converter owns a snapshot of its configuration and supports concurrent calls. Source records must not be mutated while Convert is running.

func New

Source

func New(options ...Option) (*Converter, error)

New applies options from left to right, validates and snapshots the result, and requires an explicit valid schema. Zero limits select finite input defaults. The returned Converter supports concurrent calls as long as each source value remains unchanged during conversion.

Example

{
	type Person struct {
		DisplayName	string
		Years		int
	}
	converter, err := govalue.New(
		govalue.WithSchema(schema.Struct(schema.String("name"), schema.Int("age"))),
		govalue.WithStructs(govalue.StructMapping{
			Type:	reflect.TypeFor[Person](),
			Fields:	map[string]string{"name": "DisplayName", "age": "Years"},
		}),
	)
	if err != nil {
		panic(err)
	}
	value, err := converter.Convert(context.Background(), Person{DisplayName: "Alice", Years: 25})
	if err != nil {
		panic(err)
	}
	name, _ := value.Lookup("name")
	text, _ := name.AsString()
	fmt.Println(text)

}
Complete runnable example
package main

import (
	"context"
	"fmt"
	"reflect"

	"github.com/ornew/hff/adapters/govalue"
	"github.com/ornew/hff/schema"
)

func main() {
	type Person struct {
		DisplayName	string
		Years		int
	}
	converter, err := govalue.New(
		govalue.WithSchema(schema.Struct(schema.String("name"), schema.Int("age"))),
		govalue.WithStructs(govalue.StructMapping{
			Type:	reflect.TypeFor[Person](),
			Fields:	map[string]string{"name": "DisplayName", "age": "Years"},
		}),
	)
	if err != nil {
		panic(err)
	}
	value, err := converter.Convert(context.Background(), Person{DisplayName: "Alice", Years: 25})
	if err != nil {
		panic(err)
	}
	name, _ := value.Lookup("name")
	text, _ := name.AsString()
	fmt.Println(text)
}

Output:

Alice

func (*Converter) Convert

Source

func (c *Converter) Convert(ctx context.Context, source any) (hff.Value, error)

Convert maps one Go value to an HFF Value and validates it against the Converter's explicit schema. It preserves numeric representations without coercion and does not infer names from tags. Nil pointers, maps, slices, interfaces, and nil itself become explicit null; non-nil empty containers remain empty. Cycles, unsupported representations, invalid text, cancellation, exceeded input limits, and schema mismatches return typed errors without a partial Value. Do not mutate source while conversion is running.

Example

{
	converter, err := govalue.New(govalue.WithSchema(schema.Struct(schema.Int("age"))))
	if err != nil {
		panic(err)
	}

	value, err := converter.Convert(context.Background(), map[string]any{"age": int64(25)})
	if err != nil {
		panic(err)
	}
	age, _ := value.Lookup("age")
	integer, ok := age.AsInt()
	fmt.Println(integer, ok)

}
Complete runnable example
package main

import (
	"context"
	"fmt"

	"github.com/ornew/hff/adapters/govalue"
	"github.com/ornew/hff/schema"
)

func main() {
	converter, err := govalue.New(govalue.WithSchema(schema.Struct(schema.Int("age"))))
	if err != nil {
		panic(err)
	}
	// A string-keyed Go map needs no StructMapping. Conversion preserves the
	// integer kind instead of promoting it to a floating value.
	value, err := converter.Convert(context.Background(), map[string]any{"age": int64(25)})
	if err != nil {
		panic(err)
	}
	age, _ := value.Lookup("age")
	integer, ok := age.AsInt()
	fmt.Println(integer, ok)
}

Output:

25 true

type Filter

Source

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

Filter evaluates a Program against Go values of T using its Binding's conversion plan. It is immutable and safe for concurrent calls when records are not mutated during matching.

func (*Filter[T]) Match

Source

func (f *Filter[T]) Match(ctx context.Context, record T) (bool, error)

Match converts and validates record before evaluating the local filter. A completed false result is not an error; conversion, input, cancellation, and evaluation-limit failures are returned as typed errors.

type Option

Source

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

Option changes one Converter setting. New applies options from left to right.

func WithConfig

Source

func WithConfig(config *Config) Option

WithConfig copies a complete Converter configuration. Nil is rejected, and later options replace fields copied from this value.

func WithLimits

Source

func WithLimits(limits hff.Limits) Option

WithLimits selects input traversal/validation limits. Other limit fields are validated but do not control conversion; zero input limits resolve to finite defaults.

func WithSchema

Source

func WithSchema(schema hff.Type) Option

WithSchema sets the required explicit HFF root schema for New.

func WithStructs

Source

func WithStructs(mappings ...StructMapping) Option

WithStructs sets explicit Go struct mappings. New copies the slice and maps.

func WithUnlimitedLimits

Source

func WithUnlimitedLimits() Option

WithUnlimitedLimits disables this adapter's input depth/value limits.

type StructMapping

Source

type StructMapping struct {
	// Type is the exact Go struct type to map, typically reflect.TypeFor[T]().
	Type	reflect.Type
	// Fields maps HFF field names to Go field names.
	Fields	map[string]string
}

StructMapping explicitly maps an HFF object type to one Go struct type. Fields maps HFF object keys to direct exported Go field names; embedded or promoted fields are not accepted by this explicit mapping. Unmapped Go fields are omitted from the converted object.

Explore HFF
Search documentation

Search the language specification and guides.