go: cuelang.org/go/cuego Index | Examples | Files

package cuego

import "cuelang.org/go/cuego"

Package cuego allows using CUE constraints in Go programs.

CUE constraints can be used to validate Go types as well as fill out missing struct fields that are implied from the constraints and the values already defined by the struct value.

CUE constraints can be added through field tags or by associating CUE code with a Go type. The field tags method follows the usual Go pattern:

type Sum struct {
    A int `cue:"C-B" json:",omitempty"`
    B int `cue:"C-A" json:",omitempty"`
    C int `cue:"A+B" json:",omitempty"`
}

func main() {
    fmt.Println(cuego.Validate(&Sum{A: 1, B: 5, C: 7}))
}

AddConstraints allows annotating Go types with any CUE constraints.

Validating Go Values

To check whether a struct's values satisfy its constraints, call Validate:

if err := cuego.Validate(p); err != nil {
   return err
}

Validation assumes that all values are filled in correctly and will not infer values. To automatically infer values, use Complete.

Completing Go Values

Package cuego can also be used to infer undefined values from a set of CUE constraints, for instance to fill out fields in a struct. A value is considered undefined if it is a nil pointer type or if it is a zero value and there is a JSON field tag with the omitempty flag. A Complete will implicitly validate a struct.

Index

Examples

Package Files

cuego.go doc.go

Variables

var DefaultContext = &Context{}

DefaultContext is the shared context used with top-level functions.

func Complete Uses

func Complete(x interface{}) error

Complete sets previously undefined values in x that can be uniquely determined form the constraints defined on the type of x such that validation passes, or returns an error, without modifying anything, if this is not possible.

Complete does a JSON round trip. This means that data not preserved in such a round trip, such as the location name of a time.Time, is lost after a successful update.

Code:

type Sum struct {
    A   int `cue:"C-B" json:",omitempty"`
    B   int `cue:"C-A" json:",omitempty"`
    C   int `cue:"A+B" json:",omitempty"`
}

a := Sum{A: 1, B: 5}
err := cuego.Complete(&a)
fmt.Printf("completed: %#v (err: %v)\n", a, err)

a = Sum{A: 2, C: 8}
err = cuego.Complete(&a)
fmt.Printf("completed: %#v (err: %v)\n", a, err)

a = Sum{A: 2, B: 3, C: 8}
err = cuego.Complete(&a)
fmt.Println(err)

Output:

completed: cuego_test.Sum{A:1, B:5, C:6} (err: <nil>)
completed: cuego_test.Sum{A:2, B:6, C:8} (err: <nil>)
empty disjunction: invalid operation null & {A: 2, B: 3, C: 8} (mismatched types null and struct)

func Constrain Uses

func Constrain(x interface{}, constraints string) error

Constrain associates the given CUE constraints with the type of x or reports an error if the constraints are invalid or not compatible with x.

Constrain works across package boundaries and is typically called in the package defining the type. Use a Context to apply constraints locally.

Code:

type Config struct {
    Filename string
    OptFile  string `json:",omitempty"`
    MaxCount int
    MinCount int

    // TODO: show a field with time.Time
}

err := cuego.Constrain(&Config{}, `{
		jsonFile = =~".json$"

		// Filename must be defined and have a .json extension
		Filename: jsonFile

		// OptFile must be undefined or be a file name with a .json extension
		OptFile?: jsonFile

		MinCount: >0 & <=MaxCount
		MaxCount: <=10_000
	}`)

fmt.Println("error:", err)

fmt.Println("validate:", cuego.Validate(&Config{
    Filename: "foo.json",
    MaxCount: 1200,
    MinCount: 39,
}))

fmt.Println("validate:", cuego.Validate(&Config{
    Filename: "foo.json",
    MaxCount: 12,
    MinCount: 39,
}))

fmt.Println("validate:", cuego.Validate(&Config{
    Filename: "foo.jso",
    MaxCount: 120,
    MinCount: 39,
}))

Output:

error: <nil>
validate: <nil>
validate: invalid value 39 (out of bound <=12)
validate: invalid value "foo.jso" (does not match =~".json$")

func MustConstrain Uses

func MustConstrain(x interface{}, constraints string)

MustConstrain is like Constrain, but panics if there is an error.

func Validate Uses

func Validate(x interface{}) error

Validate is a wrapper for Validate called on the global context.

type Context Uses

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

A Context holds type constraints that are only applied within a given context. Global constraints that are defined at the time a constraint is created are applied as well.

func (*Context) Complete Uses

func (c *Context) Complete(x interface{}) error

Complete sets previously undefined values in x that can be uniquely determined form the constraints defined on the type of x such that validation passes, or returns an error, without modifying anything, if this is not possible.

A value is considered undefined if it is pointer type and is nil or if it is a field with a zero value and a json tag with the omitempty tag. Complete does a JSON round trip. This means that data not preserved in such a round trip, such as the location name of a time.Time, is lost after a successful update.

func (*Context) Constrain Uses

func (c *Context) Constrain(x interface{}, constraints string) error

Constrain associates the given CUE constraints with the type of x or reports an error if the constraints are invalid or not compatible with x.

func (*Context) Validate Uses

func (c *Context) Validate(x interface{}) error

Validate checks whether x validates against the registered constraints for the type of x.

Constraints for x can be defined as field tags or through the Register function.

Package cuego imports 6 packages (graph). Updated 2019-12-11. Refresh now. Tools for package owners.