Skip to content

Commit b25fc05

Browse files
committed
cue: support decoding into cue.Value fields
Fixes #2029. Signed-off-by: Roger Peppe <[email protected]> Change-Id: Ibe178f5428b2e97b04a1af9d9d9b631fea0a604c Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/547369 TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]> Reviewed-by: Daniel Martí <[email protected]>
1 parent 4e30101 commit b25fc05

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

cue/decode.go

+10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ import (
3434
// An error is returned if x is nil or not a pointer.
3535
//
3636
// If x is a struct, Decode will validate the constraints specified in the field tags.
37+
//
38+
// If x contains a [Value], that part of x will be set to the value
39+
// at the corresponding part of v. This allows decoding values
40+
// that aren't entirely concrete into a Go type.
3741
func (v Value) Decode(x interface{}) error {
3842
var d decoder
3943
w := reflect.ValueOf(x)
@@ -71,6 +75,8 @@ func (d *decoder) clear(x reflect.Value) {
7175
}
7276
}
7377

78+
var valueType = reflect.TypeOf(Value{})
79+
7480
func (d *decoder) decode(x reflect.Value, v Value, isPtr bool) {
7581
if !x.IsValid() {
7682
d.addErr(errors.Newf(v.Pos(), "cannot decode into invalid value"))
@@ -87,6 +93,10 @@ func (d *decoder) decode(x reflect.Value, v Value, isPtr bool) {
8793
d.addErr(err)
8894
return
8995
}
96+
if x.Type() == valueType {
97+
x.Set(reflect.ValueOf(v))
98+
return
99+
}
90100

91101
switch x.Kind() {
92102
case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface:

cue/decode_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
package cue
1616

1717
import (
18+
"fmt"
1819
"reflect"
1920
"testing"
2021
"time"
2122

23+
"github.com/go-quicktest/qt"
2224
"github.com/google/go-cmp/cmp"
2325
)
2426

@@ -250,6 +252,25 @@ func TestDecode(t *testing.T) {
250252
}
251253
}
252254

255+
func TestDecodeIntoCUEValue(t *testing.T) {
256+
// We should be able to decode into a CUE value so we can
257+
// decode partially incomplete values into Go.
258+
// This test doesn't fit within the table used by TestDecode
259+
// because cue values aren't easily comparable with cmp.Diff.
260+
var st struct {
261+
X Value `json:"x"`
262+
}
263+
err := getInstance(t, `x: string`).Value().Decode(&st)
264+
qt.Assert(t, qt.IsNil(err))
265+
qt.Assert(t, qt.Equals(fmt.Sprint(st.X), "string"))
266+
267+
// Check we can decode into a top level value.
268+
var v Value
269+
err = getInstance(t, `int`).Value().Decode(&v)
270+
qt.Assert(t, qt.IsNil(err))
271+
qt.Assert(t, qt.Equals(fmt.Sprint(v), "int"))
272+
}
273+
253274
type Duration struct {
254275
D time.Duration
255276
}

0 commit comments

Comments
 (0)