optional

package
v0.2.0-alpha Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2025 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Optional types may be either empty (null) or contain a value that must pass validation.

Optional types support the following encoding/decoding formats:

  • json
  • sql
  • text

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Any

type Any[T any] struct {
	Custom[T, validate.Any[T]]
}

Any accepts any value of T

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.Any[string]

	// Parse a value
	value.MustParse("any value is acceptable")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty string is also valid
	value.MustParse("")
	val, exists = value.Get()
	fmt.Printf("Empty string value: %q, Exists: %t\n", val, exists)

	// Parse nil for an empty optional
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// GetPtr returns nil for empty optionals
	value.MustParse(nil)
	ptr := value.GetPtr()
	fmt.Printf("GetPtr returns nil: %t\n", ptr == nil)

}
Output:

Value: any value is acceptable, Exists: true
Empty string value: "", Exists: true
After nil: Exists: false
GetPtr returns nil: true

type Base64

type Base64[T constraint.Text] struct {
	Custom[T, validate.Base64[T]]
}

Base64 accepts valid base64 encoded strings

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.Base64[string]

	// Valid base64
	value.MustParse("SGVsbG8gV29ybGQ=") // "Hello World"
	_, exists := value.Get()
	fmt.Printf("Value exists: %t\n", exists)

	// Empty optional is valid
	value.MustParse(nil)
	_, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid base64 will fail validation
	var invalidValue optional.Base64[string]
	err := invalidValue.Parse("not!valid!base64!")

	fmt.Printf("Invalid base64 error: %t\n", err != nil)

}
Output:

Value exists: true
After nil: Exists: false
Invalid base64 error: true

type CIDR

type CIDR[T constraint.Text] struct {
	Custom[T, validate.CIDR[T]]
}

CIDR accepts CIDR notation IP address and prefix length, like "192.0.2.0/24" or "2001:db8::/32", as defined in RFC 4632 and RFC 4291

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.CIDR[string]

	// Valid CIDR
	value.MustParse("192.168.1.0/24")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid CIDRs will fail validation
	var invalidValue optional.CIDR[string]
	err := invalidValue.Parse("192.168.1.1") // missing prefix
	fmt.Printf("Missing prefix error: %t\n", err != nil)

}
Output:

Value: 192.168.1.0/24, Exists: true
After nil: Exists: false
Missing prefix error: true

type Charset

type Charset[T constraint.Text, F charset.Filter] struct {
	Custom[T, validate.Charset0[T, F]]
}

Charset accepts text which contains only runes acceptable by filter

NOTE: empty strings will also pass. Use NonZeroCharset if you need non-empty strings

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
	"github.com/metafates/schema/validate/charset"
)

func main() {
	// Charset allows empty strings
	var value optional.Charset[string, charset.Letter]

	value.MustParse("abcDEF")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty strings are allowed
	value.MustParse("")
	val, exists = value.Get()
	fmt.Printf("Empty string: %q, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Non-alphabetic characters will fail validation
	var invalidValue optional.Charset[string, charset.Letter]

	err := invalidValue.Parse("abc123")
	fmt.Printf("Non-alphabetic error: %t\n", err != nil)

}
Output:

Value: abcDEF, Exists: true
Empty string: "", Exists: true
After nil: Exists: false
Non-alphabetic error: true

type CountryAlpha

type CountryAlpha[T constraint.Text] struct {
	Custom[T, validate.CountryAlpha[T]]
}

CountryAlpha accepts either CountryAlpha2 or CountryAlpha3

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.CountryAlpha[string]

	// Accepts both 2-letter codes
	value.MustParse("US")
	val, exists := value.Get()
	fmt.Printf("2-letter: %s, Exists: %t\n", val, exists)

	// And 3-letter codes
	value.MustParse("GBR")
	val, exists = value.Get()
	fmt.Printf("3-letter: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid country codes will fail validation
	var invalidValue optional.CountryAlpha[string]
	err := invalidValue.Parse("USAX") // too long
	fmt.Printf("Too long code error: %t\n", err != nil)

}
Output:

2-letter: US, Exists: true
3-letter: GBR, Exists: true
After nil: Exists: false
Too long code error: true

type CountryAlpha2

type CountryAlpha2[T constraint.Text] struct {
	Custom[T, validate.CountryAlpha2[T]]
}

CountryAlpha2 accepts case-insensitive ISO 3166 2-letter country code

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.CountryAlpha2[string]

	// Valid country code
	value.MustParse("US")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Case-insensitive
	value.MustParse("gb")
	val, exists = value.Get()
	fmt.Printf("Case-insensitive: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid country codes will fail validation
	var invalidValue optional.CountryAlpha2[string]
	err := invalidValue.Parse("USA") // too long
	fmt.Printf("Three-letter code error: %t\n", err != nil)

}
Output:

Value: US, Exists: true
Case-insensitive: gb, Exists: true
After nil: Exists: false
Three-letter code error: true

type CountryAlpha3

type CountryAlpha3[T constraint.Text] struct {
	Custom[T, validate.CountryAlpha3[T]]
}

CountryAlpha3 accepts case-insensitive ISO 3166 3-letter country code

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.CountryAlpha3[string]

	// Valid country code
	value.MustParse("USA")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid country codes will fail validation
	var invalidValue optional.CountryAlpha3[string]
	err := invalidValue.Parse("US") // too short
	fmt.Printf("Two-letter code error: %t\n", err != nil)

}
Output:

Value: USA, Exists: true
After nil: Exists: false
Two-letter code error: true

type CurrencyAlpha

type CurrencyAlpha[T constraint.Text] struct {
	Custom[T, validate.CurrencyAlpha[T]]
}

CurrencyAlpha accepts case-insensitive ISO 4217 alphabetic currency code

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.CurrencyAlpha[string]

	// Valid currency code
	value.MustParse("USD")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid currency codes will fail validation
	var invalidValue optional.CurrencyAlpha[string]
	err := invalidValue.Parse("US") // too short
	fmt.Printf("Too short code error: %t\n", err != nil)

}
Output:

Value: USD, Exists: true
After nil: Exists: false
Too short code error: true

type Custom

type Custom[T any, V validate.Validator[T]] struct {
	// contains filtered or unexported fields
}

Custom optional type. When given non-null value it errors if validation fails

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
	"github.com/metafates/schema/validate"
)

func main() {
	// Custom allows creating an optional type with any validator
	var value optional.Custom[int, validate.Positive[int]]
	value.MustParse(42)
	val, exists := value.Get()
	fmt.Printf("Value: %d, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid values will fail validation
	var invalidValue optional.Custom[int, validate.Positive[int]]
	err := invalidValue.Parse(-5)
	fmt.Printf("Invalid value error: %t\n", err != nil)

}
Output:

Value: 42, Exists: true
After nil: Exists: false
Invalid value error: true

func (Custom[T, V]) Get

func (c Custom[T, V]) Get() (T, bool)

Get returns the contained value and a boolean stating its presence. True if value exists, false otherwise.

Panics if value was not validated yet. See also Custom.GetPtr

func (Custom[T, V]) GetPtr

func (c Custom[T, V]) GetPtr() *T

Get returns the pointer to the contained value. Non-nil if value exists, nil otherwise. Pointed value is a shallow copy.

Panics if value was not validated yet. See also Custom.Get

func (Custom[T, V]) HasValue

func (c Custom[T, V]) HasValue() bool

HasValue returns the presence of the contained value

func (Custom[T, V]) MarshalJSON

func (c Custom[T, V]) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface.

func (Custom[T, V]) MarshalText

func (c Custom[T, V]) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface

func (Custom[T, V]) Must

func (c Custom[T, V]) Must() T

Must returns the contained value and panics if it does not have one. You can check for its presence using Custom.HasValue or use a more safe alternative Custom.Get

func (*Custom[T, V]) MustParse

func (c *Custom[T, V]) MustParse(value any)

func (*Custom[T, V]) Parse

func (c *Custom[T, V]) Parse(value any) error

Parse checks if given value is valid. If it is, a value is used to initialize this type. Value is converted to the target type T, if possible. If not - parse.UnconvertableTypeError is returned. It is allowed to pass convertable type wrapped in optional type.

Parsed type is validated, therefore it is safe to call Custom.Get afterwards.

Passing nil results a valid empty instance.

func (*Custom[T, V]) Scan

func (c *Custom[T, V]) Scan(src any) error

Scan implements the sql.Scanner interface.

Use Custom.Parse instead if you need to construct this value manually

func (*Custom[T, V]) TypeValidate

func (c *Custom[T, V]) TypeValidate() error

TypeValidate implements the validate.TypeValidateable interface. You should not call this function directly.

func (*Custom[T, V]) UnmarshalJSON

func (c *Custom[T, V]) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the json.Unmarshaler interface.

func (*Custom[T, V]) UnmarshalText

func (c *Custom[T, V]) UnmarshalText(data []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface

func (Custom[T, V]) Value

func (c Custom[T, V]) Value() (driver.Value, error)

Value implements the driver.Valuer interface.

Use Custom.Get method instead for getting the go value

type Email

type Email[T constraint.Text] struct {
	Custom[T, validate.Email[T]]
}

Email accepts a single RFC 5322 address, e.g. "Barry Gibbs <bg@example.com>"

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.Email[string]

	// Valid email
	value.MustParse("user@example.com")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid emails will fail validation
	var invalidValue optional.Email[string]
	err := invalidValue.Parse("not-an-email")
	fmt.Printf("Invalid email error: %t\n", err != nil)

	// Using GetPtr()
	value.MustParse("user@example.com")
	ptr := value.GetPtr()
	fmt.Printf("GetPtr value: %s, IsNil: %t\n", *ptr, ptr == nil)

}
Output:

Value: user@example.com, Exists: true
After nil: Exists: false
Invalid email error: true
GetPtr value: user@example.com, IsNil: false

type Even

type Even[T constraint.Integer] struct {
	Custom[T, validate.Even[T]]
}

Even accepts real numbers divisible by two

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.Even[int]

	// Valid even value
	value.MustParse(42)
	val, exists := value.Get()
	fmt.Printf("Value: %d, Exists: %t\n", val, exists)

	// Zero is even
	value.MustParse(0)
	val, exists = value.Get()
	fmt.Printf("Zero value: %d, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Odd numbers will fail validation
	var invalidValue optional.Even[int]
	err := invalidValue.Parse(3)
	fmt.Printf("Odd number error: %t\n", err != nil)

}
Output:

Value: 42, Exists: true
Zero value: 0, Exists: true
After nil: Exists: false
Odd number error: true

type HTTPURL

type HTTPURL[T constraint.Text] struct {
	Custom[T, validate.HTTPURL[T]]
}

HTTPURL accepts a single http(s) url.

See also URL

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.HTTPURL[string]

	// Valid HTTP URL
	value.MustParse("https://example.com")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Non-HTTP URLs will fail validation
	var invalidValue optional.HTTPURL[string]
	err := invalidValue.Parse("ftp://example.com")
	fmt.Printf("Non-HTTP URL error: %t\n", err != nil)

	// Relative URLs will fail validation
	err = invalidValue.Parse("/relative/path")
	fmt.Printf("Relative URL error: %t\n", err != nil)

}
Output:

Value: https://example.com, Exists: true
After nil: Exists: false
Non-HTTP URL error: true
Relative URL error: true

type IP

type IP[T constraint.Text] struct {
	Custom[T, validate.IP[T]]
}

IP accepts an IP address. The address can be in dotted decimal ("192.0.2.1"), IPv6 ("2001:db8::68"), or IPv6 with a scoped addressing zone ("fe80::1cc0:3e8c:119f:c2e1%ens18").

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.IP[string]

	// Valid IPv4
	value.MustParse("192.168.1.1")
	val, exists := value.Get()
	fmt.Printf("IPv4: %s, Exists: %t\n", val, exists)

	// Valid IPv6
	value.MustParse("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
	val, exists = value.Get()
	fmt.Printf("Has IPv6: %t\n", exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid IPs will fail validation
	var invalidValue optional.IP[string]
	err := invalidValue.Parse("999.999.999.999")
	fmt.Printf("Invalid IP error: %t\n", err != nil)

}
Output:

IPv4: 192.168.1.1, Exists: true
Has IPv6: true
After nil: Exists: false
Invalid IP error: true

type IPV4

type IPV4[T constraint.Text] struct {
	Custom[T, validate.IPV4[T]]
}

IP accepts an IP V4 address (e.g. "192.0.2.1").

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.IPV4[string]

	// Valid IPv4
	value.MustParse("192.168.1.1")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// IPv6 addresses will fail validation
	var invalidValue optional.IPV4[string]
	err := invalidValue.Parse("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
	fmt.Printf("IPv6 address error: %t\n", err != nil)

}
Output:

Value: 192.168.1.1, Exists: true
After nil: Exists: false
IPv6 address error: true

type IPV6

type IPV6[T constraint.Text] struct {
	Custom[T, validate.IPV6[T]]
}

IP accepts an IP V6 address, including IPv4-mapped IPv6 addresses. The address can be regular IPv6 ("2001:db8::68"), or IPv6 with a scoped addressing zone ("fe80::1cc0:3e8c:119f:c2e1%ens18")

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.IPV6[string]

	// Valid IPv6
	value.MustParse("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
	_, exists := value.Get()
	fmt.Printf("Has value: %t\n", exists)

	// Empty optional is valid
	value.MustParse(nil)
	_, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// IPv4 addresses will fail validation
	var invalidValue optional.IPV6[string]
	err := invalidValue.Parse("192.168.1.1")
	fmt.Printf("IPv4 address error: %t\n", err != nil)

}
Output:

Has value: true
After nil: Exists: false
IPv4 address error: true

type InFuture

type InFuture[T constraint.Time] struct {
	Custom[T, validate.InFuture[T]]
}

InFuture accepts any time after current timestamp

See also InPast

Example
package main

import (
	"fmt"
	"time"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.InFuture[time.Time]

	// Valid future time
	futureTime := time.Now().Add(24 * time.Hour) // 1 day in future
	value.MustParse(futureTime)
	val, exists := value.Get()
	fmt.Printf("Is in future: %t, Exists: %t\n", val.After(time.Now()), exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Past times will fail validation
	var invalidValue optional.InFuture[time.Time]
	pastTime := time.Now().Add(-24 * time.Hour) // 1 day ago
	err := invalidValue.Parse(pastTime)
	fmt.Printf("Past time error: %t\n", err != nil)

}
Output:

Is in future: true, Exists: true
After nil: Exists: false
Past time error: true

type InPast

type InPast[T constraint.Time] struct {
	Custom[T, validate.InPast[T]]
}

InPast accepts any time before current timestamp

See also InFuture

Example
package main

import (
	"fmt"
	"time"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.InPast[time.Time]

	// Valid past time
	pastTime := time.Now().Add(-24 * time.Hour) // 1 day ago
	value.MustParse(pastTime)
	val, exists := value.Get()
	fmt.Printf("Is in past: %t, Exists: %t\n", val.Before(time.Now()), exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Future times will fail validation
	var invalidValue optional.InPast[time.Time]
	futureTime := time.Now().Add(24 * time.Hour) // 1 day in future
	err := invalidValue.Parse(futureTime)
	fmt.Printf("Future time error: %t\n", err != nil)

}
Output:

Is in past: true, Exists: true
After nil: Exists: false
Future time error: true

type JSON

type JSON[T constraint.Text] struct {
	Custom[T, validate.JSON[T]]
}

JSON accepts valid json encoded text

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.JSON[string]

	// Valid JSON
	value.MustParse(`{"name": "John", "age": 30}`)
	_, exists := value.Get()
	fmt.Printf("Has value: %t\n", exists)

	// Empty optional is valid
	value.MustParse(nil)
	_, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid JSON will fail validation
	var invalidValue optional.JSON[string]
	err := invalidValue.Parse(`{"name": "John", "age": }`) // missing value
	fmt.Printf("Invalid JSON error: %t\n", err != nil)

}
Output:

Has value: true
After nil: Exists: false
Invalid JSON error: true

type LangAlpha

type LangAlpha[T constraint.Text] struct {
	Custom[T, validate.LangAlpha[T]]
}

LangAlpha accepts either LangAlpha2 or LangAlpha3

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.LangAlpha[string]

	// Accepts both 2-letter codes
	value.MustParse("en")
	val, exists := value.Get()
	fmt.Printf("2-letter: %s, Exists: %t\n", val, exists)

	// And 3-letter codes
	value.MustParse("ger")
	val, exists = value.Get()
	fmt.Printf("3-letter: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid language codes will fail validation
	var invalidValue optional.LangAlpha[string]
	err := invalidValue.Parse("engx") // too long
	fmt.Printf("Too long code error: %t\n", err != nil)

}
Output:

2-letter: en, Exists: true
3-letter: ger, Exists: true
After nil: Exists: false
Too long code error: true

type LangAlpha2

type LangAlpha2[T constraint.Text] struct {
	Custom[T, validate.LangAlpha2[T]]
}

LangAlpha2 accepts case-insesitive ISO 639 2-letter language code.

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.LangAlpha2[string]

	// Valid language code
	value.MustParse("en")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid language codes will fail validation
	var invalidValue optional.LangAlpha2[string]
	err := invalidValue.Parse("eng") // too long
	fmt.Printf("Too long code error: %t\n", err != nil)

}
Output:

Value: en, Exists: true
After nil: Exists: false
Too long code error: true

type LangAlpha3

type LangAlpha3[T constraint.Text] struct {
	Custom[T, validate.LangAlpha3[T]]
}

LangAlpha2 accepts case-insesitive ISO 639 3-letter language code.

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.LangAlpha3[string]

	// Valid language code
	value.MustParse("eng")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid language codes will fail validation
	var invalidValue optional.LangAlpha3[string]
	err := invalidValue.Parse("en") // too short
	fmt.Printf("Too short code error: %t\n", err != nil)

}
Output:

Value: eng, Exists: true
After nil: Exists: false
Too short code error: true

type Latitude

type Latitude[T constraint.Real] struct {
	Custom[T, validate.Latitude[T]]
}

Latitude accepts any number in the range [-90; 90]

See also Longitude

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.Latitude[float64]

	// Valid latitude
	value.MustParse(37.7749) // San Francisco
	val, exists := value.Get()
	fmt.Printf("Value: %.4f, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Out of range latitudes will fail validation
	var invalidValue optional.Latitude[float64]
	err := invalidValue.Parse(91)
	fmt.Printf("Too high error: %t\n", err != nil)

}
Output:

Value: 37.7749, Exists: true
After nil: Exists: false
Too high error: true

type Longitude

type Longitude[T constraint.Real] struct {
	Custom[T, validate.Longitude[T]]
}

Longitude accepts any number in the range [-180; 180]

See also Latitude

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.Longitude[float64]

	// Valid longitude
	value.MustParse(-122.4194) // San Francisco
	val, exists := value.Get()
	fmt.Printf("Value: %.4f, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Out of range longitudes will fail validation
	var invalidValue optional.Longitude[float64]
	err := invalidValue.Parse(181)
	fmt.Printf("Too high error: %t\n", err != nil)

}
Output:

Value: -122.4194, Exists: true
After nil: Exists: false
Too high error: true

type MAC

type MAC[T constraint.Text] struct {
	Custom[T, validate.MAC[T]]
}

MAC accepts an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet IP over InfiniBand link-layer address

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.MAC[string]

	// Valid MAC address
	value.MustParse("00:1B:44:11:3A:B7")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid MAC addresses will fail validation
	var invalidValue optional.MAC[string]
	err := invalidValue.Parse("not a mac address")
	fmt.Printf("Invalid MAC error: %t\n", err != nil)

}
Output:

Value: 00:1B:44:11:3A:B7, Exists: true
After nil: Exists: false
Invalid MAC error: true

type MIME

type MIME[T constraint.Text] struct {
	Custom[T, validate.MIME[T]]
}

MIME accepts RFC 1521 mime type string

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.MIME[string]

	// Valid MIME type
	value.MustParse("text/html")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid MIME types will fail validation
	var invalidValue optional.MIME[string]
	err := invalidValue.Parse("not a mime type")
	fmt.Printf("Invalid MIME type error: %t\n", err != nil)

}
Output:

Value: text/html, Exists: true
After nil: Exists: false
Invalid MIME type error: true

type Negative

type Negative[T constraint.Real] struct {
	Custom[T, validate.Negative[T]]
}

Negative accepts all negative real numbers and zero

See also Positive

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var intValue optional.Negative[int]

	// Valid negative value
	intValue.MustParse(-42)
	val, exists := intValue.Get()
	fmt.Printf("Value: %d, Exists: %t\n", val, exists)

	// Empty optional is valid
	intValue.MustParse(nil)
	val, exists = intValue.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Zero and positive values will fail validation
	var invalidValue optional.Negative[int]
	err := invalidValue.Parse(0)
	fmt.Printf("Zero error: %t\n", err != nil)

	err = invalidValue.Parse(5)
	fmt.Printf("Positive error: %t\n", err != nil)

}
Output:

Value: -42, Exists: true
After nil: Exists: false
Zero error: true
Positive error: true

type Negative0

type Negative0[T constraint.Real] struct {
	Custom[T, validate.Negative0[T]]
}

Negative0 accepts all negative real numbers including zero.

See Negative for zero excluding variant.

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var intValue optional.Negative0[int]

	// Valid negative value
	intValue.MustParse(-42)
	val, exists := intValue.Get()
	fmt.Printf("Value: %d, Exists: %t\n", val, exists)

	// Zero is valid for Negative0
	intValue.MustParse(0)
	val, exists = intValue.Get()
	fmt.Printf("Zero value: %d, Exists: %t\n", val, exists)

	// Empty optional is valid
	intValue.MustParse(nil)
	val, exists = intValue.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Positive values will fail validation
	var invalidValue optional.Negative0[int]
	err := invalidValue.Parse(5)
	fmt.Printf("Positive error: %t\n", err != nil)

}
Output:

Value: -42, Exists: true
Zero value: 0, Exists: true
After nil: Exists: false
Positive error: true

type NonEmpty

type NonEmpty[S ~[]T, T any] struct {
	Custom[S, validate.NonEmpty[S, T]]
}

NonEmpty accepts a non-empty slice-like (len > 0)

See NonEmptySlice for a slice shortcut

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	// NonEmpty with a slice type
	var value optional.NonEmpty[[]string, string]
	value.MustParse([]string{"hello", "world"})
	val, exists := value.Get()
	fmt.Printf("Value: %v, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Empty slices will fail validation
	var invalidValue optional.NonEmpty[[]string, string]
	err := invalidValue.Parse([]string{})
	fmt.Printf("Empty slice error: %t\n", err != nil)

}
Output:

Value: [hello world], Exists: true
After nil: Exists: false
Empty slice error: true

type NonEmptySlice

type NonEmptySlice[T any] struct {
	Custom[[]T, validate.NonEmptySlice[T]]
}

NonEmpty accepts a non-empty slice (len > 0)

See NonEmpty for a more generic version

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	// NonEmptySlice is a simplified version of NonEmpty
	var value optional.NonEmptySlice[int]
	value.MustParse([]int{1, 2, 3})
	val, exists := value.Get()
	fmt.Printf("Value: %v, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Empty slices will fail validation
	var invalidValue optional.NonEmptySlice[int]
	err := invalidValue.Parse([]int{})
	fmt.Printf("Empty slice error: %t\n", err != nil)

}
Output:

Value: [1 2 3], Exists: true
After nil: Exists: false
Empty slice error: true

type NonZero

type NonZero[T comparable] struct {
	Custom[T, validate.NonZero[T]]
}

NonZero accepts all non-zero values

The zero value is: - 0 for numeric types, - false for the boolean type, and - "" (the empty string) for strings.

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var strValue optional.NonZero[string]

	// Valid non-zero value
	strValue.MustParse("non-empty string")
	val, exists := strValue.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optionals are valid
	strValue.MustParse(nil)
	fmt.Printf("HasValue after nil: %t\n", strValue.HasValue())

	// Empty strings will fail validation
	var invalidStr optional.NonZero[string]
	err := invalidStr.Parse("")
	fmt.Printf("Empty string error: %t\n", err != nil)

	// Zero number will fail validation
	var numValue optional.NonZero[int]
	err = numValue.Parse(0)
	fmt.Printf("Zero number error: %t\n", err != nil)

	// Must() will panic on empty optionals
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Must() panicked on empty optional as expected")
		}
	}()
	strValue.MustParse(nil)
	strValue.Must() // This will panic

}
Output:

Value: non-empty string, Exists: true
HasValue after nil: false
Empty string error: true
Zero number error: true
Must() panicked on empty optional as expected

type NonZeroCharset

type NonZeroCharset[T constraint.Text, F charset.Filter] struct {
	Custom[T, validate.Charset[T, F]]
}

NonZeroCharset combines NonZero and Charset

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
	"github.com/metafates/schema/validate/charset"
)

func main() {
	// NonZeroCharset requires non-empty strings
	var value optional.NonZeroCharset[string, charset.Or[charset.Letter, charset.Number]]

	value.MustParse("abc123DEF")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Empty strings will fail validation
	var invalidValue optional.NonZeroCharset[string, charset.Or[charset.Letter, charset.Number]]

	err := invalidValue.Parse("")
	fmt.Printf("Empty string error: %t\n", err != nil)

	// Non-alphanumeric characters will fail validation
	err = invalidValue.Parse("abc123!")
	fmt.Printf("Non-alphanumeric error: %t\n", err != nil)

}
Output:

Value: abc123DEF, Exists: true
After nil: Exists: false
Empty string error: true
Non-alphanumeric error: true

type Odd

type Odd[T constraint.Integer] struct {
	Custom[T, validate.Odd[T]]
}

Odd accepts real numbers not divisible by two

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.Odd[int]

	// Valid odd value
	value.MustParse(43)
	val, exists := value.Get()
	fmt.Printf("Value: %d, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Even numbers will fail validation
	var invalidValue optional.Odd[int]
	err := invalidValue.Parse(2)
	fmt.Printf("Even number error: %t\n", err != nil)

	err = invalidValue.Parse(0)
	fmt.Printf("Zero error: %t\n", err != nil)

}
Output:

Value: 43, Exists: true
After nil: Exists: false
Even number error: true
Zero error: true

type Positive

type Positive[T constraint.Real] struct {
	Custom[T, validate.Positive[T]]
}

Positive accepts all positive real numbers and zero

See also Negative

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var intValue optional.Positive[int]

	// Valid positive value
	intValue.MustParse(42)
	val, exists := intValue.Get()
	fmt.Printf("Value: %d, Exists: %t\n", val, exists)

	// Empty optional is valid
	intValue.MustParse(nil)
	val, exists = intValue.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Zero and negative values will fail validation
	var invalidValue optional.Positive[int]
	err := invalidValue.Parse(0)
	fmt.Printf("Zero error: %t\n", err != nil)

	err = invalidValue.Parse(-5)
	fmt.Printf("Negative error: %t\n", err != nil)

}
Output:

Value: 42, Exists: true
After nil: Exists: false
Zero error: true
Negative error: true

type Positive0

type Positive0[T constraint.Real] struct {
	Custom[T, validate.Positive0[T]]
}

Positive0 accepts all positive real numbers including zero.

See Positive for zero excluding variant.

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var intValue optional.Positive0[int]

	// Valid positive value
	intValue.MustParse(42)
	val, exists := intValue.Get()
	fmt.Printf("Value: %d, Exists: %t\n", val, exists)

	// Zero is valid for Positive0
	intValue.MustParse(0)
	val, exists = intValue.Get()
	fmt.Printf("Zero value: %d, Exists: %t\n", val, exists)

	// Empty optional is valid
	intValue.MustParse(nil)
	val, exists = intValue.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Negative values will fail validation
	var invalidValue optional.Positive0[int]
	err := invalidValue.Parse(-5)
	fmt.Printf("Negative error: %t\n", err != nil)

}
Output:

Value: 42, Exists: true
Zero value: 0, Exists: true
After nil: Exists: false
Negative error: true

type URL

type URL[T constraint.Text] struct {
	Custom[T, validate.URL[T]]
}

URL accepts a single url. The url may be relative (a path, without a host) or absolute (starting with a scheme)

See also HTTPURL

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.URL[string]

	// Valid URL
	value.MustParse("https://example.com")
	val, exists := value.Get()
	fmt.Printf("Value: %s, Exists: %t\n", val, exists)

	// Relative URLs are valid too
	value.MustParse("/relative/path")
	val, exists = value.Get()
	fmt.Printf("Relative URL: %s, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid URLs will fail validation
	var invalidValue optional.URL[string]
	err := invalidValue.Parse("htt ps://com example")
	fmt.Printf("Invalid URL error: %t\n", err != nil)

}
Output:

Value: https://example.com, Exists: true
Relative URL: /relative/path, Exists: true
After nil: Exists: false
Invalid URL error: true

type UUID

type UUID[T constraint.Text] struct {
	Custom[T, validate.UUID[T]]
}

UUID accepts a properly formatted UUID in one of the following formats:

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	var value optional.UUID[string]

	// Valid UUID
	value.MustParse("550e8400-e29b-41d4-a716-446655440000")
	_, exists := value.Get()
	fmt.Printf("Value exists: %t\n", exists)

	// Empty optional is valid
	value.MustParse(nil)
	_, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Invalid UUIDs will fail validation
	var invalidValue optional.UUID[string]
	err := invalidValue.Parse("not-a-uuid")
	fmt.Printf("Invalid UUID error: %t\n", err != nil)

}
Output:

Value exists: true
After nil: Exists: false
Invalid UUID error: true

type Unique

type Unique[S ~[]T, T comparable] struct {
	Custom[S, validate.Unique[S, T]]
}

Unique accepts a slice-like of unique values

See UniqueSlice for a slice shortcut

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	// Unique with a slice type
	var value optional.Unique[[]int, int]
	value.MustParse([]int{1, 2, 3, 4, 5})
	val, exists := value.Get()
	fmt.Printf("Value: %v, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Duplicate values will fail validation
	var invalidValue optional.Unique[[]int, int]
	err := invalidValue.Parse([]int{1, 2, 3, 1, 4})
	fmt.Printf("Duplicate value error: %t\n", err != nil)

}
Output:

Value: [1 2 3 4 5], Exists: true
After nil: Exists: false
Duplicate value error: true

type UniqueSlice

type UniqueSlice[T comparable] struct {
	Custom[[]T, validate.UniqueSlice[T]]
}

Unique accepts a slice of unique values

See Unique for a more generic version

Example
package main

import (
	"fmt"

	"github.com/metafates/schema/optional"
)

func main() {
	// UniqueSlice is a simplified version of Unique
	var value optional.UniqueSlice[string]
	value.MustParse([]string{"apple", "banana", "cherry"})
	val, exists := value.Get()
	fmt.Printf("Value: %v, Exists: %t\n", val, exists)

	// Empty optional is valid
	value.MustParse(nil)
	val, exists = value.Get()
	fmt.Printf("After nil: Exists: %t\n", exists)

	// Duplicate values will fail validation
	var invalidValue optional.UniqueSlice[string]
	err := invalidValue.Parse([]string{"apple", "banana", "apple"})
	fmt.Printf("Duplicate value error: %t\n", err != nil)

}
Output:

Value: [apple banana cherry], Exists: true
After nil: Exists: false
Duplicate value error: true

Jump to

Keyboard shortcuts

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