Skip to content

Commit 5b3ed79

Browse files
joeybloggsjoeybloggs
authored andcommitted
Remove panic and replace by returning InvalidDecodeError
for issue-#7
1 parent ae3bce1 commit 5b3ed79

File tree

2 files changed

+58
-8
lines changed

2 files changed

+58
-8
lines changed

decoder_test.go

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ func TestDecodeAllTypes(t *testing.T) {
11291129
Equal(t, phones[1].Label, "label2")
11301130
}
11311131

1132-
func TestDecoderPanics(t *testing.T) {
1132+
func TestDecoderPanicsAndBadValues(t *testing.T) {
11331133

11341134
type Phone struct {
11351135
Number string
@@ -1152,7 +1152,28 @@ func TestDecoderPanics(t *testing.T) {
11521152
PanicMatches(t, func() { decoder.Decode(&test, values) }, "Invalid formatting for key 'Phone[0.Number' missing ']' bracket")
11531153

11541154
i := 1
1155-
PanicMatches(t, func() { decoder.Decode(i, values) }, "interface must be a pointer")
1155+
err := decoder.Decode(i, values)
1156+
NotEqual(t, err, nil)
1157+
1158+
_, ok := err.(*InvalidDecoderError)
1159+
Equal(t, ok, true)
1160+
Equal(t, err.Error(), "form: Decode(non-pointer int)")
1161+
1162+
err = decoder.Decode(nil, values)
1163+
NotEqual(t, err, nil)
1164+
1165+
_, ok = err.(*InvalidDecoderError)
1166+
Equal(t, ok, true)
1167+
Equal(t, err.Error(), "form: Decode(nil)")
1168+
1169+
var ts *TestError
1170+
1171+
err = decoder.Decode(ts, values)
1172+
NotEqual(t, err, nil)
1173+
1174+
_, ok = err.(*InvalidDecoderError)
1175+
Equal(t, ok, true)
1176+
Equal(t, err.Error(), "form: Decode(nil *form.TestError)")
11561177

11571178
values = url.Values{
11581179
"Phone0].Number": []string{"1(111)111-1111"},
@@ -1357,7 +1378,12 @@ func TestDecoderInterface(t *testing.T) {
13571378

13581379
iface = i
13591380

1360-
PanicMatches(t, func() { d.Decode(iface, values) }, "interface must be a pointer")
1381+
err = d.Decode(iface, values)
1382+
NotEqual(t, err, nil)
1383+
1384+
_, ok := err.(*InvalidDecoderError)
1385+
Equal(t, ok, true)
1386+
Equal(t, err.Error(), "form: Decode(non-pointer int)")
13611387

13621388
values = map[string][]string{
13631389
"Value": {"testVal"},
@@ -1377,5 +1403,10 @@ func TestDecoderInterface(t *testing.T) {
13771403

13781404
iface = tst
13791405

1380-
PanicMatches(t, func() { d.Decode(iface, values) }, "interface must be a pointer")
1406+
err = d.Decode(iface, values)
1407+
NotEqual(t, err, nil)
1408+
1409+
_, ok = err.(*InvalidDecoderError)
1410+
Equal(t, ok, true)
1411+
Equal(t, err.Error(), "form: Decode(non-pointer form.test)")
13811412
}

form_decoder.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@ func (d DecodeErrors) Error() string {
2828
return strings.TrimSpace(buff.String())
2929
}
3030

31+
// An InvalidDecoderError describes an invalid argument passed to Decode.
32+
// (The argument passed to Decode must be a non-nil pointer.)
33+
type InvalidDecoderError struct {
34+
Type reflect.Type
35+
}
36+
37+
func (e *InvalidDecoderError) Error() string {
38+
if e.Type == nil {
39+
return "form: Decode(nil)"
40+
}
41+
42+
if e.Type.Kind() != reflect.Ptr {
43+
return "form: Decode(non-pointer " + e.Type.String() + ")"
44+
}
45+
return "form: Decode(nil " + e.Type.String() + ")"
46+
}
47+
3148
type key struct {
3249
ivalue int
3350
value string
@@ -92,7 +109,9 @@ func (d *Decoder) RegisterCustomTypeFunc(fn DecodeCustomTypeFunc, types ...inter
92109
}
93110
}
94111

95-
// Decode decodes the given values and sets the corresponding struct values
112+
// Decode parses the given values and sets the corresponding struct and/or type values
113+
//
114+
// Decode returns an InvalidDecoderError if interface passed is invalid.
96115
func (d *Decoder) Decode(v interface{}, values url.Values) (err error) {
97116

98117
dec := &decoder{
@@ -102,12 +121,12 @@ func (d *Decoder) Decode(v interface{}, values url.Values) (err error) {
102121

103122
val := reflect.ValueOf(v)
104123

105-
if val.Kind() != reflect.Ptr {
106-
panic("interface must be a pointer")
124+
if val.Kind() != reflect.Ptr || val.IsNil() {
125+
return &InvalidDecoderError{reflect.TypeOf(v)}
126+
// panic("interface must be a pointer")
107127
}
108128

109129
val = val.Elem()
110-
111130
typ := val.Type()
112131

113132
if val.Kind() == reflect.Struct && typ != timeType {

0 commit comments

Comments
 (0)