Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slicestr fix for other int type param #1353

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 41 additions & 24 deletions tpl/template_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,32 +128,65 @@ func compareGetFloat(a interface{}, b interface{}) (float64, float64) {
return left, right
}

// Taken out from Substr, to be used by Slicestr too.
func toInt(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)
}
}

// Slicing in Slicestr is done by specifying a half-open range with
// two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
// The end index can be omitted, it defaults to the string's length.
func Slicestr(a interface{}, startEnd ...int) (string, error) {
func Slicestr(a interface{}, startEnd ...interface{}) (string, error) {
aStr, err := cast.ToStringE(a)
if err != nil {
return "", err
}

if len(startEnd) > 2 {
var argStart, argEnd int

argNum := len(startEnd)

if argNum > 0 {
if argStart, err = toInt(startEnd[0], "start argument must be integer"); err != nil {
return "", err
}
}
if argNum > 1 {
if argEnd, err = toInt(startEnd[1], "end argument must be integer"); err != nil {
return "", err
}
}

if argNum > 2 {
return "", errors.New("too many arguments")
}

asRunes := []rune(aStr)

if len(startEnd) > 0 && (startEnd[0] < 0 || startEnd[0] >= len(asRunes)) {
if argNum > 0 && (argStart < 0 || argStart >= len(asRunes)) {
return "", errors.New("slice bounds out of range")
}

if len(startEnd) == 2 {
if startEnd[1] < 0 || startEnd[1] > len(asRunes) {
if argNum == 2 {
if argEnd < 0 || argEnd > len(asRunes) {
return "", errors.New("slice bounds out of range")
}
return string(asRunes[startEnd[0]:startEnd[1]]), nil
} else if len(startEnd) == 1 {
return string(asRunes[startEnd[0]:]), nil
return string(asRunes[argStart:argEnd]), nil
} else if argNum == 1 {
return string(asRunes[argStart:]), nil
} else {
return string(asRunes[:]), nil
}
Expand All @@ -179,22 +212,6 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
}

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)
}
}

asRunes := []rune(aStr)

Expand Down
53 changes: 35 additions & 18 deletions tpl/template_funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,29 +348,46 @@ func TestIn(t *testing.T) {
}

func TestSlicestr(t *testing.T) {
var err error
for i, this := range []struct {
v1 interface{}
v2 []int
v2 interface{}
v3 interface{}
expect interface{}
}{
{"abc", []int{1, 2}, "b"},
{"abc", []int{1, 3}, "bc"},
{"abc", []int{0, 1}, "a"},
{"abcdef", []int{}, "abcdef"},
{"abcdef", []int{0, 6}, "abcdef"},
{"abcdef", []int{0, 2}, "ab"},
{"abcdef", []int{2}, "cdef"},
{123, []int{1, 3}, "23"},
{123, []int{1, 2, 3}, false},
{"abcdef", []int{6}, false},
{"abcdef", []int{4, 7}, false},
{"abcdef", []int{-1}, false},
{"abcdef", []int{-1, 7}, false},
{"abcdef", []int{1, -1}, false},
{tstNoStringer{}, []int{0, 1}, false},
{"ĀĀĀ", []int{0, 1}, "Ā"}, // issue #1333
{"abc", 1, 2, "b"},
{"abc", 1, 3, "bc"},
{"abcdef", 1, int8(3), "bc"},
{"abcdef", 1, int16(3), "bc"},
{"abcdef", 1, int32(3), "bc"},
{"abcdef", 1, int64(3), "bc"},
{"abc", 0, 1, "a"},
{"abcdef", nil, nil, "abcdef"},
{"abcdef", 0, 6, "abcdef"},
{"abcdef", 0, 2, "ab"},
{"abcdef", 2, nil, "cdef"},
{"abcdef", int8(2), nil, "cdef"},
{"abcdef", int16(2), nil, "cdef"},
{"abcdef", int32(2), nil, "cdef"},
{"abcdef", int64(2), nil, "cdef"},
{123, 1, 3, "23"},
{"abcdef", 6, nil, false},
{"abcdef", 4, 7, false},
{"abcdef", -1, nil, false},
{"abcdef", -1, 7, false},
{"abcdef", 1, -1, false},
{tstNoStringer{}, 0, 1, false},
{"ĀĀĀ", 0, 1, "Ā"}, // issue #1333
} {
result, err := Slicestr(this.v1, this.v2...)

var result string
if this.v2 == nil {
result, err = Slicestr(this.v1)
} else if this.v3 == nil {
result, err = Slicestr(this.v1, this.v2)
} else {
result, err = Slicestr(this.v1, this.v2, this.v3)
}

if b, ok := this.expect.(bool); ok && !b {
if err == nil {
Expand Down