diff --git a/providers/slice/slice.go b/providers/slice/slice.go index 021d82c..2f90a58 100644 --- a/providers/slice/slice.go +++ b/providers/slice/slice.go @@ -1,6 +1,6 @@ package slice -import "fmt" +import "reflect" import "html/template" import "git.tebibyte.media/sashakoshka/step" @@ -16,50 +16,34 @@ type Provider struct { // FuncMap fulfills the step.FuncProvider interface. func (this *Provider) FuncMap () template.FuncMap { return template.FuncMap { - "sAppend": funcSAppend, - "iAppend": funcIAppend, - "fAppend": funcFAppend, + "list": funcList, + "append": funcAppend, } } -func funcSAppend (slice any, addition string) []string { - switch slice := slice.(type) { - case []string: - newSlice := make([]string, len(slice) + 1) - copy(newSlice, slice) - newSlice[len(slice)] = addition - return newSlice - case string: - return []string { slice, addition } - default: - return funcSAppend(fmt.Sprint(slice), addition) +func funcList (items ...reflect.Value) (reflect.Value, error) { + if len(items) == 0 { return reflect.Value { }, nil } + ty := items[0].Type() + list := reflect.MakeSlice(ty, len(items), len(items)) + for index, item := range items { + if item.Type().AssignableTo(ty) { + return reflect.Value { }, step.ErrTypeMismatch + } + dest := list.Index(index) + dest.Set(item) } + return list, nil } -func funcIAppend (slice any, addition int) []int { - switch slice := slice.(type) { - case []int: - newSlice := make([]int, len(slice) + 1) - copy(newSlice, slice) - newSlice[len(slice)] = addition - return newSlice - case int: - return []int { slice, addition } - default: - return funcIAppend(0, addition) - } -} - -func funcFAppend (slice any, addition float64) []float64 { - switch slice := slice.(type) { - case []float64: - newSlice := make([]float64, len(slice) + 1) - copy(newSlice, slice) - newSlice[len(slice)] = addition - return newSlice - case float64: - return []float64 { slice, addition } - default: - return funcFAppend(0, addition) +func funcAppend (slice reflect.Value, items ...reflect.Value) (reflect.Value, error) { + if slice.Type().Kind() != reflect.Slice { + return reflect.Value { }, step.ErrTypeMismatch } + if len(items) == 0 { return reflect.Value { }, nil } + ty := slice.Type().Elem() + end := slice.Len() + len(items) + list := reflect.MakeSlice(ty, end, end) + boundary := reflect.Copy(list, slice) + reflect.Copy(list.Slice(boundary, end), reflect.ValueOf(items)) + return list, nil }