Skip to content

Commit

Permalink
cue: simplify the reflect checks in Value.Decode
Browse files Browse the repository at this point in the history
reflect.Value.CanSet is documented as:

    A Value can be changed only if it is addressable and was not
    obtained by the use of unexported struct fields.

We call reflect.ValueOf ourselves here, so we cannot have reached for an
unexported struct field via reflect.Value.Field.
The only other requirement is that the value must be addressable,
which can only be met if x was a non-nil pointer that we dereferenced.

This was already the expectation that Decode had on x;
it just wasn't documented very clearly, but now it is.
We can then replace the CanSet check with a check for a non-nil pointer,
which exactly matches the logic from APIs like encoding/json.Unmarshal.

Signed-off-by: Daniel Martí <[email protected]>
Change-Id: I919026530c683a2c9b10f1484910f9cb66fee861
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1168928
Unity-Result: CUE porcuepine <[email protected]>
Reviewed-by: Roger Peppe <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
  • Loading branch information
mvdan committed Sep 14, 2023
1 parent b8cb9a4 commit 8709d8a
Showing 1 changed file with 7 additions and 10 deletions.
17 changes: 7 additions & 10 deletions cue/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,18 @@ import (
"cuelang.org/go/internal/core/adt"
)

// Decode initializes x with Value v. If x is a struct, it will validate the
// constraints specified in the field tags.
// Decode initializes the value pointed to by x with Value v.
// An error is returned if x is nil or not a pointer.
//
// If x is a struct, Decode will validate the constraints specified in the field tags.
func (v Value) Decode(x interface{}) error {
var d decoder
w := reflect.ValueOf(x)
switch {
case !reflect.Indirect(w).CanSet():
if w.Kind() != reflect.Pointer || w.IsNil() {
d.addErr(errors.Newf(v.Pos(), "cannot decode into unsettable value"))

default:
if w.Kind() == reflect.Ptr {
w = w.Elem()
}
d.decode(w, v, false)
return d.errs
}
d.decode(w.Elem(), v, false)
return d.errs
}

Expand Down

0 comments on commit 8709d8a

Please sign in to comment.