validation

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package validation provides structured error primitives plus a small rule-based API for accumulating validation failures.

An Error captures a single failure as a (Subject, Field, Message) triple, where Subject identifies the thing being validated (e.g. a hostname or certificate CN), Field names the attribute that failed, and Message describes the failure in human-readable form. Errors aggregates multiple Error values into a single error while remaining compatible with errors.Is, errors.As, and errors.Join via its Unwrap method.

Higher-level validation is expressed by passing a list of Rule values to Validate, typically constructed via Field and the built-in Check functions (Required, Unique, IsHostPort). Validate accumulates every rule's output into one Errors value and stamps the supplied subject onto entries that don't already carry one.

Conditional logic is expressed with the When family of combinators: When guards Checks on a value-aware predicate, WhenFn guards Checks on a value-free predicate (closing over outer state), and WhenRules guards an entire block of Rules. Nested struct validation is expressed with Nested, which embeds a child's Validator (anything with Validate() error) as a Rule and stamps a subject onto entries the child left unattributed; WhenNested guards a Nested on a value-free predicate, so the child is validated only when present (for example, an optional pointer field the predicate nil-checks).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Validate

func Validate(subject string, rules ...Rule) error

Validate runs each rule, accumulating failures into a single error (which will typically be an Errors instance). Any Error whose Subject is empty is stamped with subject.

Types

type Check

type Check[V any] func(V) error

Check verifies a single value of type V. A nil return means valid.

func GT

func GT[V cmp.Ordered](mark V) Check[V]

GT rejects any value not strictly greater than mark; a value equal to mark fails. It works for any cmp.Ordered type (numbers, strings), comparing with the language's < operator, so for floats a NaN bound or input never satisfies the check.

func GTE

func GTE[V cmp.Ordered](mark V) Check[V]

GTE rejects any value less than mark; a value equal to mark passes. It is the inclusive counterpart to GT and shares its cmp.Ordered and NaN semantics.

func IsHostPort

func IsHostPort() Check[string]

IsHostPort validates that s is syntactically a host:port pair. The check is purely lexical: no DNS lookup, no /etc/services port resolution. Both "host:port" and ":port" (listen-on-all-interfaces) forms are valid, and the port must be a decimal integer in [0, 65535]. Port 0 is accepted because it is a valid listener form meaning "let the OS pick".

func LT

func LT[V cmp.Ordered](mark V) Check[V]

LT rejects any value not strictly less than mark; a value equal to mark fails. It is the mirror of GT and shares its cmp.Ordered and NaN semantics.

func Required

func Required[V comparable]() Check[V]

Required rejects the zero value of V. Note that this means Required[bool]() rejects false; reach for a different check when false is a meaningful value.

func Unique

func Unique[V comparable]() Check[[]V]

Unique rejects a slice containing two or more equal elements. The error message names the first duplicate encountered.

func When

func When[V any](pred func(V) bool, checks ...Check[V]) Check[V]

When runs the supplied checks only when pred(v) returns true. When pred returns false the combinator yields nil and no inner check runs. Inner failures are aggregated into a single Errors return.

func WhenFn

func WhenFn[V any](pred func() bool, checks ...Check[V]) Check[V]

WhenFn is When with a value-free predicate. Use it to guard checks on captured outer state - for example, "if cfg.TLS != nil, require this field" - where the predicate does not depend on the value under validation.

type Error

type Error struct {
	Subject string // identifier of the thing being validated (e.g. a hostname or cert CN)
	Field   string // attribute or property that failed (e.g. "expiry", "key_type")
	Message string // human-readable description of the failure
}

Error is a single validation failure for a named subject and field.

func (Error) Error

func (e Error) Error() string

Error implements the error interface.

type Errors

type Errors []Error

Errors is a collection of Error values.

func (Errors) Error

func (ve Errors) Error() string

Error implements the error interface, joining all individual errors.

func (Errors) Unwrap

func (ve Errors) Unwrap() []error

Unwrap returns each Error as an individual error, enabling errors.As and errors.Is traversal.

type Rule

type Rule func() Errors

Rule produces zero or more validation errors when run.

func Children

func Children[S ~[]T, T any](name string, items S, validate func(*T) error) Rule

Children is the slice counterpart to Nested: it validates each element of items with validate, prefixing a "name[i]" segment onto the resulting subjects to build a dotted path (e.g. "classes[0].subjects[1]"). Empty subjects become the segment; already-set ones are prefixed into a path. The per-element validate is supplied explicitly rather than via the Validator interface, so callers can thread external context by closing over it - for example Children("classes", c.Classes, func(x *Class) error { return x.validate(ctx) }). A nil or empty slice yields no entries and never calls validate.

func Field

func Field[V any](name string, value V, checks ...Check[V]) Rule

Field builds a Rule that runs every Check[V] against value and turns any failure into validation.Errors entries. The returned Errors have their Field stamped with name, unless the check returned a validation.Error or validation.Errors with Field already set, in which case the existing value is preserved.

func Nested

func Nested(subject string, v Validator) Rule

Nested embeds the result of v.Validate as a Rule, prefixing subject onto each entry to build a dotted path. An entry the child left unattributed gets Subject set to subject; an entry the child already attributed gets its Subject prefixed (subject + "." + child), so deeper nesting composes into a path like "classes[0].subjects[1]". A nil error from v yields no entries, an empty subject leaves entries unchanged, and any non-validation error is wrapped as a single entry whose Message is err.Error() and whose Subject is subject.

A child segment that starts with "[" is an accessor on the segment before it rather than a path component of its own, so it is concatenated instead of dot-joined. That covers both element indexes, where a child Subject of "[0]" composes into "classes[0]", and whole-collection pseudo-fields, where an unattributed child Field of "[name]" composes into "classes[name]" and leaves Subject empty - the failure belongs to the collection, not to any one element.

func WhenNested

func WhenNested(pred func() bool, subject string, v Validator) Rule

WhenNested guards a Nested validation behind a value-free predicate: it runs Nested(subject, v) only when pred returns true, yielding no entries otherwise. Because the guard short-circuits before Nested runs, v.Validate is never called when pred is false - so the predicate is the place to nil-check the optional value (for example, func() bool { return cfg.TLS != nil }).

func WhenRules

func WhenRules(pred func() bool, rules ...Rule) Rule

WhenRules runs the supplied rules only when pred returns true. When pred returns false the combinator yields no entries. Use this to skip an entire block of Field rules at once (for example, every TLS.* field when TLS is not configured).

type Validator

type Validator interface {
	Validate() error
}

Validator is satisfied by any type whose Validate method returns an error. Types that already follow the standard "Validate() error" convention satisfy this interface implicitly.

Directories

Path Synopsis
Package certs provides reusable validation.Check building blocks for inspecting X.509 certificates and PEM material: expiry, CA basic constraint, signature-algorithm and key-type strength, and key size.
Package certs provides reusable validation.Check building blocks for inspecting X.509 certificates and PEM material: expiry, CA basic constraint, signature-algorithm and key-type strength, and key size.

Jump to

Keyboard shortcuts

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