Skip to content

Commit

Permalink
hanlde custom types / types aliases during unpack
Browse files Browse the repository at this point in the history
  • Loading branch information
moukoublen committed Apr 23, 2024
1 parent 5edd2c2 commit 447e2b2
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
74 changes: 74 additions & 0 deletions unpack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type stUnpackable struct {
Expand Down Expand Up @@ -237,3 +238,76 @@ func TestReifyUnpackersPtr(t *testing.T) {
assertSubConfig(to.C.c)
assertSubConfig(to.R.c)
}

func TestUnpack(t *testing.T) {
type CustomString string
type StructWithCustomString struct {
Foo CustomString `config:"foo"`
}
type StructWithCustomStringPtr struct {
Foo *CustomString `config:"foo"`
}

type StructWithString struct {
Foo string `config:"foo"`
}
type StructWithStringPtr struct {
Foo *string `config:"foo"`
}

strPtr := func(s string) *string { return &s }
customStrPtr := func(s CustomString) *CustomString { return &s }

tests := map[string]struct {
config func() *Config
unpackTo interface{}
expect interface{}
}{
"string to string": {
config: func() *Config {
return MustNewFrom(map[string]interface{}{
"foo": "bar",
})
},
unpackTo: &StructWithString{},
expect: &StructWithString{Foo: "bar"},
},
"string to *string": {
config: func() *Config {
return MustNewFrom(map[string]interface{}{
"foo": "bar",
})
},
unpackTo: &StructWithStringPtr{},
expect: &StructWithStringPtr{Foo: strPtr("bar")},
},
"string to CustomString": {
config: func() *Config {
return MustNewFrom(map[string]interface{}{
"foo": "bar",
})
},
unpackTo: &StructWithCustomString{},
expect: &StructWithCustomString{Foo: "bar"},
},
"string to *CustomString": {
config: func() *Config {
return MustNewFrom(map[string]interface{}{
"foo": "bar",
})
},
unpackTo: &StructWithCustomStringPtr{},
expect: &StructWithCustomStringPtr{Foo: customStrPtr("bar")},
},
}

for name, tc := range tests {
tc := tc
t.Run(name, func(t *testing.T) {
config := tc.config()
err := config.Unpack(tc.unpackTo)
require.NoError(t, err)
require.Equal(t, tc.expect, tc.unpackTo)
})
}
}
7 changes: 6 additions & 1 deletion util.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,12 @@ func pointerize(t, base reflect.Type, v reflect.Value) reflect.Value {
}

for t != v.Type() {
if !v.CanAddr() {
// if kinds are the same and the type not,
// then we might have custom type / type alias,
// so we can check if we can convert.
if t.Kind() == v.Kind() && v.CanConvert(t) {
v = v.Convert(t)
} else if !v.CanAddr() {
tmp := reflect.New(v.Type())
tmp.Elem().Set(v)
v = tmp
Expand Down

0 comments on commit 447e2b2

Please sign in to comment.