From fc8b1dc37b5f04bb38a7ccb310e87a67fde96475 Mon Sep 17 00:00:00 2001 From: Nathan Hyland Date: Thu, 28 Sep 2017 08:53:03 -0700 Subject: [PATCH 1/6] parse boolean pointers --- form/form.go | 45 ++++++++++++++++++++++++++------------------- form/form_test.go | 9 ++++++--- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/form/form.go b/form/form.go index d8ca3885a4..74e6750e10 100644 --- a/form/form.go +++ b/form/form.go @@ -61,6 +61,11 @@ type formOptions struct { // properly encode an explicit 0. It indicates that an explicit zero should // be sent. Zero bool + + // EncodeZeroVal indicates the need to encode the zero value of a pointer. + // It is not parsed from the form, it's meant to be passed while encoding + // boolean values, to make sure 'false' is not ignored. + EncodeZeroVal bool } type structEncoder struct { @@ -141,20 +146,21 @@ func FormatKey(parts []string) string { // --- func boolEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { - if !v.Bool() { + if !v.Bool() && !(options != nil && options.EncodeZeroVal) { return } if options != nil { - if v.Bool() { - switch { - case options.Empty: - values.Add(FormatKey(keyParts), "") - case options.Invert: - values.Add(FormatKey(keyParts), strconv.FormatBool(false)) - case options.Zero: - values.Add(FormatKey(keyParts), "0") - } + switch { + case options.Empty: + values.Add(FormatKey(keyParts), "") + case options.Invert: + values.Add(FormatKey(keyParts), strconv.FormatBool(false)) + case options.Zero: + values.Add(FormatKey(keyParts), "0") + case options.EncodeZeroVal: + fmt.Println(strconv.FormatBool(v.Bool())) + values.Add(FormatKey(keyParts), strconv.FormatBool(v.Bool())) } } else { values.Add(FormatKey(keyParts), strconv.FormatBool(v.Bool())) @@ -196,6 +202,9 @@ func buildPtrEncoder(t reflect.Type) encoderFunc { if v.IsNil() { return } + if options == nil { + options = &formOptions{EncodeZeroVal: true} + } elemF(values, v.Elem(), keyParts, options) } } @@ -357,9 +366,12 @@ func makeStructEncoder(t reflect.Type) *structEncoder { continue } + fldTyp := reflectField.Type + fldKind := fldTyp.Kind() + if Strict && options != nil && (options.Empty || options.Invert || options.Zero) && - reflectField.Type.Kind() != reflect.Bool { + fldKind != reflect.Bool { panic(fmt.Sprintf( "Cannot specify `empty`, `invert`, or `zero` for non-boolean field; on: %s/%s", @@ -367,20 +379,15 @@ func makeStructEncoder(t reflect.Type) *structEncoder { )) } - var isPtr bool - if reflectField.Type.Kind() == reflect.Ptr { - isPtr = true - } - se.fields = append(se.fields, &field{ formName: formName, index: i, - isAppender: isAppender(reflectField.Type), - isPtr: isPtr, + isAppender: isAppender(fldTyp), + isPtr: fldKind == reflect.Ptr, options: options, }) se.fieldEncs = append(se.fieldEncs, - getCachedOrBuildTypeEncoder(reflectField.Type)) + getCachedOrBuildTypeEncoder(fldTyp)) } return se diff --git a/form/form_test.go b/form/form_test.go index e22e3044af..4d9fba3da0 100644 --- a/form/form_test.go +++ b/form/form_test.go @@ -128,7 +128,8 @@ func BenchmarkAppendTo(b *testing.B) { func TestAppendTo(t *testing.T) { var arrayVal = [3]string{"1", "2", "3"} - var boolVal = true + var boolValT = true + var boolValF = false var float32Val float32 = 1.2345 @@ -165,8 +166,10 @@ func TestAppendTo(t *testing.T) { {"array_indexed[2]", &testStruct{ArrayIndexed: arrayVal}, "3"}, - {"bool", &testStruct{Bool: boolVal}, "true"}, - {"bool_ptr", &testStruct{BoolPtr: &boolVal}, "true"}, + {"bool", &testStruct{Bool: boolValT}, "true"}, + {"bool_ptr", &testStruct{BoolPtr: nil}, ""}, + {"bool_ptr", &testStruct{BoolPtr: &boolValT}, "true"}, + {"bool_ptr", &testStruct{BoolPtr: &boolValF}, "false"}, {"emptied", &testStruct{Emptied: true}, ""}, From eaf5d9a49376a96cd88d5f12cb3b5b00e5998382 Mon Sep 17 00:00:00 2001 From: Nathan Hyland Date: Thu, 28 Sep 2017 09:17:07 -0700 Subject: [PATCH 2/6] Removed println, reduced function calls --- form/form.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/form/form.go b/form/form.go index 74e6750e10..ed29c11525 100644 --- a/form/form.go +++ b/form/form.go @@ -146,7 +146,8 @@ func FormatKey(parts []string) string { // --- func boolEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { - if !v.Bool() && !(options != nil && options.EncodeZeroVal) { + val := v.Bool() + if !val && !(options != nil && options.EncodeZeroVal) { return } @@ -159,11 +160,10 @@ func boolEncoder(values *Values, v reflect.Value, keyParts []string, options *fo case options.Zero: values.Add(FormatKey(keyParts), "0") case options.EncodeZeroVal: - fmt.Println(strconv.FormatBool(v.Bool())) - values.Add(FormatKey(keyParts), strconv.FormatBool(v.Bool())) + values.Add(FormatKey(keyParts), strconv.FormatBool(val)) } } else { - values.Add(FormatKey(keyParts), strconv.FormatBool(v.Bool())) + values.Add(FormatKey(keyParts), strconv.FormatBool(val)) } } From 306b6995b49dcdf25e30f6470e78232f027353c3 Mon Sep 17 00:00:00 2001 From: Nathan Hyland Date: Thu, 28 Sep 2017 15:06:08 -0700 Subject: [PATCH 3/6] Updated handling of more pointer values --- form/form.go | 46 +++++++++++++++++++++++++++++----------------- form/form_test.go | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/form/form.go b/form/form.go index ed29c11525..7908c04b25 100644 --- a/form/form.go +++ b/form/form.go @@ -143,11 +143,13 @@ func FormatKey(parts []string) string { return key } +func encodeZeroVal(options *formOptions) bool { return options != nil && options.EncodeZeroVal } + // --- func boolEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { val := v.Bool() - if !val && !(options != nil && options.EncodeZeroVal) { + if !val && !encodeZeroVal(options) { return } @@ -202,9 +204,14 @@ func buildPtrEncoder(t reflect.Type) encoderFunc { if v.IsNil() { return } + + // pointers are considered optional. If the pointer has data, consider the data the + // requested literal value if options == nil { - options = &formOptions{EncodeZeroVal: true} + options = &formOptions{} } + options.EncodeZeroVal = true + elemF(values, v.Elem(), keyParts, options) } } @@ -214,18 +221,20 @@ func buildStructEncoder(t reflect.Type) encoderFunc { return se.encode } -func float32Encoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { - if v.Float() == 0.0 { +func float32Encoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { + val := v.Float() + if val == 0.0 && !encodeZeroVal(options) { return } - values.Add(FormatKey(keyParts), strconv.FormatFloat(v.Float(), 'f', 4, 32)) + values.Add(FormatKey(keyParts), strconv.FormatFloat(val, 'f', 4, 32)) } -func float64Encoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { - if v.Float() == 0.0 { +func float64Encoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { + val := v.Float() + if val == 0.0 && !encodeZeroVal(options) { return } - values.Add(FormatKey(keyParts), strconv.FormatFloat(v.Float(), 'f', 4, 64)) + values.Add(FormatKey(keyParts), strconv.FormatFloat(val, 'f', 4, 64)) } func getCachedOrBuildStructEncoder(t reflect.Type) *structEncoder { @@ -287,11 +296,12 @@ func getCachedOrBuildTypeEncoder(t reflect.Type) encoderFunc { return f } -func intEncoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { - if v.Int() == 0 { +func intEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { + val := v.Int() + if val == 0 && !encodeZeroVal(options) { return } - values.Add(FormatKey(keyParts), strconv.FormatInt(v.Int(), 10)) + values.Add(FormatKey(keyParts), strconv.FormatInt(val, 10)) } func interfaceEncoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { @@ -315,18 +325,20 @@ func mapEncoder(values *Values, v reflect.Value, keyParts []string, _ *formOptio } } -func stringEncoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { - if v.String() == "" { +func stringEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { + val := v.String() + if val == "" && !encodeZeroVal(options) { return } - values.Add(FormatKey(keyParts), v.String()) + values.Add(FormatKey(keyParts), val) } -func uintEncoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { - if v.Uint() == 0 { +func uintEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { + val := v.Uint() + if val == 0 && !encodeZeroVal(options) { return } - values.Add(FormatKey(keyParts), strconv.FormatUint(v.Uint(), 10)) + values.Add(FormatKey(keyParts), strconv.FormatUint(val, 10)) } func reflectValue(values *Values, v reflect.Value, keyParts []string) { diff --git a/form/form_test.go b/form/form_test.go index 4d9fba3da0..7408fbde83 100644 --- a/form/form_test.go +++ b/form/form_test.go @@ -132,18 +132,26 @@ func TestAppendTo(t *testing.T) { var boolValF = false var float32Val float32 = 1.2345 + var float32Val0 float32 var float64Val = 1.2345 + var float64Val0 = 0.0 var intVal = 123 + var intVal0 = 0 var int8Val int8 = 123 + var int8Val0 int8 var int16Val int16 = 123 + var int16Val0 int16 var int32Val int32 = 123 + var int32Val0 int32 var int64Val int64 = 123 + var int64Val0 int64 var sliceVal = []string{"1", "2", "3"} var stringVal = "123" + var stringVal0 = "" var subStructVal = testSubStruct{ SubSubStruct: testSubSubStruct{ @@ -152,10 +160,15 @@ func TestAppendTo(t *testing.T) { } var uintVal uint = 123 + var uintVal0 uint var uint8Val uint8 = 123 + var uint8Val0 uint8 var uint16Val uint16 = 123 + var uint16Val0 uint16 var uint32Val uint32 = 123 + var uint32Val0 uint32 var uint64Val uint64 = 123 + var uint64Val0 uint64 testCases := []struct { field string @@ -167,7 +180,7 @@ func TestAppendTo(t *testing.T) { {"array_indexed[2]", &testStruct{ArrayIndexed: arrayVal}, "3"}, {"bool", &testStruct{Bool: boolValT}, "true"}, - {"bool_ptr", &testStruct{BoolPtr: nil}, ""}, + {"bool_ptr", &testStruct{}, ""}, {"bool_ptr", &testStruct{BoolPtr: &boolValT}, "true"}, {"bool_ptr", &testStruct{BoolPtr: &boolValF}, "false"}, @@ -175,20 +188,34 @@ func TestAppendTo(t *testing.T) { {"float32", &testStruct{Float32: float32Val}, "1.2345"}, {"float32_ptr", &testStruct{Float32Ptr: &float32Val}, "1.2345"}, + {"float32_ptr", &testStruct{Float32Ptr: &float32Val0}, "0.000"}, + {"float32_ptr", &testStruct{}, ""}, {"float64", &testStruct{Float64: float64Val}, "1.2345"}, {"float64_ptr", &testStruct{Float64Ptr: &float64Val}, "1.2345"}, + {"float64_ptr", &testStruct{Float64Ptr: &float64Val0}, "0.0000"}, + {"float64_ptr", &testStruct{}, ""}, {"int", &testStruct{Int: intVal}, "123"}, {"int_ptr", &testStruct{IntPtr: &intVal}, "123"}, + {"int_ptr", &testStruct{IntPtr: &intVal0}, "0"}, + {"int_ptr", &testStruct{}, ""}, {"int8", &testStruct{Int8: int8Val}, "123"}, {"int8_ptr", &testStruct{Int8Ptr: &int8Val}, "123"}, + {"int8_ptr", &testStruct{Int8Ptr: &int8Val0}, "0"}, + {"int8_ptr", &testStruct{}, ""}, {"int16", &testStruct{Int16: int16Val}, "123"}, {"int16_ptr", &testStruct{Int16Ptr: &int16Val}, "123"}, + {"int16_ptr", &testStruct{Int16Ptr: &int16Val0}, "0"}, + {"int16_ptr", &testStruct{}, ""}, {"int32", &testStruct{Int32: int32Val}, "123"}, {"int32_ptr", &testStruct{Int32Ptr: &int32Val}, "123"}, + {"int32_ptr", &testStruct{Int32Ptr: &int32Val0}, "0"}, + {"int32_ptr", &testStruct{}, ""}, {"int64", &testStruct{Int64: int64Val}, "123"}, {"int64_ptr", &testStruct{Int64Ptr: &int64Val}, "123"}, + {"int64_ptr", &testStruct{Int64Ptr: &int64Val0}, "0"}, + {"int64_ptr", &testStruct{}, ""}, {"inverted", &testStruct{Inverted: true}, "false"}, @@ -214,6 +241,8 @@ func TestAppendTo(t *testing.T) { {"string", &testStruct{String: stringVal}, stringVal}, {"string_ptr", &testStruct{StringPtr: &stringVal}, stringVal}, + {"string_ptr", &testStruct{StringPtr: &stringVal0}, stringVal0}, + {"string_ptr", &testStruct{}, stringVal0}, {"substruct[subsubstruct][string]", &testStruct{SubStruct: subStructVal}, "123"}, {"substruct_ptr[subsubstruct][string]", &testStruct{SubStructPtr: &subStructVal}, "123"}, @@ -223,14 +252,24 @@ func TestAppendTo(t *testing.T) { {"uint", &testStruct{Uuint: uintVal}, "123"}, {"uint_ptr", &testStruct{UuintPtr: &uintVal}, "123"}, + {"uint_ptr", &testStruct{UuintPtr: &uintVal0}, "0"}, + {"uint_ptr", &testStruct{}, ""}, {"uint8", &testStruct{Uuint8: uint8Val}, "123"}, {"uint8_ptr", &testStruct{Uuint8Ptr: &uint8Val}, "123"}, + {"uint8_ptr", &testStruct{Uuint8Ptr: &uint8Val0}, "0"}, + {"uint8_ptr", &testStruct{}, ""}, {"uint16", &testStruct{Uuint16: uint16Val}, "123"}, {"uint16_ptr", &testStruct{Uuint16Ptr: &uint16Val}, "123"}, + {"uint16_ptr", &testStruct{Uuint16Ptr: &uint16Val0}, "0"}, + {"uint16_ptr", &testStruct{}, ""}, {"uint32", &testStruct{Uuint32: uint32Val}, "123"}, {"uint32_ptr", &testStruct{Uuint32Ptr: &uint32Val}, "123"}, + {"uint32_ptr", &testStruct{Uuint32Ptr: &uint32Val0}, "0"}, + {"uint32_ptr", &testStruct{}, ""}, {"uint64", &testStruct{Uuint64: uint64Val}, "123"}, {"uint64_ptr", &testStruct{Uuint64Ptr: &uint64Val}, "123"}, + {"uint64_ptr", &testStruct{Uuint64Ptr: &uint64Val0}, "0"}, + {"uint64_ptr", &testStruct{}, ""}, {"zeroed", &testStruct{Zeroed: true}, "0"}, } From 705c09202680def8ecd6b2c08d6d72b4b09f3a9b Mon Sep 17 00:00:00 2001 From: Nathan Hyland Date: Thu, 28 Sep 2017 15:16:00 -0700 Subject: [PATCH 4/6] Fixed float32ptr --- form/form_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/form/form_test.go b/form/form_test.go index 7408fbde83..48832efe61 100644 --- a/form/form_test.go +++ b/form/form_test.go @@ -188,7 +188,7 @@ func TestAppendTo(t *testing.T) { {"float32", &testStruct{Float32: float32Val}, "1.2345"}, {"float32_ptr", &testStruct{Float32Ptr: &float32Val}, "1.2345"}, - {"float32_ptr", &testStruct{Float32Ptr: &float32Val0}, "0.000"}, + {"float32_ptr", &testStruct{Float32Ptr: &float32Val0}, "0.0000"}, {"float32_ptr", &testStruct{}, ""}, {"float64", &testStruct{Float64: float64Val}, "1.2345"}, From 83ddbcc3705fd9b669d073a5f8e9e7d743e81595 Mon Sep 17 00:00:00 2001 From: Nathan Hyland Date: Tue, 3 Oct 2017 06:57:11 -0700 Subject: [PATCH 5/6] Removed EncodeZeroVal from formOptions and added it as a parameter. --- form/form.go | 79 +++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/form/form.go b/form/form.go index 7908c04b25..bc931dd08d 100644 --- a/form/form.go +++ b/form/form.go @@ -27,7 +27,15 @@ type Appender interface { AppendTo(values *Values, keyParts []string) } -type encoderFunc func(values *Values, v reflect.Value, keyParts []string, options *formOptions) +// encoderFunc is used to encode any type from a request. +// +// A note about encodeZeroVal: +// Since some types in the Stripe API are defaulted to non-zero values, and Go defaults types to their zero values, +// any type that has a Stripe API default of a non-zero value is defined as a go pointer, meaning nil defaults to +// the Stripe API non-zero value. To override this, a check is made to see if the value is the zero-value for that +// type. If it is, and encodeZeroVal is true, it's encoded. This is ignored as a parameter when dealing with types +// like structs, where the decision can not be made preemptivelys. +type encoderFunc func(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) // field represents a single field found in a struct. It caches information // about that field so that we can make encoding faster. @@ -61,11 +69,6 @@ type formOptions struct { // properly encode an explicit 0. It indicates that an explicit zero should // be sent. Zero bool - - // EncodeZeroVal indicates the need to encode the zero value of a pointer. - // It is not parsed from the form, it's meant to be passed while encoding - // boolean values, to make sure 'false' is not ignored. - EncodeZeroVal bool } type structEncoder struct { @@ -73,7 +76,7 @@ type structEncoder struct { fieldEncs []encoderFunc } -func (se *structEncoder) encode(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { +func (se *structEncoder) encode(values *Values, v reflect.Value, keyParts []string, _ bool, _ *formOptions) { for i, f := range se.fields { var fieldKeyParts []string fieldV := v.Field(f.index) @@ -89,7 +92,7 @@ func (se *structEncoder) encode(values *Values, v reflect.Value, keyParts []stri fieldKeyParts = append(keyParts, f.formName) } - se.fieldEncs[i](values, fieldV, fieldKeyParts, f.options) + se.fieldEncs[i](values, fieldV, fieldKeyParts, f.isPtr, f.options) if f.isAppender && (!f.isPtr || !fieldV.IsNil()) { fieldV.Interface().(Appender).AppendTo(values, fieldKeyParts) } @@ -115,7 +118,7 @@ var structCache struct { // AppendTo uses reflection to form encode into the given values collection // based off the form tags that it defines. func AppendTo(values *Values, i interface{}) { - reflectValue(values, reflect.ValueOf(i), nil) + reflectValue(values, reflect.ValueOf(i), false, nil) } // AppendToPrefixed is the same as AppendTo, but it allows a slice of key parts @@ -125,7 +128,7 @@ func AppendTo(values *Values, i interface{}) { // for recipients. Recipients is going away, and when it does, we can probably // remove it again. func AppendToPrefixed(values *Values, i interface{}, keyParts []string) { - reflectValue(values, reflect.ValueOf(i), keyParts) + reflectValue(values, reflect.ValueOf(i), false, keyParts) } // FormatKey takes a series of key parts that may be parameter keyParts, map keys, @@ -143,13 +146,11 @@ func FormatKey(parts []string) string { return key } -func encodeZeroVal(options *formOptions) bool { return options != nil && options.EncodeZeroVal } - // --- -func boolEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { +func boolEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { val := v.Bool() - if !val && !encodeZeroVal(options) { + if !val && !encodeZeroVal { return } @@ -161,8 +162,6 @@ func boolEncoder(values *Values, v reflect.Value, keyParts []string, options *fo values.Add(FormatKey(keyParts), strconv.FormatBool(false)) case options.Zero: values.Add(FormatKey(keyParts), "0") - case options.EncodeZeroVal: - values.Add(FormatKey(keyParts), strconv.FormatBool(val)) } } else { values.Add(FormatKey(keyParts), strconv.FormatBool(val)) @@ -173,7 +172,7 @@ func buildArrayOrSliceEncoder(t reflect.Type) encoderFunc { // Gets an encoder for the type that the array or slice will hold elemF := getCachedOrBuildTypeEncoder(t.Elem()) - return func(values *Values, v reflect.Value, keyParts []string, options *formOptions) { + return func(values *Values, v reflect.Value, keyParts []string, _ bool, options *formOptions) { // FormatKey automatically adds square brackets, so just pass an empty // string into the breadcrumb trail arrNames := append(keyParts, "") @@ -187,7 +186,7 @@ func buildArrayOrSliceEncoder(t reflect.Type) encoderFunc { } indexV := v.Index(i) - elemF(values, indexV, arrNames, nil) + elemF(values, indexV, arrNames, indexV.Kind() == reflect.Ptr, nil) if isAppender(indexV.Type()) && !indexV.IsNil() { v.Interface().(Appender).AppendTo(values, arrNames) @@ -200,19 +199,11 @@ func buildPtrEncoder(t reflect.Type) encoderFunc { // Gets an encoder for the type that the pointer wraps elemF := getCachedOrBuildTypeEncoder(t.Elem()) - return func(values *Values, v reflect.Value, keyParts []string, options *formOptions) { + return func(values *Values, v reflect.Value, keyParts []string, _ bool, options *formOptions) { if v.IsNil() { return } - - // pointers are considered optional. If the pointer has data, consider the data the - // requested literal value - if options == nil { - options = &formOptions{} - } - options.EncodeZeroVal = true - - elemF(values, v.Elem(), keyParts, options) + elemF(values, v.Elem(), keyParts, true, options) } } @@ -221,17 +212,17 @@ func buildStructEncoder(t reflect.Type) encoderFunc { return se.encode } -func float32Encoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { +func float32Encoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { val := v.Float() - if val == 0.0 && !encodeZeroVal(options) { + if val == 0.0 && !encodeZeroVal { return } values.Add(FormatKey(keyParts), strconv.FormatFloat(val, 'f', 4, 32)) } -func float64Encoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { +func float64Encoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { val := v.Float() - if val == 0.0 && !encodeZeroVal(options) { + if val == 0.0 && !encodeZeroVal { return } values.Add(FormatKey(keyParts), strconv.FormatFloat(val, 'f', 4, 64)) @@ -296,57 +287,57 @@ func getCachedOrBuildTypeEncoder(t reflect.Type) encoderFunc { return f } -func intEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { +func intEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { val := v.Int() - if val == 0 && !encodeZeroVal(options) { + if val == 0 && !encodeZeroVal { return } values.Add(FormatKey(keyParts), strconv.FormatInt(val, 10)) } -func interfaceEncoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { +func interfaceEncoder(values *Values, v reflect.Value, keyParts []string, _ bool, _ *formOptions) { if v.IsNil() { return } - reflectValue(values, v.Elem(), keyParts) + reflectValue(values, v.Elem(), false, keyParts) } func isAppender(t reflect.Type) bool { return t.Implements(reflect.TypeOf((*Appender)(nil)).Elem()) } -func mapEncoder(values *Values, v reflect.Value, keyParts []string, _ *formOptions) { +func mapEncoder(values *Values, v reflect.Value, keyParts []string, _ bool, _ *formOptions) { for _, keyVal := range v.MapKeys() { if Strict && keyVal.Kind() != reflect.String { panic("Don't support serializing maps with non-string keys") } - reflectValue(values, v.MapIndex(keyVal), append(keyParts, keyVal.String())) + reflectValue(values, v.MapIndex(keyVal), false, append(keyParts, keyVal.String())) } } -func stringEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { +func stringEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { val := v.String() - if val == "" && !encodeZeroVal(options) { + if val == "" && !encodeZeroVal { return } values.Add(FormatKey(keyParts), val) } -func uintEncoder(values *Values, v reflect.Value, keyParts []string, options *formOptions) { +func uintEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { val := v.Uint() - if val == 0 && !encodeZeroVal(options) { + if val == 0 && !encodeZeroVal { return } values.Add(FormatKey(keyParts), strconv.FormatUint(val, 10)) } -func reflectValue(values *Values, v reflect.Value, keyParts []string) { +func reflectValue(values *Values, v reflect.Value, _ bool, keyParts []string) { t := v.Type() f := getCachedOrBuildTypeEncoder(t) if f != nil { - f(values, v, keyParts, nil) + f(values, v, keyParts, v.Kind() == reflect.Ptr, nil) } if isAppender(t) { From 516bdf1b343c18ecdeee7651c121c3be540462f3 Mon Sep 17 00:00:00 2001 From: Nathan Hyland Date: Tue, 3 Oct 2017 07:00:24 -0700 Subject: [PATCH 6/6] Updated parameter name --- form/form.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/form/form.go b/form/form.go index bc931dd08d..471d9fb6e9 100644 --- a/form/form.go +++ b/form/form.go @@ -29,13 +29,13 @@ type Appender interface { // encoderFunc is used to encode any type from a request. // -// A note about encodeZeroVal: +// A note about encodeZero: // Since some types in the Stripe API are defaulted to non-zero values, and Go defaults types to their zero values, // any type that has a Stripe API default of a non-zero value is defined as a go pointer, meaning nil defaults to // the Stripe API non-zero value. To override this, a check is made to see if the value is the zero-value for that -// type. If it is, and encodeZeroVal is true, it's encoded. This is ignored as a parameter when dealing with types +// type. If it is, and encodeZero is true, it's encoded. This is ignored as a parameter when dealing with types // like structs, where the decision can not be made preemptivelys. -type encoderFunc func(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) +type encoderFunc func(values *Values, v reflect.Value, keyParts []string, encodeZero bool, options *formOptions) // field represents a single field found in a struct. It caches information // about that field so that we can make encoding faster. @@ -148,9 +148,9 @@ func FormatKey(parts []string) string { // --- -func boolEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { +func boolEncoder(values *Values, v reflect.Value, keyParts []string, encodeZero bool, options *formOptions) { val := v.Bool() - if !val && !encodeZeroVal { + if !val && !encodeZero { return } @@ -212,17 +212,17 @@ func buildStructEncoder(t reflect.Type) encoderFunc { return se.encode } -func float32Encoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { +func float32Encoder(values *Values, v reflect.Value, keyParts []string, encodeZero bool, options *formOptions) { val := v.Float() - if val == 0.0 && !encodeZeroVal { + if val == 0.0 && !encodeZero { return } values.Add(FormatKey(keyParts), strconv.FormatFloat(val, 'f', 4, 32)) } -func float64Encoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { +func float64Encoder(values *Values, v reflect.Value, keyParts []string, encodeZero bool, options *formOptions) { val := v.Float() - if val == 0.0 && !encodeZeroVal { + if val == 0.0 && !encodeZero { return } values.Add(FormatKey(keyParts), strconv.FormatFloat(val, 'f', 4, 64)) @@ -287,9 +287,9 @@ func getCachedOrBuildTypeEncoder(t reflect.Type) encoderFunc { return f } -func intEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { +func intEncoder(values *Values, v reflect.Value, keyParts []string, encodeZero bool, options *formOptions) { val := v.Int() - if val == 0 && !encodeZeroVal { + if val == 0 && !encodeZero { return } values.Add(FormatKey(keyParts), strconv.FormatInt(val, 10)) @@ -316,17 +316,17 @@ func mapEncoder(values *Values, v reflect.Value, keyParts []string, _ bool, _ *f } } -func stringEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { +func stringEncoder(values *Values, v reflect.Value, keyParts []string, encodeZero bool, options *formOptions) { val := v.String() - if val == "" && !encodeZeroVal { + if val == "" && !encodeZero { return } values.Add(FormatKey(keyParts), val) } -func uintEncoder(values *Values, v reflect.Value, keyParts []string, encodeZeroVal bool, options *formOptions) { +func uintEncoder(values *Values, v reflect.Value, keyParts []string, encodeZero bool, options *formOptions) { val := v.Uint() - if val == 0 && !encodeZeroVal { + if val == 0 && !encodeZero { return } values.Add(FormatKey(keyParts), strconv.FormatUint(val, 10))