From 0d355250cbb731c8fef0af7246aa0a2733fd8c18 Mon Sep 17 00:00:00 2001 From: Tatsushi Demachi Date: Sun, 7 Jun 2015 00:21:14 +0900 Subject: [PATCH] Fix substr tpl func's int type variant issue `substr` template function takes one or two range arguments. Both arguments must be int type values but if it is used with a calclation function e.g. `add`, `len` etc, it causes a wrong type error. This fixes the issue to allow the function to take other integer type variant like `int64` etc. This also includes a small fix on no range argument case. Fix #1190 --- tpl/template_funcs.go | 33 ++++++++++++++++++++++++++++---- tpl/template_funcs_test.go | 39 +++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go index a5bd221e750..ff6b4a23abc 100644 --- a/tpl/template_funcs.go +++ b/tpl/template_funcs.go @@ -170,20 +170,45 @@ func Slicestr(a interface{}, startEnd ...int) (string, error) { // In addition, borrowing from the extended behavior described at http://php.net/substr, // if length is given and is negative, then that many characters will be omitted from // the end of string. -func Substr(a interface{}, nums ...int) (string, error) { +func Substr(a interface{}, nums ...interface{}) (string, error) { aStr, err := cast.ToStringE(a) if err != nil { return "", err } var start, length int + toInt := func (v interface{}, message string) (int, error) { + switch i := v.(type) { + case int: + return i, nil + case int8: + return int(i), nil + case int16: + return int(i), nil + case int32: + return int(i), nil + case int64: + return int(i), nil + default: + return 0, errors.New(message) + } + } + switch len(nums) { + case 0: + return "", errors.New("too less arguments") case 1: - start = nums[0] + if start, err = toInt(nums[0], "start argument must be integer"); err != nil { + return "", err + } length = len(aStr) case 2: - start = nums[0] - length = nums[1] + if start, err = toInt(nums[0], "start argument must be integer"); err != nil { + return "", err + } + if length, err = toInt(nums[1], "length argument must be integer"); err != nil { + return "", err + } default: return "", errors.New("too many arguments") } diff --git a/tpl/template_funcs_test.go b/tpl/template_funcs_test.go index a3c20290d86..c8ed002724a 100644 --- a/tpl/template_funcs_test.go +++ b/tpl/template_funcs_test.go @@ -317,10 +317,12 @@ func TestSlicestr(t *testing.T) { } func TestSubstr(t *testing.T) { + var err error + var n int for i, this := range []struct { v1 interface{} - v2 int - v3 int + v2 interface{} + v3 interface{} expect interface{} }{ {"abc", 1, 2, "bc"}, @@ -334,11 +336,30 @@ func TestSubstr(t *testing.T) { {"abcdef", 1, 100, "bcdef"}, {"abcdef", -100, 3, "abc"}, {"abcdef", -3, -1, "de"}, + {"abcdef", 2, nil, "cdef"}, + {"abcdef", int8(2), nil, "cdef"}, + {"abcdef", int16(2), nil, "cdef"}, + {"abcdef", int32(2), nil, "cdef"}, + {"abcdef", int64(2), nil, "cdef"}, + {"abcdef", 2, int8(3), "cde"}, + {"abcdef", 2, int16(3), "cde"}, + {"abcdef", 2, int32(3), "cde"}, + {"abcdef", 2, int64(3), "cde"}, {123, 1, 3, "23"}, {1.2e3, 0, 4, "1200"}, {tstNoStringer{}, 0, 1, false}, + {"abcdef", 2.0, nil, false}, + {"abcdef", 2.0, 2, false}, + {"abcdef", 2, 2.0, false}, } { - result, err := Substr(this.v1, this.v2, this.v3) + var result string + n = i + + if this.v3 == nil { + result, err = Substr(this.v1, this.v2) + } else { + result, err = Substr(this.v1, this.v2, this.v3) + } if b, ok := this.expect.(bool); ok && !b { if err == nil { @@ -354,6 +375,18 @@ func TestSubstr(t *testing.T) { } } } + + n++ + _, err = Substr("abcdef") + if err == nil { + t.Errorf("[%d] Substr didn't return an expected error", n) + } + + n++ + _, err = Substr("abcdef", 1, 2, 3) + if err == nil { + t.Errorf("[%d] Substr didn't return an expected error", n) + } } func TestSplit(t *testing.T) {