Skip to content

Commit 41cce52

Browse files
committed
pkg/encoding: add {yaml.json}.Validate
This allows creating types of embedded YAML and JSON text that most conform to the given CUE constraints. Change-Id: I74e07f2f110251bd9c48feafd82b0a969a8ee2c1 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2876 Reviewed-by: Marcel van Lohuizen <[email protected]>
1 parent d208ff1 commit 41cce52

File tree

7 files changed

+164
-1
lines changed

7 files changed

+164
-1
lines changed

cue/build.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,16 @@ type Runtime struct {
3737

3838
func init() {
3939
internal.GetRuntime = func(instance interface{}) interface{} {
40-
return &Runtime{idx: instance.(*Instance).index}
40+
switch x := instance.(type) {
41+
case Value:
42+
return &Runtime{idx: x.idx}
43+
44+
case *Instance:
45+
return &Runtime{idx: x.index}
46+
47+
default:
48+
panic("argument must be Value or *Instance")
49+
}
4150
}
4251

4352
internal.CheckAndForkRuntime = func(runtime, value interface{}) interface{} {

cue/builtin_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ func TestBuiltins(t *testing.T) {
7676
}, {
7777
test("encoding/hex", `hex.Decode("foo")`),
7878
`_|_(error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o')`,
79+
}, {
80+
test("encoding/json", `json.Validate("{\"a\":10}", {b:string})`),
81+
`true`,
82+
}, {
83+
test("encoding/json", `json.Validate("{\"a\":10}", {a:<3})`),
84+
`_|_(error in call to encoding/json.Validate: invalid value 10 (out of bound <3))`,
85+
}, {
86+
test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<3})`),
87+
`_|_(error in call to encoding/yaml.Validate: invalid value 4 (out of bound <3))`,
88+
}, {
89+
test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<5})`),
90+
`true`,
7991
}, {
8092
test("strconv", `strconv.FormatUint(64, 16)`),
8193
`"40"`,

cue/builtins.go

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

encoding/json/json.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2019 CUE Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package yaml converts JSON to and from CUE.
16+
package json
17+
18+
import (
19+
"cuelang.org/go/cue"
20+
"cuelang.org/go/pkg/encoding/json"
21+
)
22+
23+
// Validate validates JSON and confirms it matches the constraints
24+
// specified by v.
25+
func Validate(b []byte, v cue.Value) error {
26+
_, err := json.Validate(b, v)
27+
return err
28+
}

encoding/yaml/yaml.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"cuelang.org/go/cue"
2424
"cuelang.org/go/cue/ast"
2525
"cuelang.org/go/internal/third_party/yaml"
26+
pkgyaml "cuelang.org/go/pkg/encoding/yaml"
2627
goyaml "github.com/ghodss/yaml"
2728
)
2829

@@ -98,3 +99,10 @@ func EncodeStream(iter cue.Iterator) ([]byte, error) {
9899
}
99100
return buf.Bytes(), nil
100101
}
102+
103+
// Validate validates the YAML and confirms it matches the constraints
104+
// specified by v. For YAML streams, all values must match v.
105+
func Validate(b []byte, v cue.Value) error {
106+
_, err := pkgyaml.Validate(b, v)
107+
return err
108+
}

pkg/encoding/json/manual.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"cuelang.org/go/cue"
2323
"cuelang.org/go/cue/ast"
2424
"cuelang.org/go/cue/parser"
25+
"cuelang.org/go/internal"
2526
)
2627

2728
// Compact generates the JSON-encoded src with insignificant space characters
@@ -101,3 +102,22 @@ func Unmarshal(b []byte) (ast.Expr, error) {
101102
}
102103
return expr, nil
103104
}
105+
106+
// Validate validates JSON and confirms it matches the constraints
107+
// specified by v.
108+
func Validate(b []byte, v cue.Value) (bool, error) {
109+
if !json.Valid(b) {
110+
return false, fmt.Errorf("json: invalid JSON")
111+
}
112+
r := internal.GetRuntime(v).(*cue.Runtime)
113+
inst, err := r.Compile("json.Validate", b)
114+
if err != nil {
115+
return false, err
116+
}
117+
118+
v = v.Unify(inst.Value())
119+
if v.Err() != nil {
120+
return false, v.Err()
121+
}
122+
return true, nil
123+
}

pkg/encoding/yaml/manual.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ package yaml
1616

1717
import (
1818
"bytes"
19+
"io"
1920

2021
"cuelang.org/go/cue"
2122
"cuelang.org/go/cue/ast"
23+
"cuelang.org/go/internal"
2224
"cuelang.org/go/internal/third_party/yaml"
2325
goyaml "github.com/ghodss/yaml"
2426
)
@@ -54,3 +56,31 @@ func MarshalStream(v cue.Value) (string, error) {
5456
func Unmarshal(data []byte) (ast.Expr, error) {
5557
return yaml.Unmarshal("", data)
5658
}
59+
60+
// Validate validates YAML and confirms it matches the constraints
61+
// specified by v. If the YAML source is a stream, every object must match v.
62+
func Validate(b []byte, v cue.Value) (bool, error) {
63+
d, err := yaml.NewDecoder("yaml.Validate", b)
64+
if err != nil {
65+
return false, err
66+
}
67+
r := internal.GetRuntime(v).(*cue.Runtime)
68+
for {
69+
expr, err := d.Decode()
70+
if err != nil {
71+
if err == io.EOF {
72+
return true, nil
73+
}
74+
return false, err
75+
}
76+
77+
inst, err := r.CompileExpr(expr)
78+
if err != nil {
79+
return false, err
80+
}
81+
82+
if x := v.Unify(inst.Value()); x.Err() != nil {
83+
return false, x.Err()
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)