From 2cd3a22a6787d1f230758493b5c79734c7403a15 Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Sat, 2 Feb 2019 17:27:40 -0800 Subject: [PATCH 1/2] fix array idx issue with custom functions --- README.md | 2 +- benchmarks/ajg_form_test.go | 305 ------------------------------ benchmarks/benchmarks.md | 100 +++------- benchmarks/formam_test.go | 155 --------------- benchmarks/gorilla_scheme_test.go | 168 ---------------- decoder.go | 3 +- 6 files changed, 24 insertions(+), 709 deletions(-) delete mode 100644 benchmarks/ajg_form_test.go delete mode 100644 benchmarks/formam_test.go delete mode 100644 benchmarks/gorilla_scheme_test.go diff --git a/README.md b/README.md index a743db1..a1cd515 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Package form ============ -![Project status](https://img.shields.io/badge/version-3.1.3-green.svg) +![Project status](https://img.shields.io/badge/version-3.1.4-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) diff --git a/benchmarks/ajg_form_test.go b/benchmarks/ajg_form_test.go deleted file mode 100644 index fc57183..0000000 --- a/benchmarks/ajg_form_test.go +++ /dev/null @@ -1,305 +0,0 @@ -package benchmarks - -import ( - "net/url" - "testing" - - ajg "github.com/ajg/form" -) - -// Simple Benchmarks - -func BenchmarkSimpleUserDecodeStructAGJForm(b *testing.B) { - - values := getUserStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test User - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkSimpleUserDecodeStructParallelAGJFrom(b *testing.B) { - - values := getUserStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test User - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -func BenchmarkSimpleUserEncodeStructAGJForm(b *testing.B) { - - test := getUserStruct() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkSimpleUserEncodeStructParallelAGJForm(b *testing.B) { - - test := getUserStruct() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } - }) -} - -// Primitives ALL types - -func BenchmarkPrimitivesDecodeStructAllPrimitivesTypesAGJForm(b *testing.B) { - values := getPrimitivesStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test PrimitivesStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallelAGJForm(b *testing.B) { - values := getPrimitivesStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test PrimitivesStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -func BenchmarkPrimitivesEncodeStructAllPrimitivesTypesAGJForm(b *testing.B) { - test := getPrimitivesStruct() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallelAGJForm(b *testing.B) { - test := getPrimitivesStruct() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } - }) -} - -// Complex Array ALL types - -func BenchmarkComplexArrayDecodeStructAllTypesAGJForm(b *testing.B) { - values := getComplexArrayStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test ComplexArrayStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkComplexArrayDecodeStructAllTypesParallelAGJForm(b *testing.B) { - values := getComplexArrayStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test ComplexArrayStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -func BenchmarkComplexArrayEncodeStructAllTypesAGJForm(b *testing.B) { - test := getComplexArrayStruct() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkComplexArrayEncodeStructAllTypesParallelAGJForm(b *testing.B) { - test := getComplexArrayStruct() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } - }) -} - -// Complex Map ALL types - -func getComplexMapStructValuesAGJForm() url.Values { - return url.Values{ - "String.key": []string{"value"}, - "StringPtr.key": []string{"value"}, - "Int.0": []string{"1"}, - "IntPtr.0": []string{"1"}, - "Int8.0": []string{"1"}, - "Int8Ptr.0": []string{"1"}, - "Int16.0": []string{"1"}, - "Int16Ptr.0": []string{"1"}, - "Int32.0": []string{"1"}, - "Int32Ptr.0": []string{"1"}, - "Int64.0": []string{"1"}, - "Int64Ptr.0": []string{"1"}, - "Uint.0": []string{"1"}, - "UintPtr.0": []string{"1"}, - "Uint8.0": []string{"1"}, - "Uint8Ptr.0": []string{"1"}, - "Uint16.0": []string{"1"}, - "Uint16Ptr.0": []string{"1"}, - "Uint32.0": []string{"1"}, - "Uint32Ptr.0": []string{"1"}, - "Uint64.0": []string{"1"}, - "Uint64Ptr.0": []string{"1"}, - "NestedInt.1.2": []string{"3"}, - "NestedIntPtr.1.2": []string{"3"}, - } -} - -func BenchmarkComplexMapDecodeStructAllTypesAGJForm(b *testing.B) { - values := getComplexMapStructValuesAGJForm() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test ComplexMapStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkComplexMapDecodeStructAllTypesParallelAGJForm(b *testing.B) { - values := getComplexMapStructValuesAGJForm() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test ComplexMapStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -func BenchmarkComplexMapEncodeStructAllTypesAGJForm(b *testing.B) { - test := getComplexMapStructValuesAGJForm() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkComplexMapEncodeStructAllTypesParallelAGJForm(b *testing.B) { - test := getComplexMapStructValuesAGJForm() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } - }) -} - -// NestedStruct Benchmarks - -func BenchmarkDecodeNestedStructAGJForm(b *testing.B) { - - values := getNestedStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test NestedStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkDecodeNestedStructParallelAGJForm(b *testing.B) { - - values := getNestedStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test NestedStruct - if err := ajg.DecodeValues(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -func BenchmarkEncodeNestedStructAGJForm(b *testing.B) { - - test := getNestedStruct() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkEncodeNestedStructParallelAGJForm(b *testing.B) { - - test := getNestedStruct() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := ajg.EncodeToValues(&test); err != nil { - b.Error(err) - } - } - }) -} diff --git a/benchmarks/benchmarks.md b/benchmarks/benchmarks.md index 22bcc66..cbb6cc3 100644 --- a/benchmarks/benchmarks.md +++ b/benchmarks/benchmarks.md @@ -1,86 +1,30 @@ ## Benchmarks -All Benchmarks Last Run Sept 10, 2017 +All Benchmarks Last Run Feb 2, 2019 -Run on MacBook Pro (15-inch, 2017) using go version go1.9 darwin/amd64 +Run on MacBook Pro (15-inch, 2017) using go version go1.11.5 darwin/amd64 go test -run=NONE -bench=. -benchmem=true ### go-playground/form ```go -BenchmarkSimpleUserDecodeStruct-8 5000000 243 ns/op 64 B/op 1 allocs/op -BenchmarkSimpleUserDecodeStructParallel-8 20000000 72.4 ns/op 64 B/op 1 allocs/op -BenchmarkSimpleUserEncodeStruct-8 2000000 683 ns/op 485 B/op 10 allocs/op -BenchmarkSimpleUserEncodeStructParallel-8 10000000 205 ns/op 485 B/op 10 allocs/op -BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 2000000 739 ns/op 96 B/op 1 allocs/op -BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 10000000 214 ns/op 96 B/op 1 allocs/op -BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 500000 3608 ns/op 2977 B/op 36 allocs/op -BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1000000 1013 ns/op 2978 B/op 36 allocs/op -BenchmarkComplexArrayDecodeStructAllTypes-8 100000 13358 ns/op 2249 B/op 121 allocs/op -BenchmarkComplexArrayDecodeStructAllTypesParallel-8 500000 3656 ns/op 2249 B/op 121 allocs/op -BenchmarkComplexArrayEncodeStructAllTypes-8 100000 11574 ns/op 7112 B/op 104 allocs/op -BenchmarkComplexArrayEncodeStructAllTypesParallel-8 500000 3278 ns/op 7112 B/op 104 allocs/op -BenchmarkComplexMapDecodeStructAllTypes-8 100000 18945 ns/op 5305 B/op 130 allocs/op -BenchmarkComplexMapDecodeStructAllTypesParallel-8 300000 5213 ns/op 5308 B/op 130 allocs/op -BenchmarkComplexMapEncodeStructAllTypes-8 100000 12177 ns/op 6972 B/op 129 allocs/op -BenchmarkComplexMapEncodeStructAllTypesParallel-8 500000 3409 ns/op 6971 B/op 129 allocs/op -BenchmarkDecodeNestedStruct-8 500000 2642 ns/op 384 B/op 14 allocs/op -BenchmarkDecodeNestedStructParallel-8 2000000 760 ns/op 384 B/op 14 allocs/op -BenchmarkEncodeNestedStruct-8 1000000 1686 ns/op 693 B/op 16 allocs/op -BenchmarkEncodeNestedStructParallel-8 3000000 468 ns/op 693 B/op 16 allocs/op -``` - -### gorilla/schema -```go -BenchmarkSimpleUserStructGorilla-8 500000 2602 ns/op 568 B/op 26 allocs/op -BenchmarkSimpleUserStructGorillaParallel-8 2000000 742 ns/op 568 B/op 26 allocs/op -BenchmarkPrimitivesStructAllPrimitivesTypesGorilla-8 200000 9801 ns/op 1616 B/op 95 allocs/op -BenchmarkPrimitivesStructAllPrimitivesTypesGorillaParallel-8 500000 2674 ns/op 1616 B/op 95 allocs/op -BenchmarkComplexArrayStructAllTypesGorilla-8 50000 27079 ns/op 5528 B/op 240 allocs/op -BenchmarkComplexArrayStructAllTypesGorillaParallel-8 200000 7382 ns/op 5528 B/op 240 allocs/op -BenchmarkArrayMapNestedStructGorilla-8 200000 8578 ns/op 2397 B/op 82 allocs/op -BenchmarkArrayMapNestedStructGorillaParallel-8 1000000 2392 ns/op 2397 B/op 82 allocs/op -``` - -### monoculum/formam -```go -BenchmarkSimpleUserStructFormam-8 500000 2657 ns/op 232 B/op 16 allocs/op -BenchmarkSimpleUserStructFormamParallel-8 2000000 700 ns/op 232 B/op 16 allocs/op -BenchmarkPrimitivesStructAllPrimitivesFormamTypes-8 200000 8657 ns/op 1088 B/op 121 allocs/op -BenchmarkPrimitivesStructAllPrimitivesTypesFormamParallel-8 1000000 2168 ns/op 1088 B/op 121 allocs/op -BenchmarkComplexArrayStructAllTypesFormam-8 50000 35892 ns/op 5588 B/op 484 allocs/op -BenchmarkComplexArrayStructAllTypesFormamParallel-8 200000 9238 ns/op 5554 B/op 482 allocs/op -BenchmarkComplexMapStructAllTypesFormam-8 30000 40312 ns/op 14645 B/op 534 allocs/op -BenchmarkComplexMapStructAllTypesFormamParallel-8 200000 10826 ns/op 14646 B/op 534 allocs/op ---- FAIL: BenchmarkArrayMapNestedStructFormam - formam_test.go:137: formam: not supported type for field "Value" in path "NestedPtrArray[0].Value". Maybe you should to include it the UnmarshalText interface or register it using custom type? ---- FAIL: BenchmarkArrayMapNestedStructFormamParallel - formam_test.go:151: formam: not supported type for field "Value" in path "NestedPtrArray[1].Value". Maybe you should to include it the UnmarshalText interface or register it using custom type? -``` - -### ajg/form -```go -BenchmarkSimpleUserDecodeStructAGJForm-8 300000 5134 ns/op 1320 B/op 34 allocs/op -BenchmarkSimpleUserDecodeStructParallelAGJFrom-8 1000000 1379 ns/op 1320 B/op 34 allocs/op -BenchmarkSimpleUserEncodeStructAGJForm-8 300000 4245 ns/op 1272 B/op 28 allocs/op -BenchmarkSimpleUserEncodeStructParallelAGJForm-8 1000000 1144 ns/op 1272 B/op 28 allocs/op -BenchmarkPrimitivesDecodeStructAllPrimitivesTypesAGJForm-8 100000 19222 ns/op 5662 B/op 143 allocs/op -BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallelAGJForm-8 300000 4966 ns/op 5662 B/op 143 allocs/op -BenchmarkPrimitivesEncodeStructAllPrimitivesTypesAGJForm-8 100000 13655 ns/op 5761 B/op 72 allocs/op -BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallelAGJForm-8 500000 3617 ns/op 5760 B/op 72 allocs/op ---- FAIL: BenchmarkComplexArrayDecodeStructAllTypesAGJForm - ajg_form_test.go:127: is not a valid index for type []uint16 ---- FAIL: BenchmarkComplexArrayDecodeStructAllTypesParallelAGJForm - ajg_form_test.go:140: is not a valid index for type []int -BenchmarkComplexArrayEncodeStructAllTypesAGJForm-8 30000 57848 ns/op 21210 B/op 314 allocs/op -BenchmarkComplexArrayEncodeStructAllTypesParallelAGJForm-8 100000 15527 ns/op 21207 B/op 314 allocs/op -BenchmarkComplexMapDecodeStructAllTypesAGJForm-8 20000 77528 ns/op 22295 B/op 592 allocs/op -BenchmarkComplexMapDecodeStructAllTypesParallelAGJForm-8 100000 20717 ns/op 22297 B/op 592 allocs/op -BenchmarkComplexMapEncodeStructAllTypesAGJForm-8 50000 39453 ns/op 17936 B/op 299 allocs/op -BenchmarkComplexMapEncodeStructAllTypesParallelAGJForm-8 200000 11513 ns/op 17937 B/op 299 allocs/op ---- FAIL: BenchmarkDecodeNestedStructAGJForm - ajg_form_test.go:261: NestedArray[0] doesn't exist in benchmarks.NestedStruct ---- FAIL: BenchmarkDecodeNestedStructParallelAGJForm - ajg_form_test.go:275: NestedArray[1] doesn't exist in benchmarks.NestedStruct -BenchmarkEncodeNestedStructAGJForm-8 100000 15791 ns/op 5656 B/op 108 allocs/op -BenchmarkEncodeNestedStructParallelAGJForm-8 300000 4625 ns/op 5656 B/op 108 allocs/op +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 ``` \ No newline at end of file diff --git a/benchmarks/formam_test.go b/benchmarks/formam_test.go deleted file mode 100644 index efe58e3..0000000 --- a/benchmarks/formam_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package benchmarks - -import ( - "testing" - - "github.com/monoculum/formam" -) - -// Simple Benchmarks - -func BenchmarkSimpleUserStructFormam(b *testing.B) { - - values := getUserStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test User - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkSimpleUserStructFormamParallel(b *testing.B) { - - values := getUserStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test User - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } - }) -} - -// Primitives ALL types - -func BenchmarkPrimitivesStructAllPrimitivesFormamTypes(b *testing.B) { - values := getPrimitivesStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test PrimitivesStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkPrimitivesStructAllPrimitivesTypesFormamParallel(b *testing.B) { - values := getPrimitivesStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test PrimitivesStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } - }) -} - -// Complex Array ALL types - -func BenchmarkComplexArrayStructAllTypesFormam(b *testing.B) { - values := getComplexArrayStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test ComplexArrayStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkComplexArrayStructAllTypesFormamParallel(b *testing.B) { - values := getComplexArrayStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test ComplexArrayStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } - }) -} - -// Complex Map ALL types - -func BenchmarkComplexMapStructAllTypesFormam(b *testing.B) { - // b.Log("Formam only supports map key of string at this time") - // b.SkipNow() - values := getComplexMapStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test ComplexMapStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkComplexMapStructAllTypesFormamParallel(b *testing.B) { - // b.Log("Formam only supports map key of string at this time") - // b.SkipNow() - values := getComplexMapStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test ComplexMapStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } - }) -} - -// NestedStruct Benchmarks - -func BenchmarkArrayMapNestedStructFormam(b *testing.B) { - - values := getNestedStructValues() - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test NestedStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } -} - -func BenchmarkArrayMapNestedStructFormamParallel(b *testing.B) { - - values := getNestedStructValues() - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test NestedStruct - if err := formam.Decode(values, &test); err != nil { - b.Error(err) - } - } - }) -} diff --git a/benchmarks/gorilla_scheme_test.go b/benchmarks/gorilla_scheme_test.go deleted file mode 100644 index 846fb24..0000000 --- a/benchmarks/gorilla_scheme_test.go +++ /dev/null @@ -1,168 +0,0 @@ -package benchmarks - -import ( - "net/url" - "testing" - - "github.com/gorilla/schema" -) - -// Simple Benchmarks - -func BenchmarkSimpleUserStructGorilla(b *testing.B) { - - values := getUserStructValues() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test User - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkSimpleUserStructGorillaParallel(b *testing.B) { - - values := getUserStructValues() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test User - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -// Primitives ALL types - -func BenchmarkPrimitivesStructAllPrimitivesTypesGorilla(b *testing.B) { - values := getPrimitivesStructValues() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test PrimitivesStruct - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkPrimitivesStructAllPrimitivesTypesGorillaParallel(b *testing.B) { - values := getPrimitivesStructValues() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test PrimitivesStruct - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -// Complex Array ALL types - -func BenchmarkComplexArrayStructAllTypesGorilla(b *testing.B) { - values := getComplexArrayStructValues() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test ComplexArrayStruct - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkComplexArrayStructAllTypesGorillaParallel(b *testing.B) { - values := getComplexArrayStructValues() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test ComplexArrayStruct - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } - }) -} - -// Complex Map ALL types - -func BenchmarkComplexMapStructAllTypesGorilla(b *testing.B) { - b.Log("Gorilla does not support map parsing at this time") - b.SkipNow() -} - -func BenchmarkComplexMapStructAllTypesGorillaParallel(b *testing.B) { - b.Log("Gorilla does not support map parsing at this time") - b.SkipNow() -} - -// NestedStruct Benchmarks - -func getNestedStructValuesGorilla() url.Values { - return url.Values{ - // Nested Field - "Value": []string{"value"}, - // Nested Array - "NestedArray.0.Value": []string{"value"}, - "NestedArray.1.Value": []string{"value"}, - // Nested Array Ptr - "NestedPtrArray.0.Value": []string{"value"}, - "NestedPtrArray.1.Value": []string{"value"}, - // Nested 2 - "Nested2.Value": []string{"value"}, - "Nested2.Nested2.Value": []string{"value"}, - } -} - -func BenchmarkArrayMapNestedStructGorilla(b *testing.B) { - - values := getNestedStructValuesGorilla() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - for n := 0; n < b.N; n++ { - var test NestedStruct - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } -} - -func BenchmarkArrayMapNestedStructGorillaParallel(b *testing.B) { - - values := getNestedStructValuesGorilla() - decoder := schema.NewDecoder() - decoder.IgnoreUnknownKeys(true) - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var test NestedStruct - if err := decoder.Decode(&test, values); err != nil { - b.Error(err) - } - } - }) -} diff --git a/decoder.go b/decoder.go index 5b4cb90..cf858f0 100644 --- a/decoder.go +++ b/decoder.go @@ -188,7 +188,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in if ok { if cf, ok := d.d.customTypeFuncs[v.Type()]; ok { - val, err := cf(arr) + val, err := cf(arr[idx:]) if err != nil { d.setError(namespace, err) return @@ -355,7 +355,6 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in set = true case reflect.Slice: - d.parseMapData() // slice elements could be mixed eg. number and non-numbers Value[0]=[]string{"10"} and Value=[]string{"10","20"} From 5e9b2ad2848bed46117b9dfdef193413410a4c15 Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Sat, 2 Feb 2019 17:35:10 -0800 Subject: [PATCH 2/2] added slice tests --- decoder_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/decoder_test.go b/decoder_test.go index 4d7709b..aab0e65 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -1615,3 +1615,44 @@ func TestDecodeArrayBug(t *testing.T) { Equal(t, data.G[1], "") Equal(t, data.G[2], "20") } + +func TestDecoder_RegisterCustomTypeFuncOnSlice(t *testing.T) { + type customString string + + type TestStruct struct { + Slice []customString `form:"slice"` + } + + d := NewDecoder() + d.RegisterCustomTypeFunc(func(vals []string) (i interface{}, e error) { + custom := make([]customString, 0, len(vals)) + for i := 0; i < len(vals); i++ { + custom = append(custom, customString("custom"+vals[i])) + } + return custom, nil + }, []customString{}) + + var v TestStruct + err := d.Decode(&v, url.Values{"slice": []string{"v1", "v2"}}) + Equal(t, err, nil) + Equal(t, v.Slice, []customString{"customv1", "customv2"}) +} + +func TestDecoder_RegisterCustomTypeFunc(t *testing.T) { + type customString string + + type TestStruct struct { + Slice []customString `form:"slice"` + } + + d := NewDecoder() + d.RegisterCustomTypeFunc(func(vals []string) (i interface{}, e error) { + return customString("custom" + vals[0]), nil + }, customString("")) + + var v TestStruct + err := d.Decode(&v, url.Values{"slice": []string{"v1", "v2"}}) + Equal(t, err, nil) + + Equal(t, v.Slice, []customString{"customv1", "customv2"}) +}