Home

ffcue @3e3e4f232e75ebca8b1af4c5ada9b2730acd5e41 - refs - log -
-
https://git.jolheiser.com/ffcue.git
ffcue / schema.go
- raw -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package ffcue

import (
	"fmt"
	"strings"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/cuecontext"
	"cuelang.org/go/cue/errors"
)

// Schema is a CUE schema file
type Schema string

// Unmarshal validates data against a [Schema] and decodes it into v, returning any validation errors
func (s Schema) Unmarshal(data []byte, v any) error {
	ctx := cuecontext.New()

	constraints := ctx.CompileString(string(s), cue.Filename("constraints.cue"))
	if constraints.Err() != nil {
		return fmt.Errorf("invalid schema: %w", constraints.Err())
	}

	config := ctx.CompileBytes(data, cue.Filename("config.cue"))
	if config.Err() != nil {
		return fmt.Errorf("invalid config: %w", config.Err())
	}

	unified := constraints.Unify(config)
	if unified.Err() != nil {
		err := unified.Validate(cue.Concrete(true))
		var errs []string
		for _, e := range errors.Errors(err) {
			errs = append(errs, e.Error())
		}
		return fmt.Errorf("config failed validation with %d errors:\n%s", len(errs), strings.Join(errs, "\n"))
	}

	if err := unified.Decode(&v); err != nil {
		return fmt.Errorf("could not decode unified config: %w", err)
	}

	return nil
}