Skip to content

Commit

Permalink
Fix out-of-range exception (#46)
Browse files Browse the repository at this point in the history
Fixed out-of-range exception.

Fixes #45
  • Loading branch information
deankarn authored Nov 17, 2019
1 parent 5c5278d commit ff1a304
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package form
============
<img align="right" src="https://raw.githubusercontent.com/go-playground/form/master/logo.jpg">![Project status](https://img.shields.io/badge/version-4.1.0-green.svg)
<img align="right" src="https://raw.githubusercontent.com/go-playground/form/master/logo.jpg">![Project status](https://img.shields.io/badge/version-4.1.1-green.svg)
[![Build Status](https://travis-ci.org/go-playground/form.svg?branch=master)](https://travis-ci.org/go-playground/form)
[![Coverage Status](https://coveralls.io/repos/github/go-playground/form/badge.svg?branch=master)](https://coveralls.io/github/go-playground/form?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/form)](https://goreportcard.com/report/github.com/go-playground/form)
Expand Down
45 changes: 23 additions & 22 deletions benchmarks/benchmarks.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
## Benchmarks

All Benchmarks Last Run Feb 2, 2019
All Benchmarks Last Run Nov 17, 2019

Run on MacBook Pro (15-inch, 2017) using go version go1.11.5 darwin/amd64
Run on MacBook Pro (15-inch, 2017) using go version go1.13.4 darwin/amd64
go test -run=NONE -bench=. -benchmem=true

### go-playground/form
```go
BenchmarkSimpleUserDecodeStruct-8 5000000 255 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserDecodeStructParallel-8 20000000 77.1 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserEncodeStruct-8 2000000 625 ns/op 485 B/op 10 allocs/op
BenchmarkSimpleUserEncodeStructParallel-8 10000000 207 ns/op 485 B/op 10 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 2000000 768 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 10000000 221 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 500000 3192 ns/op 2977 B/op 35 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1000000 1011 ns/op 2977 B/op 35 allocs/op
BenchmarkComplexArrayDecodeStructAllTypes-8 100000 13269 ns/op 2248 B/op 121 allocs/op
BenchmarkComplexArrayDecodeStructAllTypesParallel-8 500000 3758 ns/op 2249 B/op 121 allocs/op
BenchmarkComplexArrayEncodeStructAllTypes-8 200000 10728 ns/op 7112 B/op 104 allocs/op
BenchmarkComplexArrayEncodeStructAllTypesParallel-8 500000 3305 ns/op 7113 B/op 104 allocs/op
BenchmarkComplexMapDecodeStructAllTypes-8 100000 17331 ns/op 5306 B/op 130 allocs/op
BenchmarkComplexMapDecodeStructAllTypesParallel-8 300000 4901 ns/op 5309 B/op 130 allocs/op
BenchmarkComplexMapEncodeStructAllTypes-8 100000 11226 ns/op 6970 B/op 129 allocs/op
BenchmarkComplexMapEncodeStructAllTypesParallel-8 500000 3418 ns/op 6970 B/op 129 allocs/op
BenchmarkDecodeNestedStruct-8 500000 2448 ns/op 384 B/op 14 allocs/op
BenchmarkDecodeNestedStructParallel-8 2000000 736 ns/op 384 B/op 14 allocs/op
BenchmarkEncodeNestedStruct-8 1000000 1468 ns/op 693 B/op 16 allocs/op
BenchmarkEncodeNestedStructParallel-8 3000000 467 ns/op 693 B/op 16 allocs/op
BenchmarkSimpleUserDecodeStruct-8 4447569 255 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserDecodeStructParallel-8 14087551 77.2 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserEncodeStruct-8 1863354 645 ns/op 485 B/op 10 allocs/op
BenchmarkSimpleUserEncodeStructParallel-8 5554753 208 ns/op 485 B/op 10 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 1345276 881 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 4729965 259 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 303967 3331 ns/op 2977 B/op 35 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1094600 1077 ns/op 2978 B/op 35 allocs/op
BenchmarkComplexArrayDecodeStructAllTypes-8 76928 14567 ns/op 2248 B/op 121 allocs/op
BenchmarkComplexArrayDecodeStructAllTypesParallel-8 292060 4355 ns/op 2249 B/op 121 allocs/op
BenchmarkComplexArrayEncodeStructAllTypes-8 94536 11334 ns/op 7113 B/op 104 allocs/op
BenchmarkComplexArrayEncodeStructAllTypesParallel-8 298318 3633 ns/op 7112 B/op 104 allocs/op
BenchmarkComplexMapDecodeStructAllTypes-8 58084 18635 ns/op 5306 B/op 130 allocs/op
BenchmarkComplexMapDecodeStructAllTypesParallel-8 187159 5454 ns/op 5308 B/op 130 allocs/op
BenchmarkComplexMapEncodeStructAllTypes-8 101962 11763 ns/op 6971 B/op 129 allocs/op
BenchmarkComplexMapEncodeStructAllTypesParallel-8 312925 4185 ns/op 6970 B/op 129 allocs/op
BenchmarkDecodeNestedStruct-8 469940 2547 ns/op 384 B/op 14 allocs/op
BenchmarkDecodeNestedStructParallel-8 1486963 810 ns/op 384 B/op 14 allocs/op
BenchmarkEncodeNestedStruct-8 796798 1501 ns/op 693 B/op 16 allocs/op
BenchmarkEncodeNestedStructParallel-8 2290203 520 ns/op 693 B/op 16 allocs/op

```
33 changes: 13 additions & 20 deletions decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,19 @@ func (d *decoder) setError(namespace []byte, err error) {
if d.errs == nil {
d.errs = make(DecodeErrors)
}

d.errs[string(namespace)] = err
}

func (d *decoder) findAlias(ns string) *recursiveData {

for i := 0; i < len(d.dm); i++ {

if d.dm[i].alias == ns {
return d.dm[i]
}
}

return nil
}

func (d *decoder) parseMapData() {

// already parsed
if len(d.dm) > 0 {
return
Expand Down Expand Up @@ -153,7 +148,6 @@ func (d *decoder) traverseStruct(v reflect.Value, typ reflect.Type, namespace []
}

for _, f := range s.fields {

namespace = namespace[:l]

if f.isAnonymous {
Expand Down Expand Up @@ -202,28 +196,27 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
}
switch kind {
case reflect.Interface:
if !ok {
if !ok || idx == len(arr) {
return
}
v.Set(reflect.ValueOf(arr[idx]))
set = true

case reflect.Ptr:

newVal := reflect.New(v.Type().Elem())
if set = d.setFieldByType(newVal.Elem(), namespace, idx); set {
v.Set(newVal)
}

case reflect.String:
if !ok {
if !ok || idx == len(arr) {
return
}
v.SetString(arr[idx])
set = true

case reflect.Uint, reflect.Uint64:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var u64 uint64
Expand All @@ -235,7 +228,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Uint8:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var u64 uint64
Expand All @@ -247,7 +240,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Uint16:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var u64 uint64
Expand All @@ -259,7 +252,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Uint32:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var u64 uint64
Expand All @@ -271,7 +264,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Int, reflect.Int64:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var i64 int64
Expand All @@ -283,7 +276,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Int8:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var i64 int64
Expand All @@ -295,7 +288,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Int16:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var i64 int64
Expand All @@ -307,7 +300,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Int32:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var i64 int64
Expand All @@ -319,7 +312,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Float32:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var f float64
Expand All @@ -331,7 +324,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Float64:
if !ok || len(arr[idx]) == 0 {
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
return
}
var f float64
Expand All @@ -343,7 +336,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
set = true

case reflect.Bool:
if !ok {
if !ok || idx == len(arr) {
return
}
var b bool
Expand Down
29 changes: 29 additions & 0 deletions decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1656,3 +1656,32 @@ func TestDecoder_RegisterCustomTypeFunc(t *testing.T) {

Equal(t, v.Slice, []customString{"customv1", "customv2"})
}

func TestDecoder_EmptyArrayString(t *testing.T) {
type T1 struct {
F1 string `form:"F1"`
}
in := url.Values{
"F1": []string{},
}

v := new(T1)

d := NewDecoder()
err := d.Decode(v, in)
Equal(t, err, nil)
}

func TestDecoder_EmptyArrayBool(t *testing.T) {
type T1 struct {
F1 bool `form:"F1"`
}
in := url.Values{
"F1": []string{},
}

v := new(T1)
d := NewDecoder()
err := d.Decode(v, in)
Equal(t, err, nil)
}

0 comments on commit ff1a304

Please sign in to comment.