validate

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package validate provides reusable codex.Constraint values for common validation rules.

Every constraint in this package does two things:

  1. Checks the value at runtime (on both Encode and Decode).
  2. Annotates schema.Schema automatically so the constraint appears in generated OpenAPI / AsyncAPI specs — no extra wiring required.

String format constraints

Format constraints validate common string patterns and set the corresponding OpenAPI format keyword in the schema:

codex.String().Refine(validate.Email)         // format: email
codex.String().Refine(validate.UUID)          // format: uuid
codex.String().Refine(validate.URL)           // format: uri
codex.String().Refine(validate.DateTime)      // format: date-time
codex.String().Refine(validate.ContainerImage) // OCI container image reference

Range and length constraints

Numeric and string range constraints annotate minimum/maximum/minLength/ maxLength in the schema:

codex.Int().Refine(validate.RangeInt(1, 100))    // minimum: 1, maximum: 100
codex.String().Refine(validate.MaxLen(255))       // maxLength: 255
codex.String().Refine(validate.OneOf("a", "b"))   // enum: [a, b]

Protocol constraints

Path and topic constraints are used with api/rest.WithPathConstraints and api/events.WithTopicConstraints:

rest.NewBuilder(info, rest.WithPathConstraints(validate.HTTPPath))
events.NewBuilder(info, events.WithTopicConstraints(validate.MQTTPublishTopic))

Environment variable name constraints

Validate environment variable names from external input (config files, CLI flags, user-supplied overrides) before passing them to [config.FromEnvVar] or os.LookupEnv:

// POSIX format: [A-Z_][A-Z0-9_]*
codex.String().Refine(validate.EnvVarName)

// Format + namespace — combine for full validation
appVarCodec := codex.String().
    Refine(validate.EnvVarName).
    Refine(validate.EnvVarPrefix("APP_"))

These constraints are not needed when env var names are Go code literals — use them only when names arrive as runtime string input.

Binary byte constraints

Byte size constraints work with any []byte value:

codex.Bytes().Refine(validate.MaxBytes(5 * 1024 * 1024)) // at most 5 MiB
codex.Bytes().Refine(validate.MinBytes(1))               // non-empty

Binary file format constraints

Predefined constants validate common binary file formats by checking their magic bytes (file signatures). Use them with codex.Bytes and [format.Binary]:

validate.PNG   // \x89PNG\r\n\x1a\n  — PNG images
validate.JPEG  // \xFF\xD8\xFF        — JPEG images (all subtypes)
validate.GIF   // GIF87a / GIF89a    — GIF images
validate.WebP  // RIFF....WEBP       — WebP images
validate.PDF   // %PDF-              — PDF documents
validate.ZIP   // PK\x03\x04         — ZIP archives (also DOCX, XLSX, APK, JAR)

When to use which

Use a built-in constant (PNG, JPEG, GIF, WebP, PDF, ZIP) for known file formats — they produce readable error names ("png", "jpeg", …) in logs and codex.ConstraintError values.

Use HasPrefix for custom or proprietary binary formats not covered by the built-in set (e.g. an internal protocol header or a vendor-specific file type).

Use MaxBytes and MinBytes to enforce size limits on any []byte value.

Composition and ordering

When combining constraints with codex.Codec.Refine, put size checks before format checks — rejecting oversized input before reading the magic bytes avoids unnecessary work:

pngCodec := codex.Bytes().
    Refine(validate.MaxBytes(5 * 1024 * 1024)). // 1. size (cheap, fails fast)
    Refine(validate.PNG)                         // 2. format (reads 8 bytes)

Custom constraints

Use codex.Constraint[T] to define your own rules; the validate package uses the same mechanism internally:

func MaxBytes(n int) codex.Constraint[[]byte] {
    return codex.Constraint[[]byte]{
        Name:  fmt.Sprintf("maxBytes(%d)", n),
        Check: func(v []byte) bool { return len(v) <= n },
        Message: func(v []byte) string {
            return fmt.Sprintf("expected at most %d bytes, got %d", n, len(v))
        },
    }
}

Index

Constants

This section is empty.

Variables

View Source
var BearerToken = codex.Constraint[string]{
	Name:  "bearer-token",
	Check: func(v string) bool { return v != "" && v == strings.TrimSpace(v) },
	Message: func(_ string) string {
		return "bearer token must be non-empty and contain no leading or trailing whitespace"
	},
}

BearerToken is a Constraint that validates a non-empty bearer token string. It accepts any non-empty string without leading or trailing whitespace. Use with api/rest.SecurityScheme or api/events.SecurityScheme Codec to format-check extracted bearer tokens before calling SecurityFunc.

View Source
var CIDR = codex.Constraint[string]{
	Name: "cidr",
	Check: func(v string) bool {
		_, _, err := net.ParseCIDR(v)
		return err == nil
	},
	Message: func(v string) string { return fmt.Sprintf("invalid CIDR notation: %q", v) },
}

CIDR is a Constraint that requires a valid CIDR notation string (e.g. "192.168.0.0/24", "10.0.0.0/8", "::/0"). Host bits may be set (e.g. "192.168.0.1/24" is accepted). No schema annotation — there is no standard JSON Schema format for CIDR.

View Source
var ContainerImage = codex.Constraint[string]{
	Name:    "container-image",
	Check:   func(v string) bool { return reContainerImage.MatchString(v) },
	Message: func(v string) string { return fmt.Sprintf("invalid container image reference: %q", v) },
}

ContainerImage is a Constraint that requires a valid OCI container image reference (e.g. "alpine:latest", "ubuntu:22.04", "docker.io/library/nginx:1.25", "my.registry.io:5000/project/image@sha256:abc...").

The reference is checked against the OCI Distribution Spec format:

[registry-host[:port]/]repository[:tag][@digest]

No Schema annotation — there is no standard JSON Schema format for container image references.

View Source
var Date = codex.Constraint[string]{
	Name: "date",
	Check: func(v string) bool {
		_, err := time.Parse("2006-01-02", v)
		return err == nil
	},
	Message: func(v string) string { return fmt.Sprintf("invalid date (expected YYYY-MM-DD): %q", v) },
	Schema:  withFormat("date"),
}

Date is a Constraint that requires an ISO 8601 date string (YYYY-MM-DD).

View Source
var DateTime = codex.Constraint[string]{
	Name: "date-time",
	Check: func(v string) bool {
		_, err := time.Parse(time.RFC3339, v)
		if err == nil {
			return true
		}
		_, err = time.Parse(time.RFC3339Nano, v)
		return err == nil
	},
	Message: func(v string) string { return fmt.Sprintf("invalid date-time (expected RFC 3339): %q", v) },
	Schema:  withFormat("date-time"),
}

DateTime is a Constraint that requires an RFC 3339 date-time string.

View Source
var Email = codex.Constraint[string]{
	Name:    "email",
	Check:   func(v string) bool { return reEmail.MatchString(v) },
	Message: func(v string) string { return fmt.Sprintf("invalid email address: %q", v) },
	Schema:  withFormat("email"),
}

Email is a Constraint that requires a valid email address. Validation uses a standard format check; it does not perform DNS lookup.

View Source
var EnvVarName = codex.Constraint[string]{
	Name:  "envVarName",
	Check: func(v string) bool { return reEnvVar.MatchString(v) },
	Message: func(v string) string {
		return fmt.Sprintf("invalid env var name %q: must match [A-Z_][A-Z0-9_]*", v)
	},
	Schema: func(s schema.Schema) schema.Schema {
		s.Pattern = reEnvVar.String()
		return s
	},
}

EnvVarName is a Constraint that requires a valid POSIX environment variable name: the value must start with an uppercase letter or underscore, and contain only uppercase letters (A-Z), digits (0-9), and underscores.

Rejects lowercase names ("log_level"), names with hyphens ("APP-PORT"), names that start with a digit ("1STVAR"), and names with spaces.

Use this constraint when environment variable names arrive from external input (configuration files, CLI flags, user-provided overrides) rather than as Go code literals, so that programming errors are caught before the name is passed to [config.FromEnvVar] or os.LookupEnv.

Compose with EnvVarPrefix to enforce both format and namespace:

appVarCodec := codex.String().
    Refine(validate.EnvVarName).
    Refine(validate.EnvVarPrefix("APP_"))
View Source
var GIF = codex.Constraint[[]byte]{
	Name: "gif",
	Check: func(v []byte) bool {
		if len(v) < 6 {
			return false
		}
		return bytes.Equal(v[:6], []byte("GIF87a")) || bytes.Equal(v[:6], []byte("GIF89a"))
	},
	Message: func([]byte) string {
		return "expected GIF file: missing or invalid magic bytes (GIF87a or GIF89a)"
	},
}

GIF is a Constraint that requires the byte slice to be a GIF image. It accepts both GIF87a and GIF89a by checking the first 6 bytes.

View Source
var HTTPPath = codex.Constraint[string]{
	Name:  "http-path",
	Check: func(v string) bool { return httpPathRe.MatchString(v) },
	Message: func(v string) string {
		switch {
		case v == "" || v[0] != '/':
			return fmt.Sprintf("http path must start with '/', got %q", v)
		case strings.ContainsRune(v, 0):
			return fmt.Sprintf("http path must not contain null bytes, got %q", v)
		case strings.ContainsRune(v, ' '):
			return fmt.Sprintf("http path must not contain unencoded spaces, got %q", v)
		default:
			return fmt.Sprintf("invalid http path: %q", v)
		}
	},
}

HTTPPath is a Constraint that validates an HTTP path string. It requires the path to start with '/' and contain no unencoded spaces or null bytes. OpenAPI-style path parameters (e.g. /users/{id}) are permitted.

View Source
var Hostname = codex.Constraint[string]{
	Name: "hostname",
	Check: func(v string) bool {
		return len(v) <= 253 && len(v) > 0 && reHostname.MatchString(v)
	},
	Message: func(v string) string { return fmt.Sprintf("invalid hostname: %q", v) },
	Schema:  withFormat("hostname"),
}

Hostname is a Constraint that requires a valid RFC 1123 hostname. Labels must be 1–63 characters; total length must not exceed 253 characters.

View Source
var IP = codex.Constraint[string]{
	Name:    "ip",
	Check:   func(v string) bool { return net.ParseIP(v) != nil },
	Message: func(v string) string { return fmt.Sprintf("invalid IP address: %q", v) },
	Schema:  withFormat("ip"),
}

IP is a Constraint that requires a valid IP address (IPv4 or IPv6).

View Source
var IPv4 = codex.Constraint[string]{
	Name: "ipv4",
	Check: func(v string) bool {
		ip := net.ParseIP(v)
		return ip != nil && ip.To4() != nil && strings.Contains(v, ".")
	},
	Message: func(v string) string { return fmt.Sprintf("invalid IPv4 address: %q", v) },
	Schema:  withFormat("ipv4"),
}

IPv4 is a Constraint that requires a valid IPv4 address.

View Source
var IPv6 = codex.Constraint[string]{
	Name: "ipv6",
	Check: func(v string) bool {
		ip := net.ParseIP(v)
		return ip != nil && ip.To4() == nil
	},
	Message: func(v string) string { return fmt.Sprintf("invalid IPv6 address: %q", v) },
	Schema:  withFormat("ipv6"),
}

IPv6 is a Constraint that requires a valid IPv6 address.

View Source
var IntString = codex.Constraint[string]{
	Name:    "int-string",
	Check:   func(v string) bool { _, err := strconv.Atoi(v); return err == nil },
	Message: func(v string) string { return fmt.Sprintf("expected a valid integer string, got %q", v) },
}

IntString is a Constraint that requires the string to be a valid signed integer (as accepted by strconv.Atoi).

Intended for use in api/rest.RouteConfig.PathParamCodecs and api/events.ChannelConfig.TopicParamCodecs where path and topic variables are always strings but may represent integers:

PathParamCodecs: map[string]codex.Codec[string]{
    "page": codex.String().Refine(validate.IntString),
}
View Source
var JPEG = codex.Constraint[[]byte]{
	Name: "jpeg",
	Check: func(v []byte) bool {
		return len(v) >= 3 && bytes.Equal(v[:3], []byte{0xFF, 0xD8, 0xFF})
	},
	Message: func([]byte) string {
		return `expected JPEG file: missing or invalid SOI marker (\xFF\xD8\xFF)`
	},
}

JPEG is a Constraint that requires the byte slice to be a JPEG image. It checks the 3-byte SOI marker: \xFF\xD8\xFF. This covers all JPEG subtypes (JFIF, Exif, JFIF-Exif, ICC, etc.).

View Source
var JWT = codex.Constraint[string]{
	Name:    "jwt",
	Check:   func(v string) bool { return jwtRe.MatchString(v) },
	Message: func(_ string) string { return "value must be a compact JWT (header.payload.signature in base64url)" },
}

JWT is a Constraint that validates a compact JWT serialization: three base64url-encoded segments separated by dots (header.payload.signature). It does not verify signatures or decode claims. Use with api/rest.SecurityScheme or api/events.SecurityScheme Codec to format-check extracted JWTs before calling SecurityFunc.

View Source
var MQTTPublishTopic = codex.Constraint[string]{
	Name: "mqtt-publish-topic",
	Check: func(v string) bool {
		return v != "" && !strings.ContainsRune(v, 0) && len(v) <= 65535 &&
			!strings.ContainsAny(v, "+#")
	},
	Message: func(v string) string {
		switch {
		case v == "":
			return "mqtt publish topic must not be empty"
		case strings.ContainsRune(v, 0):
			return "mqtt publish topic must not contain null bytes"
		case len(v) > 65535:
			return fmt.Sprintf("mqtt publish topic exceeds maximum length of 65535 bytes, got %d", len(v))
		case strings.ContainsAny(v, "+#"):
			return fmt.Sprintf("mqtt publish topic must not contain wildcard characters '+' or '#', got %q", v)
		default:
			return fmt.Sprintf("invalid mqtt publish topic: %q", v)
		}
	},
}

MQTTPublishTopic is a Constraint that validates an MQTT topic string for publishing. It applies all rules from MQTTTopic and additionally forbids wildcard characters ('+' and '#'), which are reserved for subscriptions only.

View Source
var MQTTTopic = codex.Constraint[string]{
	Name: "mqtt-topic",
	Check: func(v string) bool {
		return v != "" && !strings.ContainsRune(v, 0) && utf8.RuneCountInString(v) > 0 && len(v) <= 65535
	},
	Message: func(v string) string {
		switch {
		case v == "":
			return "mqtt topic must not be empty"
		case strings.ContainsRune(v, 0):
			return "mqtt topic must not contain null bytes"
		case len(v) > 65535:
			return fmt.Sprintf("mqtt topic exceeds maximum length of 65535 bytes, got %d", len(v))
		default:
			return fmt.Sprintf("invalid mqtt topic: %q", v)
		}
	},
}

MQTTTopic is a Constraint that validates an MQTT topic string for general use (subscribe or publish). It requires the string to be non-empty, contain no null bytes (U+0000), and be at most 65535 UTF-8 bytes — as required by the MQTT specification (section 4.7).

View Source
var NegativeFloat = codex.Constraint[float64]{
	Name:    "negative",
	Check:   func(v float64) bool { return v < 0 },
	Message: func(v float64) string { return fmt.Sprintf("expected negative number, got %g", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Maximum = float64ptr(0)
		s.ExclusiveMaximum = true
		return s
	},
}

NegativeFloat is a Constraint that requires float64 < 0.

View Source
var NegativeInt = codex.Constraint[int]{
	Name:    "negative",
	Check:   func(v int) bool { return v < 0 },
	Message: func(v int) string { return fmt.Sprintf("expected negative integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Maximum = float64ptr(0)
		s.ExclusiveMaximum = true
		return s
	},
}

NegativeInt is a Constraint that requires int < 0.

View Source
var NegativeInt32 = codex.Constraint[int32]{
	Name:    "negative",
	Check:   func(v int32) bool { return v < 0 },
	Message: func(v int32) string { return fmt.Sprintf("expected negative integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Maximum = float64ptr(0)
		s.ExclusiveMaximum = true
		return s
	},
}

NegativeInt32 is a Constraint that requires int32 < 0.

View Source
var NegativeInt64 = codex.Constraint[int64]{
	Name:    "negative",
	Check:   func(v int64) bool { return v < 0 },
	Message: func(v int64) string { return fmt.Sprintf("expected negative integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Maximum = float64ptr(0)
		s.ExclusiveMaximum = true
		return s
	},
}

NegativeInt64 is a Constraint that requires int64 < 0.

View Source
var NonEmptyString = codex.Constraint[string]{
	Name:    "non-empty",
	Check:   func(v string) bool { return v != "" },
	Message: func(v string) string { return "expected non-empty string" },
	Schema: func(s schema.Schema) schema.Schema {
		s.MinLength = intptr(1)
		return s
	},
}

NonEmptyString is a Constraint that requires a non-empty string.

View Source
var NonNegativeDuration = codex.Constraint[time.Duration]{
	Name:    "nonNegative",
	Check:   func(v time.Duration) bool { return v >= 0 },
	Message: func(v time.Duration) string { return fmt.Sprintf("expected non-negative duration, got %s", v) },
}

NonNegativeDuration is a Constraint that requires time.Duration >= 0.

View Source
var NonNegativeIntString = codex.Constraint[string]{
	Name: "non-negative-int-string",
	Check: func(v string) bool {
		n, err := strconv.Atoi(v)
		return err == nil && n >= 0
	},
	Message: func(v string) string {
		return fmt.Sprintf("expected a non-negative integer string (>= 0), got %q", v)
	},
}

NonNegativeIntString is a Constraint that requires the string to represent a non-negative integer (>= 0).

View Source
var NonZeroFloat = codex.Constraint[float64]{
	Name:    "nonzero",
	Check:   func(v float64) bool { return v != 0 },
	Message: func(v float64) string { return "expected non-zero number, got 0" },
}

NonZeroFloat is a Constraint that requires float64 != 0.

View Source
var NonZeroInt = codex.Constraint[int]{
	Name:    "nonzero",
	Check:   func(v int) bool { return v != 0 },
	Message: func(_ int) string { return "expected non-zero integer, got 0" },
}

NonZeroInt is a Constraint that requires int != 0.

View Source
var PDF = codex.Constraint[[]byte]{
	Name: "pdf",
	Check: func(v []byte) bool {
		return len(v) >= 5 && bytes.Equal(v[:5], []byte("%PDF-"))
	},
	Message: func([]byte) string {
		return "expected PDF file: missing or invalid magic bytes (%PDF-)"
	},
}

PDF is a Constraint that requires the byte slice to be a PDF document. It checks the 5-byte magic: %PDF-.

View Source
var PNG = codex.Constraint[[]byte]{
	Name: "png",
	Check: func(v []byte) bool {
		return len(v) >= 8 && bytes.Equal(v[:8], []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A})
	},
	Message: func([]byte) string {
		return `expected PNG file: missing or invalid magic bytes (\x89PNG\r\n\x1a\n)`
	},
}

PNG is a Constraint that requires the byte slice to be a PNG image. It checks the 8-byte PNG signature: \x89PNG\r\n\x1a\n.

View Source
var PositiveDuration = codex.Constraint[time.Duration]{
	Name:    "positive",
	Check:   func(v time.Duration) bool { return v > 0 },
	Message: func(v time.Duration) string { return fmt.Sprintf("expected positive duration, got %s", v) },
}

PositiveDuration is a Constraint that requires time.Duration > 0.

View Source
var PositiveFloat = codex.Constraint[float64]{
	Name:    "positive",
	Check:   func(v float64) bool { return v > 0 },
	Message: func(v float64) string { return fmt.Sprintf("expected positive number, got %g", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Minimum = float64ptr(0)
		s.ExclusiveMinimum = true
		return s
	},
}

PositiveFloat is a Constraint that requires float64 > 0.

View Source
var PositiveInt = codex.Constraint[int]{
	Name:    "positive",
	Check:   func(v int) bool { return v > 0 },
	Message: func(v int) string { return fmt.Sprintf("expected positive integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Minimum = float64ptr(0)
		s.ExclusiveMinimum = true
		return s
	},
}

PositiveInt is a Constraint that requires int > 0.

View Source
var PositiveInt32 = codex.Constraint[int32]{
	Name:    "positive",
	Check:   func(v int32) bool { return v > 0 },
	Message: func(v int32) string { return fmt.Sprintf("expected positive integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Minimum = float64ptr(0)
		s.ExclusiveMinimum = true
		return s
	},
}

PositiveInt32 is a Constraint that requires int32 > 0.

View Source
var PositiveInt64 = codex.Constraint[int64]{
	Name:    "positive",
	Check:   func(v int64) bool { return v > 0 },
	Message: func(v int64) string { return fmt.Sprintf("expected positive integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Minimum = float64ptr(0)
		s.ExclusiveMinimum = true
		return s
	},
}

PositiveInt64 is a Constraint that requires int64 > 0.

View Source
var PositiveIntString = codex.Constraint[string]{
	Name: "positive-int-string",
	Check: func(v string) bool {
		n, err := strconv.Atoi(v)
		return err == nil && n > 0
	},
	Message: func(v string) string {
		return fmt.Sprintf("expected a positive integer string (> 0), got %q", v)
	},
}

PositiveIntString is a Constraint that requires the string to represent a positive integer (> 0).

View Source
var PositiveUint = codex.Constraint[uint]{
	Name:    "positive",
	Check:   func(v uint) bool { return v > 0 },
	Message: func(v uint) string { return fmt.Sprintf("expected positive integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Minimum = float64ptr(0)
		s.ExclusiveMinimum = true
		return s
	},
}

PositiveUint is a Constraint that requires uint > 0.

View Source
var PositiveUint64 = codex.Constraint[uint64]{
	Name:    "positive",
	Check:   func(v uint64) bool { return v > 0 },
	Message: func(v uint64) string { return fmt.Sprintf("expected positive integer, got %d", v) },
	Schema: func(s schema.Schema) schema.Schema {
		s.Minimum = float64ptr(0)
		s.ExclusiveMinimum = true
		return s
	},
}

PositiveUint64 is a Constraint that requires uint64 > 0.

View Source
var SemVer = codex.Constraint[string]{
	Name:  "semver",
	Check: func(v string) bool { return reSemVer.MatchString(v) },
	Message: func(v string) string {
		return fmt.Sprintf("invalid semantic version (expected MAJOR.MINOR.PATCH): %q", v)
	},
	Schema: func(s schema.Schema) schema.Schema {
		s.Pattern = reSemVer.String()
		return s
	},
}

SemVer is a Constraint that requires a semantic version string following semver.org spec, with an optional leading "v" prefix. Examples: "1.2.3", "v2.0.0-alpha+build.123".

View Source
var Slug = codex.Constraint[string]{
	Name:  "slug",
	Check: func(v string) bool { return reSlug.MatchString(v) },
	Message: func(v string) string {
		return fmt.Sprintf("invalid slug (lowercase alphanumeric and hyphens only): %q", v)
	},
	Schema: func(s schema.Schema) schema.Schema {
		s.Pattern = reSlug.String()
		return s
	},
}

Slug is a Constraint that requires a URL-friendly slug (lowercase alphanumeric and hyphens). Example valid slugs: "hello-world", "my-post-123".

View Source
var Time = codex.Constraint[string]{
	Name: "time",
	Check: func(v string) bool {
		dummy := "2000-01-01T" + v
		_, err := time.Parse(time.RFC3339, dummy)
		if err == nil {
			return true
		}
		_, err = time.Parse(time.RFC3339Nano, dummy)
		return err == nil
	},
	Message: func(v string) string {
		return fmt.Sprintf("invalid time (expected HH:MM:SS[.frac]Z or ±offset): %q", v)
	},
	Schema: withFormat("time"),
}

Time is a Constraint that requires an RFC 3339 full-time string (e.g. "10:30:00Z", "10:30:00.5+02:00").

View Source
var URI = codex.Constraint[string]{
	Name: "uri",
	Check: func(v string) bool {
		u, err := url.ParseRequestURI(v)
		return err == nil && u.Scheme != "" && u.Host != ""
	},
	Message: func(v string) string { return fmt.Sprintf("invalid URI: %q", v) },
	Schema:  withFormat("uri"),
}

URI is a Constraint that requires a valid absolute URI with any scheme. Use this for non-HTTP URIs such as grpc://, ws://, or custom schemes.

View Source
var URL = URLWithSchemes("http", "https")

URL is a Constraint that requires a valid absolute URL with http or https scheme.

View Source
var UUID = codex.Constraint[string]{
	Name:    "uuid",
	Check:   func(v string) bool { return reUUID.MatchString(v) },
	Message: func(v string) string { return fmt.Sprintf("invalid UUID: %q", v) },
	Schema:  withFormat("uuid"),
}

UUID is a Constraint that requires a valid UUID (any version, RFC 4122 format).

View Source
var WebP = codex.Constraint[[]byte]{
	Name: "webp",
	Check: func(v []byte) bool {
		return len(v) >= 12 &&
			bytes.Equal(v[:4], []byte("RIFF")) &&
			bytes.Equal(v[8:12], []byte("WEBP"))
	},
	Message: func([]byte) string {
		return "expected WebP file: missing or invalid RIFF/WEBP container signature"
	},
}

WebP is a Constraint that requires the byte slice to be a WebP image. It checks for RIFF at bytes 0–3 and WEBP at bytes 8–11 (minimum 12 bytes).

View Source
var ZIP = codex.Constraint[[]byte]{
	Name: "zip",
	Check: func(v []byte) bool {
		return len(v) >= 4 && bytes.Equal(v[:4], []byte{0x50, 0x4B, 0x03, 0x04})
	},
	Message: func([]byte) string {
		return `expected ZIP archive: missing or invalid local file header (PK\x03\x04)`
	},
}

ZIP is a Constraint that requires the byte slice to be a ZIP archive. It checks the 4-byte local file header signature: PK\x03\x04. This also covers ZIP-based formats such as DOCX, XLSX, APK, and JAR.

Functions

func EnvVarPrefix added in v0.11.0

func EnvVarPrefix(prefix string) codex.Constraint[string]

EnvVarPrefix returns a Constraint that requires the string to begin with the given prefix. Use this with EnvVarName to enforce both the POSIX format and a project-specific namespace (e.g. "APP_"):

appVarCodec := codex.String().
    Refine(validate.EnvVarName).
    Refine(validate.EnvVarPrefix("APP_"))

The prefix itself is not validated against EnvVarName; ensure it follows the same conventions (e.g. "APP_" not "app_").

func HasPrefix added in v0.11.0

func HasPrefix(prefix []byte) codex.Constraint[[]byte]

HasPrefix returns a Constraint that requires the byte slice to begin with the given prefix.

For well-known file formats, prefer the predefined constants in this package: PNG, JPEG, GIF, WebP, PDF, ZIP. They produce human-readable constraint names ("png", "jpeg", …) instead of hex strings, and their check logic is tested and documented.

Use HasPrefix for custom or proprietary binary formats not covered by the built-in constants — for example, an internal binary protocol or a vendor-specific file type.

An empty prefix always passes. The produced error is a codex.ConstraintError navigable via errors.As.

func IntStringInRange added in v0.5.0

func IntStringInRange(min, max int) codex.Constraint[string]

IntStringInRange returns a Constraint that requires the string to represent an integer within [min, max] (inclusive on both ends).

func MaxBytes

func MaxBytes(n int) codex.Constraint[[]byte]

MaxBytes returns a Constraint that requires a byte slice of at most n bytes. The check applies to the decoded byte count, not the base64-encoded string length.

func MaxDuration added in v0.3.0

func MaxDuration(d time.Duration) codex.Constraint[time.Duration]

MaxDuration returns a Constraint that requires time.Duration <= d.

func MaxFloat

func MaxFloat(n float64) codex.Constraint[float64]

MaxFloat returns a Constraint that requires float64 <= n.

func MaxInt

func MaxInt(n int) codex.Constraint[int]

MaxInt returns a Constraint that requires int <= n.

func MaxInt32 added in v0.3.0

func MaxInt32(n int32) codex.Constraint[int32]

MaxInt32 returns a Constraint that requires int32 <= n.

func MaxInt64 added in v0.3.0

func MaxInt64(n int64) codex.Constraint[int64]

MaxInt64 returns a Constraint that requires int64 <= n.

func MaxItems added in v0.12.0

func MaxItems[T any](n int) codex.Constraint[[]T]

MaxItems returns a Constraint that requires a slice of at most n elements.

func MaxLen

func MaxLen(n int) codex.Constraint[string]

MaxLen returns a Constraint that requires a string of at most n characters.

func MaxProperties added in v0.12.0

func MaxProperties[K comparable, V any](n int) codex.Constraint[map[K]V]

MaxProperties returns a Constraint that requires a map of at most n entries.

func MaxUint added in v0.3.0

func MaxUint(n uint) codex.Constraint[uint]

MaxUint returns a Constraint that requires uint <= n.

func MaxUint64 added in v0.3.0

func MaxUint64(n uint64) codex.Constraint[uint64]

MaxUint64 returns a Constraint that requires uint64 <= n.

func MinBytes

func MinBytes(n int) codex.Constraint[[]byte]

MinBytes returns a Constraint that requires a byte slice of at least n bytes. The check applies to the decoded byte count, not the base64-encoded string length.

func MinDuration added in v0.3.0

func MinDuration(d time.Duration) codex.Constraint[time.Duration]

MinDuration returns a Constraint that requires time.Duration >= d.

func MinFloat

func MinFloat(n float64) codex.Constraint[float64]

MinFloat returns a Constraint that requires float64 >= n.

func MinInt

func MinInt(n int) codex.Constraint[int]

MinInt returns a Constraint that requires int >= n.

func MinInt32 added in v0.3.0

func MinInt32(n int32) codex.Constraint[int32]

MinInt32 returns a Constraint that requires int32 >= n.

func MinInt64 added in v0.3.0

func MinInt64(n int64) codex.Constraint[int64]

MinInt64 returns a Constraint that requires int64 >= n.

func MinItems added in v0.12.0

func MinItems[T any](n int) codex.Constraint[[]T]

MinItems returns a Constraint that requires a slice of at least n elements. Compose with codex.SliceOf:

itemsCodec := codex.SliceOf(lineItemCodec).Refine(validate.MinItems[LineItem](1))

func MinLen

func MinLen(n int) codex.Constraint[string]

MinLen returns a Constraint that requires a string of at least n characters.

func MinProperties added in v0.12.0

func MinProperties[K comparable, V any](n int) codex.Constraint[map[K]V]

MinProperties returns a Constraint that requires a map of at least n entries. Compose with codex.Map/codex.StringMap:

tagsCodec := codex.StringMap(codex.String()).Refine(validate.MinProperties[string, string](1))

func MinUint added in v0.3.0

func MinUint(n uint) codex.Constraint[uint]

MinUint returns a Constraint that requires uint >= n.

func MinUint64 added in v0.3.0

func MinUint64(n uint64) codex.Constraint[uint64]

MinUint64 returns a Constraint that requires uint64 >= n.

func NonEmptyMap added in v0.12.0

func NonEmptyMap[K comparable, V any]() codex.Constraint[map[K]V]

NonEmptyMap returns a Constraint that requires a non-empty map. Equivalent to MinProperties[K, V](1), with a schema-appropriate name/message — mirrors NonEmptyString/NonEmptySlice for the map case. Like NonEmptySlice, this is a function, not a package-level var: Go has no generic package-level vars, so both type parameters must be supplied at the call site:

tagsCodec := codex.StringMap(codex.String()).Refine(validate.NonEmptyMap[string, string]())

func NonEmptySlice added in v0.12.0

func NonEmptySlice[T any]() codex.Constraint[[]T]

NonEmptySlice returns a Constraint that requires a non-empty slice. Equivalent to MinItems[T](1), with a schema-appropriate name/message — mirrors NonEmptyString for the array case. Unlike NonEmptyString this is a function, not a package-level var: Go has no generic package-level vars, so the type parameter must be supplied at the call site:

itemsCodec := codex.SliceOf(lineItemCodec).Refine(validate.NonEmptySlice[LineItem]())

func OneOf

func OneOf(values ...string) codex.Constraint[string]

OneOf returns a Constraint that requires the string to be one of the given values.

func Pattern

func Pattern(re *regexp.Regexp) codex.Constraint[string]

Pattern returns a Constraint that requires the string to match the given regular expression. The caller is responsible for compiling the regexp (use regexp.MustCompile for literals).

func RangeFloat

func RangeFloat(min, max float64) codex.Constraint[float64]

RangeFloat returns a Constraint that requires min <= float64 <= max.

func RangeInt

func RangeInt(min, max int) codex.Constraint[int]

RangeInt returns a Constraint that requires min <= int <= max.

func RangeInt32 added in v0.3.0

func RangeInt32(min, max int32) codex.Constraint[int32]

RangeInt32 returns a Constraint that requires min <= int32 <= max.

func RangeInt64 added in v0.3.0

func RangeInt64(min, max int64) codex.Constraint[int64]

RangeInt64 returns a Constraint that requires min <= int64 <= max.

func RangeUint added in v0.3.0

func RangeUint(min, max uint) codex.Constraint[uint]

RangeUint returns a Constraint that requires min <= uint <= max.

func RangeUint64 added in v0.3.0

func RangeUint64(min, max uint64) codex.Constraint[uint64]

RangeUint64 returns a Constraint that requires min <= uint64 <= max.

func URLWithSchemes added in v0.3.0

func URLWithSchemes(schemes ...string) codex.Constraint[string]

URLWithSchemes returns a Constraint that requires a valid absolute URL whose scheme is one of the provided values. The host must be non-empty. Schema annotation uses JSON Schema format "uri".

func UniqueItems added in v0.12.0

func UniqueItems[T comparable]() codex.Constraint[[]T]

UniqueItems returns a Constraint that requires every element of a slice to be distinct, checked via Go equality (==) — T must be [comparable]. This excludes element types containing slices, maps, or funcs; for those, write a custom codex.Constraint using reflect.DeepEqual or a domain-specific key extractor instead.

Uses a map[T]struct{} for O(n) duplicate detection.

Types

This section is empty.

Jump to

Keyboard shortcuts

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