Skip to content

Commit

Permalink
internal/encoding/yaml: use adt.Unify instead of Value.Unify
Browse files Browse the repository at this point in the history
This change should by itself be a no-op, as we
still need to pass cycle information through to
the respective OpContexts. This will be done in
a followup CL. We include these changes in a
separate CL, though, to be able to isolate any
issues that may arise from this change.

Issue #3649

Signed-off-by: Marcel van Lohuizen <[email protected]>
Change-Id: I2915f5d0e54fbd07bf20093e3da4a0ce4ae30cbc
Dispatch-Trailer: {"type":"trybot","CL":1208700,"patchset":2,"ref":"refs/changes/00/1208700/2","targetBranch":"master"}
  • Loading branch information
mpvl authored and cueckoo committed Feb 13, 2025
1 parent 6f6ff9b commit dcaa1bd
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 8 deletions.
4 changes: 3 additions & 1 deletion encoding/yaml/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"cuelang.org/go/cue/ast"
cueyaml "cuelang.org/go/internal/encoding/yaml"
"cuelang.org/go/internal/source"
"cuelang.org/go/internal/value"
)

// Extract parses the YAML specified by src to a CUE expression. If
Expand Down Expand Up @@ -96,6 +97,7 @@ func EncodeStream(iter cue.Iterator) ([]byte, error) {
// Validate validates the YAML and confirms it matches the constraints
// specified by v. For YAML streams, all values must match v.
func Validate(b []byte, v cue.Value) error {
_, err := cueyaml.Validate(b, v)
ctx := value.OpContext(v)
_, err := cueyaml.Validate(ctx, b, v)
return err
}
20 changes: 15 additions & 5 deletions internal/encoding/yaml/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ import (
"io"

"cuelang.org/go/cue"
"cuelang.org/go/internal/core/adt"
"cuelang.org/go/internal/pkg"
"cuelang.org/go/internal/value"
)

// Validate validates YAML and confirms it is an instance of schema.
// If the YAML source is a stream, every object must match v.
func Validate(b []byte, v cue.Value) (bool, error) {
//
// If Validate is called in a broader context, like a validation or function
// call, the cycle context of n should be accumulated in c before this call.
// This can be done by using the Expr method on the CallContext.
func Validate(c *adt.OpContext, b []byte, v cue.Value) (bool, error) {
d := NewDecoder("yaml.Validate", b)
r := v.Context()
for {
Expand All @@ -50,10 +56,12 @@ func Validate(b []byte, v cue.Value) (bool, error) {
// if err := v.Subsume(inst.Value(), cue.Final()); err != nil {
// return false, err
// }
x = v.Unify(x)
vx := adt.Unify(c, value.Vertex(x), value.Vertex(v))
if err := x.Err(); err != nil {
return false, err
}
x = value.Make(c, vx)

if err := x.Validate(cue.Concrete(true)); err != nil {
// Strip error codes: incomplete errors are terminal in this case.
var b pkg.Bottomer
Expand All @@ -69,7 +77,7 @@ func Validate(b []byte, v cue.Value) (bool, error) {
// specified by v using unification. This means that b must be consistent with,
// but does not have to be an instance of v. If the YAML source is a stream,
// every object must match v.
func ValidatePartial(b []byte, v cue.Value) (bool, error) {
func ValidatePartial(c *adt.OpContext, b []byte, v cue.Value) (bool, error) {
d := NewDecoder("yaml.ValidatePartial", b)
r := v.Context()
for {
Expand All @@ -86,8 +94,10 @@ func ValidatePartial(b []byte, v cue.Value) (bool, error) {
return false, err
}

if x := v.Unify(x); x.Err() != nil {
return false, x.Err()
vx := adt.Unify(c, value.Vertex(x), value.Vertex(v))
x = value.Make(c, vx)
if err := x.Err(); err != nil {
return false, err
}
}
}
24 changes: 24 additions & 0 deletions internal/value/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,36 @@ func Context[Ctx *cue.Runtime | *cue.Context | cue.Value | *adt.OpContext](ctx C
panic("unreachable")
}

// OpContext returns an OpContext with proper node formatting initialized.
func OpContext[Ctx *cue.Runtime | *cue.Context | cue.Value](c Ctx) *adt.OpContext {
var r *runtime.Runtime
var v *adt.Vertex
switch x := any(c).(type) {
case *cue.Runtime:
r = (*runtime.Runtime)(x)
r.Init()
case *cue.Context:
r = (*runtime.Runtime)(x)
case cue.Value:
r, v = ToInternal(x)
default:
panic("unreachable")
}
return eval.NewContext(r, v)
}

func ToInternal(v cue.Value) (*runtime.Runtime, *adt.Vertex) {
var t types.Value
v.Core(&t)
return t.R, t.V
}

func Vertex(v cue.Value) *adt.Vertex {
var t types.Value
v.Core(&t)
return t.V
}

// Make wraps cue.MakeValue.
func Make(ctx *adt.OpContext, v adt.Value) cue.Value {
return Context(ctx).Encode(v)
Expand Down
7 changes: 5 additions & 2 deletions pkg/encoding/yaml/manual.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"cuelang.org/go/cue/ast"
cueyaml "cuelang.org/go/internal/encoding/yaml"
"cuelang.org/go/internal/pkg"
"cuelang.org/go/internal/value"
)

// Marshal returns the YAML encoding of v.
Expand Down Expand Up @@ -86,13 +87,15 @@ func UnmarshalStream(data []byte) (ast.Expr, error) {
// Validate validates YAML and confirms it is an instance of schema.
// If the YAML source is a stream, every object must match v.
func Validate(b []byte, v pkg.Schema) (bool, error) {
return cueyaml.Validate(b, v)
ctx := value.OpContext(v)
return cueyaml.Validate(ctx, b, v)
}

// ValidatePartial validates YAML and confirms it matches the constraints
// specified by v using unification. This means that b must be consistent with,
// but does not have to be an instance of v. If the YAML source is a stream,
// every object must match v.
func ValidatePartial(b []byte, v pkg.Schema) (bool, error) {
return cueyaml.ValidatePartial(b, v)
ctx := value.OpContext(v)
return cueyaml.ValidatePartial(ctx, b, v)
}

0 comments on commit dcaa1bd

Please sign in to comment.