ref: 204c3a9e32fcf6617ede978e35d3e2e89a5b491c
parent: fe901b81191860b60e6fcb29f8ebf87baef2ee79
author: Cameron Moore <moorereason@gmail.com>
date: Sat May 20 07:54:13 EDT 2017
tpl/collections: Support interfaces in union Fixes #3411
--- a/tpl/collections/collections.go
+++ b/tpl/collections/collections.go
@@ -545,7 +545,7 @@
// If either l1 or l2 is nil then the non-nil list will be returned.
func (ns *Namespace) Union(l1, l2 interface{}) (interface{}, error) { if l1 == nil && l2 == nil {- return nil, errors.New("both arrays/slices have to be of the same type")+ return []interface{}{}, nil } else if l1 == nil && l2 != nil {return l2, nil
} else if l1 != nil && l2 == nil {@@ -561,21 +561,96 @@
case reflect.Array, reflect.Slice:
r := reflect.MakeSlice(l1v.Type(), 0, 0)
- if l1v.Type() != l2v.Type() {+ if l1v.Type() != l2v.Type() &&
+ l1v.Type().Elem().Kind() != reflect.Interface &&
+ l2v.Type().Elem().Kind() != reflect.Interface {+
return r.Interface(), nil
}
+ var l1vv reflect.Value
for i := 0; i < l1v.Len(); i++ {- elem := l1v.Index(i)
- if !ns.In(r.Interface(), elem.Interface()) {- r = reflect.Append(r, elem)
+ l1vv = l1v.Index(i)
+ if !ns.In(r.Interface(), l1vv.Interface()) {+ r = reflect.Append(r, l1vv)
}
}
for j := 0; j < l2v.Len(); j++ {- elem := l2v.Index(j)
- if !ns.In(r.Interface(), elem.Interface()) {- r = reflect.Append(r, elem)
+ l2vv := l2v.Index(j)
+
+ switch l1vv.Kind() {+ case reflect.String:
+ l2t, err := toString(l2vv)
+ if err == nil && !ns.In(r.Interface(), l2t) {+ r = reflect.Append(r, reflect.ValueOf(l2t))
+ }
+ case reflect.Int:
+ l2t, err := toInt(l2vv)
+ if err == nil && !ns.In(r.Interface(), l2t) {+ r = reflect.Append(r, reflect.ValueOf(int(l2t)))
+ }
+ case reflect.Int8:
+ l2t, err := toInt(l2vv)
+ if err == nil && !ns.In(r.Interface(), l2t) {+ r = reflect.Append(r, reflect.ValueOf(int8(l2t)))
+ }
+ case reflect.Int16:
+ l2t, err := toInt(l2vv)
+ if err == nil && !ns.In(r.Interface(), l2t) {+ r = reflect.Append(r, reflect.ValueOf(int16(l2t)))
+ }
+ case reflect.Int32:
+ l2t, err := toInt(l2vv)
+ if err == nil && !ns.In(r.Interface(), l2t) {+ r = reflect.Append(r, reflect.ValueOf(int32(l2t)))
+ }
+ case reflect.Int64:
+ l2t, err := toInt(l2vv)
+ if err == nil && !ns.In(r.Interface(), l2t) {+ r = reflect.Append(r, reflect.ValueOf(l2t))
+ }
+ case reflect.Float32:
+ l2t, err := toFloat(l2vv)
+ if err == nil && !ns.In(r.Interface(), float32(l2t)) {+ r = reflect.Append(r, reflect.ValueOf(float32(l2t)))
+ }
+ case reflect.Float64:
+ l2t, err := toFloat(l2vv)
+ if err == nil && !ns.In(r.Interface(), l2t) {+ r = reflect.Append(r, reflect.ValueOf(l2t))
+ }
+ case reflect.Interface:
+ switch l1vv.Interface().(type) {+ case string:
+ switch l2vvActual := l2vv.Interface().(type) {+ case string:
+ if !ns.In(r.Interface(), l2vvActual) {+ r = reflect.Append(r, l2vv)
+ }
+ }
+ case int, int8, int16, int32, int64:
+ switch l2vvActual := l2vv.Interface().(type) {+ case int, int8, int16, int32, int64:
+ if !ns.In(r.Interface(), l2vvActual) {+ r = reflect.Append(r, l2vv)
+ }
+ }
+ case uint, uint8, uint16, uint32, uint64:
+ switch l2vvActual := l2vv.Interface().(type) {+ case uint, uint8, uint16, uint32, uint64:
+ if !ns.In(r.Interface(), l2vvActual) {+ r = reflect.Append(r, l2vv)
+ }
+ }
+ case float32, float64:
+ switch l2vvActual := l2vv.Interface().(type) {+ case float32, float64:
+ if !ns.In(r.Interface(), l2vvActual) {+ r = reflect.Append(r, l2vv)
+ }
+ }
+ }
}
}
--- a/tpl/collections/collections_test.go
+++ b/tpl/collections/collections_test.go
@@ -571,15 +571,19 @@
expect interface{}isErr bool
}{+ {nil, nil, []interface{}{}, false},+ {nil, []string{"a", "b"}, []string{"a", "b"}, false},+ {[]string{"a", "b"}, nil, []string{"a", "b"}, false},+
+ // []A ∪ []B
+ {[]string{"1", "2"}, []int{3}, []string{}, false},+ {[]int{1, 2}, []string{"1", "2"}, []int{}, false},+
+ // []T ∪ []T
{[]string{"a", "b", "c", "c"}, []string{"a", "b", "b"}, []string{"a", "b", "c"}, false}, {[]string{"a", "b"}, []string{"a", "b", "c"}, []string{"a", "b", "c"}, false}, {[]string{"a", "b", "c"}, []string{"d", "e"}, []string{"a", "b", "c", "d", "e"}, false}, {[]string{}, []string{}, []string{}, false},- {[]string{"a", "b"}, nil, []string{"a", "b"}, false},- {nil, []string{"a", "b"}, []string{"a", "b"}, false},- {nil, nil, make([]interface{}, 0), true},- {[]string{"1", "2"}, []int{1, 2}, make([]string, 0), false},- {[]int{1, 2}, []string{"1", "2"}, make([]int, 0), false}, {[]int{1, 2, 3}, []int{3, 4, 5}, []int{1, 2, 3, 4, 5}, false}, {[]int{1, 2, 3}, []int{1, 2, 3}, []int{1, 2, 3}, false}, {[]int{1, 2, 4}, []int{2, 4}, []int{1, 2, 4}, false},@@ -586,6 +590,26 @@
{[]int{2, 4}, []int{1, 2, 4}, []int{2, 4, 1}, false}, {[]int{1, 2, 4}, []int{3, 6}, []int{1, 2, 4, 3, 6}, false}, {[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4, 1.1}, false},+ {[]interface{}{"a", "b", "c", "c"}, []interface{}{"a", "b", "b"}, []interface{}{"a", "b", "c"}, false},+
+ // []T ∪ []interface{}+ {[]string{"1", "2"}, []interface{}{"9"}, []string{"1", "2", "9"}, false},+ {[]int{2, 4}, []interface{}{1, 2, 4}, []int{2, 4, 1}, false},+ {[]int8{2, 4}, []interface{}{int8(1), int8(2), int8(4)}, []int8{2, 4, 1}, false},+ {[]int8{2, 4}, []interface{}{1, 2, 4}, []int8{2, 4, 1}, false},+ {[]int16{2, 4}, []interface{}{1, 2, 4}, []int16{2, 4, 1}, false},+ {[]int32{2, 4}, []interface{}{1, 2, 4}, []int32{2, 4, 1}, false},+ {[]int64{2, 4}, []interface{}{1, 2, 4}, []int64{2, 4, 1}, false},+ {[]float64{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float64{2.2, 4.4, 1.1}, false},+ {[]float32{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float32{2.2, 4.4, 1.1}, false},+
+ // []interface{} ∪ []T+ {[]interface{}{"a", "b", "c", "c"}, []string{"a", "b", "b"}, []interface{}{"a", "b", "c"}, false},+ {[]interface{}{}, []string{}, []interface{}{}, false},+ {[]interface{}{1, 2}, []int{2, 3}, []interface{}{1, 2, 3}, false},+ {[]interface{}{1, 2}, []int8{2, 3}, []interface{}{1, 2, int8(3)}, false},+ {[]interface{}{1.1, 2.2}, []float64{2.2, 3.3}, []interface{}{1.1, 2.2, 3.3}, false},+
// errors
{"not array or slice", []string{"a"}, false, true}, {[]string{"a"}, "not array or slice", false, true},--
⑨