From dcd9091413c313f98d1ccf52a23cb6a13c07982a Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Sun, 8 Apr 2018 11:24:59 -0700 Subject: [PATCH] Correct bug in array index logic fixes #33 --- README.md | 5 +++-- decoder.go | 11 +++++++---- decoder_test.go | 24 ++++++++++++++++++++++++ doc.go | 3 +++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6d4b8cf..bff7069 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Package form ============ -![Project status](https://img.shields.io/badge/version-3.1.1-green.svg) +![Project status](https://img.shields.io/badge/version-3.1.2-green.svg) [![Build Status](https://semaphoreci.com/api/v1/joeybloggs/form/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/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) @@ -23,7 +23,8 @@ It has the following features: Common Questions -- Does it support encoding.TextUnmarshaler? No because TextUnmarshaler only accepts []byte but posted values can have multiple values, so is not suitable. +- Does it support encoding.TextUnmarshaler? No because TextUnmarshaler only accepts []byte but posted values can have multiple values, so is not suitable. +- Mixing `array/slice` with `array[idx]/slice[idx]`, in which order are they parsed? `array/slice` then `array[idx]/slice[idx]` Supported Types ( out of the box ) ---------- diff --git a/decoder.go b/decoder.go index 6034248..5b4cb90 100644 --- a/decoder.go +++ b/decoder.go @@ -464,8 +464,8 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in if ok && len(arr) > 0 { var varr reflect.Value - - overCapacity := v.Len() < len(arr) + l := len(arr) + overCapacity := v.Len() < l if overCapacity { // more values than array capacity, ignore values over capacity as it's possible some would just want // to grab the first x number of elements; in the future strict mode logic should return an error @@ -474,10 +474,13 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in varr = reflect.Indirect(reflect.New(reflect.ArrayOf(v.Len(), v.Type().Elem()))) reflect.Copy(varr, v) - for i := 0; i < v.Len(); i++ { + if v.Len() < len(arr) { + l = v.Len() + } + for i := 0; i < l; i++ { newVal := reflect.New(v.Type().Elem()).Elem() - if d.setFieldByType(newVal, namespace, 0) { + if d.setFieldByType(newVal, namespace, i) { set = true varr.Index(i).Set(newVal) } diff --git a/decoder_test.go b/decoder_test.go index 85278f3..4d7709b 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -1571,6 +1571,10 @@ func TestDecodeArrayBug(t *testing.T) { A [2]string B [2]string C [2]string + D [3]string + E [3]string + F [3]string + G [3]string } decoder := NewDecoder() err := decoder.Decode(&data, url.Values{ @@ -1583,6 +1587,12 @@ func TestDecodeArrayBug(t *testing.T) { "B[2]": {"40"}, // invalid array index "C[q]": {""}, + // index and mix tests + "D": {"10"}, + "E": {"10", "20"}, + "F": {"10", "", "20"}, + "G": {"10"}, + "G[2]": {"20"}, }) NotEqual(t, err, nil) Equal(t, err.Error(), "Field Namespace:C ERROR:invalid array index 'q'") @@ -1590,4 +1600,18 @@ func TestDecodeArrayBug(t *testing.T) { Equal(t, data.A[1], "20") Equal(t, data.B[0], "10") Equal(t, data.B[1], "31") + Equal(t, data.C[0], "") + Equal(t, data.C[1], "") + Equal(t, data.D[0], "10") + Equal(t, data.D[1], "") + Equal(t, data.D[2], "") + Equal(t, data.E[0], "10") + Equal(t, data.E[1], "20") + Equal(t, data.E[2], "") + Equal(t, data.F[0], "10") + Equal(t, data.F[1], "") + Equal(t, data.F[2], "20") + Equal(t, data.G[0], "10") + Equal(t, data.G[1], "") + Equal(t, data.G[2], "20") } diff --git a/doc.go b/doc.go index c54d6ca..b2201eb 100644 --- a/doc.go +++ b/doc.go @@ -31,6 +31,9 @@ Questions No because TextUnmarshaler only accepts []byte but posted values can have multiple values, so is not suitable. + Mixing array/slice with array[idx]/slice[idx], in which order are they parsed? + array/slice then array[idx]/slice[idx] + Supported Types out of the box supported types