Skip to content
This repository has been archived by the owner on Jan 20, 2023. It is now read-only.

Commit

Permalink
Allow to set nil
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay Turpitko committed Jun 19, 2017
1 parent e8c0e13 commit 6232b75
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 6 deletions.
4 changes: 3 additions & 1 deletion el/el.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ func (i *DefaultInterpreter) Execute(
funcs[k] = v
}
var res interface{}
resultEvaluated := false
funcs["set"] = func(r interface{}) interface{} {
res = r
resultEvaluated = true
return r
}
funcs["eval"] = func(intrpr, expr string) (interface{}, error) {
Expand Down Expand Up @@ -135,7 +137,7 @@ func (i *DefaultInterpreter) Execute(
if err != nil {
return nil, err
}
if res != nil {
if resultEvaluated {
return res, nil
}
return buf.String(), nil
Expand Down
13 changes: 9 additions & 4 deletions structor.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func (ev evaluator) eval(s, extra, substruct, subctx interface{}) error {
if err != nil {
return err
}
err = reflectSet(f.value, result)
err = reflectSet(f.value, f.typ, result)
if err == nil {
return nil
}
Expand Down Expand Up @@ -174,6 +174,7 @@ type fieldDescr struct {
expr string
interpreter el.Interpreter
value reflect.Value
typ reflect.Type
tags map[string]string
}

Expand All @@ -187,6 +188,7 @@ func (ev evaluator) fieldIntrospect(
res := fieldDescr{
name: f.Name,
value: v,
typ: f.Type,
tags: tags,
}
if err != nil {
Expand Down Expand Up @@ -215,7 +217,7 @@ func (ev evaluator) fieldIntrospect(

var errTryRecursive = errors.New("try recursive") // sentinel error

func reflectSet(v reflect.Value, nv interface{}) (err error) {
func reflectSet(v reflect.Value, vt reflect.Type, nv interface{}) (err error) {
defer func() {
if r := recover(); r != nil {
var ok bool
Expand All @@ -224,14 +226,17 @@ func reflectSet(v reflect.Value, nv interface{}) (err error) {
}
}
}()
if nv == nil {
v.Set(reflect.Zero(vt))
return nil
}
vnv := reflect.ValueOf(nv)
vt := v.Type()
if !vnv.Type().ConvertibleTo(vt) &&
v.Kind() == reflect.Struct {
// Try to recursively eval tags on inner struct.
return errTryRecursive
}
// Try to convert, in worst case it'll give a panic with suitable message.
// Try to convert, it may give a panic with suitable message.
v.Set(vnv.Convert(vt))
return nil
}
Expand Down
8 changes: 7 additions & 1 deletion structor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestSimple(t *testing.T) {
D string `eval:"{{.Struct.C}}"`
E string `eval:"eee"`
F string `eval:"{{.Struct.E}} + {{.Extra.X}}"`
G string `eval:""`
}
v := &simple{
A: "init A",
Expand Down Expand Up @@ -57,6 +58,7 @@ func TestSimple(t *testing.T) {
assert.Equal(t, "extra field X", v.D)
assert.Equal(t, "eee", v.E)
assert.Equal(t, "eee + extra field X", v.F)
assert.Equal(t, "", v.G)
}

// TestObj tests structor usage with non-string fields, type conversion,
Expand All @@ -83,8 +85,10 @@ func TestObj(t *testing.T) {
J string `eval:"jjj"`
}
K inner
N interface{} `eval:"{{set nil}}"`
P string `eval:{{or .Val "second"}}`
}
v := &obj{F: &innerSub{}}
v := &obj{F: &innerSub{}, N: "xxx", P: "first"}
ev := structor.NewDefaultEvaluator(use.Packages(
use.Pkg{Prefix: "", Funcs: math.Pkg},
use.Pkg{Prefix: "", Funcs: encoding.Pkg},
Expand All @@ -103,6 +107,8 @@ func TestObj(t *testing.T) {
assert.Equal(t, "\n", v.H)
assert.Equal(t, "jjj", v.I.J)
assert.Equal(t, "LLL", v.K.L)
assert.Nil(t, v.N)
assert.Equal(t, "first", v.P)
}

// TestError tests structor's error handling.
Expand Down

0 comments on commit 6232b75

Please sign in to comment.