Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
cue: move Decode to separate file
Browse files Browse the repository at this point in the history
This prepares for a complete rewrite.

Change-Id: I13126a97c5899d3492b296fc0bd9082d32f923f0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9521
Reviewed-by: CUE cueckoo <[email protected]>
Reviewed-by: Marcel van Lohuizen <[email protected]>
  • Loading branch information
mpvl committed Apr 28, 2021
1 parent f60c88a commit 3347302
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 90 deletions.
30 changes: 30 additions & 0 deletions cue/decode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2021 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cue

import (
"encoding/json"
)

// Decode initializes x with Value v. If x is a struct, it will validate the
// constraints specified in the field tags.
func (v Value) Decode(x interface{}) error {
// TODO: optimize
b, err := v.MarshalJSON()
if err != nil {
return err
}
return json.Unmarshal(b, x)
}
96 changes: 96 additions & 0 deletions cue/decode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2021 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cue

import (
"reflect"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestDecode(t *testing.T) {
type fields struct {
A int `json:"A"`
B int `json:"B"`
C int `json:"C"`
}
intList := func(ints ...int) *[]int {
ints = append([]int{}, ints...)
return &ints
}
testCases := []struct {
value string
dst interface{}
want interface{}
err string
}{{
value: `_|_`,
err: "explicit error (_|_ literal) in source",
}, {
value: `"str"`,
dst: new(string),
want: "str",
}, {
value: `"str"`,
dst: new(int),
err: "cannot unmarshal string into Go value of type int",
}, {
value: `{}`,
dst: &fields{},
want: fields{},
}, {
value: `{a:1,b:2,c:3}`,
dst: &fields{},
want: fields{A: 1, B: 2, C: 3},
}, {
value: `{for k, v in y if v > 1 {"\(k)": v} }
y: {a:1,b:2,c:3}`,
dst: &fields{},
want: fields{B: 2, C: 3},
}, {
value: `{a:1,b:2,c:int}`,
dst: new(fields),
err: "cannot convert incomplete value",
}, {
value: `[]`,
dst: intList(),
want: *intList(),
}, {
value: `[1,2,3]`,
dst: intList(),
want: *intList(1, 2, 3),
}, {
value: `[for x in #y if x > 1 { x }]
#y: [1,2,3]`,
dst: intList(),
want: *intList(2, 3),
}, {
value: `[int]`,
err: "cannot convert incomplete value",
}}
for _, tc := range testCases {
t.Run(tc.value, func(t *testing.T) {
err := getInstance(t, tc.value).Value().Decode(tc.dst)
checkFatal(t, err, tc.err, "init")

got := reflect.ValueOf(tc.dst).Elem().Interface()
if !cmp.Equal(got, tc.want) {
t.Error(cmp.Diff(got, tc.want))
t.Errorf("\n%#v\n%#v", got, tc.want)
}
})
}
}
16 changes: 0 additions & 16 deletions cue/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1016,22 +1016,6 @@ outer:
}
}

// Decode initializes x with Value v. If x is a struct, it will validate the
// constraints specified in the field tags.
func (v Value) Decode(x interface{}) error {
// TODO: optimize
b, err := v.MarshalJSON()
if err != nil {
return err
}
return json.Unmarshal(b, x)
}

// // EncodeJSON generates JSON for the given value.
// func (v Value) EncodeJSON(w io.Writer, v Value) error {
// return nil
// }

// Doc returns all documentation comments associated with the field from which
// the current value originates.
func (v Value) Doc() []*ast.CommentGroup {
Expand Down
74 changes: 0 additions & 74 deletions cue/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1976,80 +1976,6 @@ func TestEquals(t *testing.T) {
}
}

func TestDecode(t *testing.T) {
type fields struct {
A int `json:"A"`
B int `json:"B"`
C int `json:"C"`
}
intList := func(ints ...int) *[]int {
ints = append([]int{}, ints...)
return &ints
}
testCases := []struct {
value string
dst interface{}
want interface{}
err string
}{{
value: `_|_`,
err: "explicit error (_|_ literal) in source",
}, {
value: `"str"`,
dst: new(string),
want: "str",
}, {
value: `"str"`,
dst: new(int),
err: "cannot unmarshal string into Go value of type int",
}, {
value: `{}`,
dst: &fields{},
want: fields{},
}, {
value: `{a:1,b:2,c:3}`,
dst: &fields{},
want: fields{A: 1, B: 2, C: 3},
}, {
value: `{for k, v in y if v > 1 {"\(k)": v} }
y: {a:1,b:2,c:3}`,
dst: &fields{},
want: fields{B: 2, C: 3},
}, {
value: `{a:1,b:2,c:int}`,
dst: new(fields),
err: "cannot convert incomplete value",
}, {
value: `[]`,
dst: intList(),
want: *intList(),
}, {
value: `[1,2,3]`,
dst: intList(),
want: *intList(1, 2, 3),
}, {
value: `[for x in #y if x > 1 { x }]
#y: [1,2,3]`,
dst: intList(),
want: *intList(2, 3),
}, {
value: `[int]`,
err: "cannot convert incomplete value",
}}
for _, tc := range testCases {
t.Run(tc.value, func(t *testing.T) {
err := getInstance(t, tc.value).Value().Decode(tc.dst)
checkFatal(t, err, tc.err, "init")

got := reflect.ValueOf(tc.dst).Elem().Interface()
if !cmp.Equal(got, tc.want) {
t.Error(cmp.Diff(got, tc.want))
t.Errorf("\n%#v\n%#v", got, tc.want)
}
})
}
}

// TODO: options: disallow cycles.
func TestValidate(t *testing.T) {
testCases := []struct {
Expand Down

0 comments on commit 3347302

Please sign in to comment.