Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #183 from camdencheek/master
Browse files Browse the repository at this point in the history
Add a value hook func
  • Loading branch information
mitchellh authored Nov 26, 2020
2 parents 07998cf + decea91 commit fcb781b
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 91 deletions.
47 changes: 31 additions & 16 deletions decode_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
// Create variables here so we can reference them with the reflect pkg
var f1 DecodeHookFuncType
var f2 DecodeHookFuncKind
var f3 DecodeHookFuncValue

// Fill in the variables into this interface and the rest is done
// automatically using the reflect package.
potential := []interface{}{f1, f2}
potential := []interface{}{f1, f2, f3}

v := reflect.ValueOf(h)
vt := v.Type()
Expand All @@ -38,13 +39,15 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
// that took reflect.Kind instead of reflect.Type.
func DecodeHookExec(
raw DecodeHookFunc,
from reflect.Type, to reflect.Type,
data interface{}) (interface{}, error) {
from reflect.Value, to reflect.Value) (interface{}, error) {

switch f := typedDecodeHook(raw).(type) {
case DecodeHookFuncType:
return f(from, to, data)
return f(from.Type(), to.Type(), from.Interface())
case DecodeHookFuncKind:
return f(from.Kind(), to.Kind(), data)
return f(from.Kind(), to.Kind(), from.Interface())
case DecodeHookFuncValue:
return f(from, to)
default:
return nil, errors.New("invalid decode hook signature")
}
Expand All @@ -56,22 +59,16 @@ func DecodeHookExec(
// The composed funcs are called in order, with the result of the
// previous transformation.
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{}) (interface{}, error) {
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
var err error
var data interface{}
newFrom := f
for _, f1 := range fs {
data, err = DecodeHookExec(f1, f, t, data)
data, err = DecodeHookExec(f1, newFrom, t)
if err != nil {
return nil, err
}

// Modify the from kind to be correct with the new data
f = nil
if val := reflect.ValueOf(data); val.IsValid() {
f = val.Type()
}
newFrom = reflect.ValueOf(data)
}

return data, nil
Expand Down Expand Up @@ -215,3 +212,21 @@ func WeaklyTypedHook(

return data, nil
}

func RecursiveStructToMapHookFunc() DecodeHookFunc {
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
if f.Kind() != reflect.Struct {
return f.Interface(), nil
}

var i interface{} = struct{}{}
if t.Type() != reflect.TypeOf(&i).Elem() {
return f.Interface(), nil
}

m := make(map[string]interface{})
t.Set(reflect.ValueOf(m))

return f.Interface(), nil
}
}
Loading

0 comments on commit fcb781b

Please sign in to comment.