Skip to content

Commit 58d4ec6

Browse files
Fix panic when the decoding pointer type with custom decoding function
1 parent 8785d3c commit 58d4ec6

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

.gitignore

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,18 @@ _testmain.go
2525
old.txt
2626
new.txt
2727

28-
/.idea
28+
/.idea# Devenv
29+
.devenv*
30+
devenv.local.nix
31+
32+
# direnv
33+
.direnv
34+
35+
# pre-commit
36+
.pre-commit-config.yaml
37+
38+
# devenv nix files
39+
devenv.nix
40+
devenv.yaml
41+
devenv.lock
42+
.envrc

decoder.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,15 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
193193
return
194194
}
195195

196-
v.Set(reflect.ValueOf(val))
196+
if kind == reflect.Ptr {
197+
newVal := reflect.New(v.Type().Elem())
198+
if set = d.setFieldByType(newVal.Elem(), namespace, idx); set {
199+
v.Set(newVal)
200+
}
201+
} else {
202+
v.Set(reflect.ValueOf(val))
203+
}
204+
197205
set = true
198206
return
199207
}

decoder_test.go

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -830,28 +830,71 @@ func TestDecoderStruct(t *testing.T) {
830830

831831
func TestDecoderNativeTime(t *testing.T) {
832832

833+
type TType time.Time
834+
type TTypePtr *time.Time
835+
type TTypePtrWithCustomDecoder *time.Time
836+
833837
type TestError struct {
834-
Time time.Time
835-
TimeNoValue time.Time
836-
TimePtr *time.Time
838+
Time time.Time
839+
TimeNoValue time.Time
840+
TimePtr *time.Time
841+
TimeType TType
842+
TimeTypeNoValue TType
843+
TimeTypePtr TTypePtr
844+
TimeTypePtrNoValue TTypePtr
845+
TimeTypePtrWithCustomDecoder TTypePtrWithCustomDecoder
846+
TimeTypePtrWithCustomDecoderNoValue TTypePtrWithCustomDecoder
837847
}
838848

839849
values := url.Values{
840-
"Time": []string{"2006-01-02T15:04:05Z"},
841-
"TimeNoValue": []string{""},
842-
"TimePtr": []string{"2006-01-02T15:04:05Z"},
850+
"Time": []string{"2006-01-02T15:04:05Z"},
851+
"TimeNoValue": []string{""},
852+
"TimePtr": []string{"2006-01-02T15:04:05Z"},
853+
"TimeType": []string{"2006-01-02T15:04:05Z"},
854+
"TimeTypeNoValue": []string{""},
855+
"TimeTypePtr": []string{"2006-01-02T15:04:05Z"},
856+
"TimeTypePtrNoValue": []string{""},
857+
"TimeTypePtrWithCustomDecoder": []string{"2006-01-02T15:04:05Z"},
858+
"TimeTypePtrWithCustomDecoderNoValue": []string{""},
843859
}
844860

845861
var test TestError
846862

847863
decoder := NewDecoder()
864+
decoder.RegisterCustomTypeFunc(func(s []string) (interface{}, error) {
865+
if s[0] == "" {
866+
return TType{}, nil
867+
}
868+
parsed, err := time.Parse(time.RFC3339, s[0])
869+
if err != nil {
870+
return nil, err
871+
}
872+
return TType(parsed), nil
873+
}, TType{})
874+
decoder.RegisterCustomTypeFunc(func(s []string) (interface{}, error) {
875+
if s[0] == "" {
876+
return nil, nil
877+
}
878+
parsed, err := time.Parse(time.RFC3339, s[0])
879+
if err != nil {
880+
return nil, err
881+
}
882+
return TTypePtrWithCustomDecoder(&parsed), nil
883+
}, TTypePtrWithCustomDecoder(nil))
848884

849885
errs := decoder.Decode(&test, values)
850886
Equal(t, errs, nil)
851887

852888
tm, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
853889
Equal(t, test.Time.Equal(tm), true)
854890
Equal(t, test.TimeNoValue.Equal(tm), false)
891+
Equal(t, tm.Equal(time.Time(test.TimeType)), true)
892+
Equal(t, time.Time(test.TimeTypeNoValue).Equal(tm), false)
893+
Equal(t, time.Time(test.TimeTypeNoValue).IsZero(), true)
894+
Equal(t, (*time.Time)(test.TimeTypePtr).Equal(tm), true)
895+
Equal(t, test.TimeTypePtrNoValue, nil)
896+
Equal(t, (*time.Time)(test.TimeTypePtrWithCustomDecoder).Equal(tm), true)
897+
Equal(t, test.TimeTypePtrWithCustomDecoderNoValue, nil)
855898

856899
NotEqual(t, test.TimePtr, nil)
857900
Equal(t, (*test.TimePtr).Equal(tm), true)

0 commit comments

Comments
 (0)