Skip to content

Commit f1c29b0

Browse files
moorereasonbep
authored andcommitted
tpl/collections: Add support for interfaces to intersect
Fixes #1952
1 parent 93b3b13 commit f1c29b0

File tree

3 files changed

+91
-21
lines changed

3 files changed

+91
-21
lines changed

‎tpl/collections/collections.go‎

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -298,21 +298,49 @@ func (ns *Namespace) Intersect(l1, l2 interface{}) (interface{}, error) {
298298
l2vv := l2v.Index(j)
299299
switch l1vv.Kind() {
300300
case reflect.String:
301-
if l1vv.Type() == l2vv.Type() && l1vv.String() == l2vv.String() && !ns.In(r.Interface(), l2vv.Interface()) {
302-
r = reflect.Append(r, l2vv)
301+
l2t, err := toString(l2vv)
302+
if err == nil && l1vv.String() == l2t && !ns.In(r.Interface(), l1vv.Interface()) {
303+
r = reflect.Append(r, l1vv)
303304
}
304305
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
305-
switch l2vv.Kind() {
306-
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
307-
if l1vv.Int() == l2vv.Int() && !ns.In(r.Interface(), l2vv.Interface()) {
308-
r = reflect.Append(r, l2vv)
309-
}
306+
l2t, err := toInt(l2vv)
307+
if err == nil && l1vv.Int() == l2t && !ns.In(r.Interface(), l1vv.Interface()) {
308+
r = reflect.Append(r, l1vv)
310309
}
311310
case reflect.Float32, reflect.Float64:
312-
switch l2vv.Kind() {
313-
case reflect.Float32, reflect.Float64:
314-
if l1vv.Float() == l2vv.Float() && !ns.In(r.Interface(), l2vv.Interface()) {
315-
r = reflect.Append(r, l2vv)
311+
l2t, err := toFloat(l2vv)
312+
if err == nil && l1vv.Float() == l2t && !ns.In(r.Interface(), l1vv.Interface()) {
313+
r = reflect.Append(r, l1vv)
314+
}
315+
case reflect.Interface:
316+
switch l1vvActual := l1vv.Interface().(type) {
317+
case string:
318+
switch l2vvActual := l2vv.Interface().(type) {
319+
case string:
320+
if l1vvActual == l2vvActual && !ns.In(r.Interface(), l1vvActual) {
321+
r = reflect.Append(r, l1vv)
322+
}
323+
}
324+
case int, int8, int16, int32, int64:
325+
switch l2vvActual := l2vv.Interface().(type) {
326+
case int, int8, int16, int32, int64:
327+
if l1vvActual == l2vvActual && !ns.In(r.Interface(), l1vvActual) {
328+
r = reflect.Append(r, l1vv)
329+
}
330+
}
331+
case uint, uint8, uint16, uint32, uint64:
332+
switch l2vvActual := l2vv.Interface().(type) {
333+
case uint, uint8, uint16, uint32, uint64:
334+
if l1vvActual == l2vvActual && !ns.In(r.Interface(), l1vvActual) {
335+
r = reflect.Append(r, l1vv)
336+
}
337+
}
338+
case float32, float64:
339+
switch l2vvActual := l2vv.Interface().(type) {
340+
case float32, float64:
341+
if l1vvActual == l2vvActual && !ns.In(r.Interface(), l1vvActual) {
342+
r = reflect.Append(r, l1vv)
343+
}
316344
}
317345
}
318346
}

‎tpl/collections/collections_test.go‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ func TestIntersect(t *testing.T) {
260260
{[]string{"a", "b"}, []string{"a", "b", "c"}, []string{"a", "b"}},
261261
{[]string{"a", "b", "c"}, []string{"d", "e"}, []string{}},
262262
{[]string{}, []string{}, []string{}},
263-
{nil, nil, make([]interface{}, 0)},
263+
{[]string{"a", "b"}, nil, []interface{}{}},
264+
{nil, []string{"a", "b"}, []interface{}{}},
265+
{nil, nil, []interface{}{}},
264266
{[]string{"1", "2"}, []int{1, 2}, []string{}},
265267
{[]int{1, 2}, []string{"1", "2"}, []int{}},
266268
{[]int{1, 2, 4}, []int{2, 4}, []int{2, 4}},
@@ -270,6 +272,36 @@ func TestIntersect(t *testing.T) {
270272
// errors
271273
{"not array or slice", []string{"a"}, false},
272274
{[]string{"a"}, "not array or slice", false},
275+
276+
// []interface{} ∩ []interface{}
277+
{[]interface{}{"a", "b", "c"}, []interface{}{"a", "b", "b"}, []interface{}{"a", "b"}},
278+
{[]interface{}{1, 2, 3}, []interface{}{1, 2, 2}, []interface{}{1, 2}},
279+
{[]interface{}{int8(1), int8(2), int8(3)}, []interface{}{int8(1), int8(2), int8(2)}, []interface{}{int8(1), int8(2)}},
280+
{[]interface{}{int16(1), int16(2), int16(3)}, []interface{}{int16(1), int16(2), int16(2)}, []interface{}{int16(1), int16(2)}},
281+
{[]interface{}{int32(1), int32(2), int32(3)}, []interface{}{int32(1), int32(2), int32(2)}, []interface{}{int32(1), int32(2)}},
282+
{[]interface{}{int64(1), int64(2), int64(3)}, []interface{}{int64(1), int64(2), int64(2)}, []interface{}{int64(1), int64(2)}},
283+
{[]interface{}{float32(1), float32(2), float32(3)}, []interface{}{float32(1), float32(2), float32(2)}, []interface{}{float32(1), float32(2)}},
284+
{[]interface{}{float64(1), float64(2), float64(3)}, []interface{}{float64(1), float64(2), float64(2)}, []interface{}{float64(1), float64(2)}},
285+
286+
// []interface{} ∩ []T
287+
{[]interface{}{"a", "b", "c"}, []string{"a", "b", "b"}, []interface{}{"a", "b"}},
288+
{[]interface{}{1, 2, 3}, []int{1, 2, 2}, []interface{}{1, 2}},
289+
{[]interface{}{int8(1), int8(2), int8(3)}, []int8{1, 2, 2}, []interface{}{int8(1), int8(2)}},
290+
{[]interface{}{int16(1), int16(2), int16(3)}, []int16{1, 2, 2}, []interface{}{int16(1), int16(2)}},
291+
{[]interface{}{int32(1), int32(2), int32(3)}, []int32{1, 2, 2}, []interface{}{int32(1), int32(2)}},
292+
{[]interface{}{int64(1), int64(2), int64(3)}, []int64{1, 2, 2}, []interface{}{int64(1), int64(2)}},
293+
{[]interface{}{float32(1), float32(2), float32(3)}, []float32{1, 2, 2}, []interface{}{float32(1), float32(2)}},
294+
{[]interface{}{float64(1), float64(2), float64(3)}, []float64{1, 2, 2}, []interface{}{float64(1), float64(2)}},
295+
296+
// []T ∩ []interface{}
297+
{[]string{"a", "b", "c"}, []interface{}{"a", "b", "b"}, []string{"a", "b"}},
298+
{[]int{1, 2, 3}, []interface{}{1, 2, 2}, []int{1, 2}},
299+
{[]int8{1, 2, 3}, []interface{}{int8(1), int8(2), int8(2)}, []int8{1, 2}},
300+
{[]int16{1, 2, 3}, []interface{}{int16(1), int16(2), int16(2)}, []int16{1, 2}},
301+
{[]int32{1, 2, 3}, []interface{}{int32(1), int32(2), int32(2)}, []int32{1, 2}},
302+
{[]int64{1, 2, 3}, []interface{}{int64(1), int64(2), int64(2)}, []int64{1, 2}},
303+
{[]float32{1, 2, 3}, []interface{}{float32(1), float32(2), float32(2)}, []float32{1, 2}},
304+
{[]float64{1, 2, 3}, []interface{}{float64(1), float64(2), float64(2)}, []float64{1, 2}},
273305
} {
274306
errMsg := fmt.Sprintf("[%d] %v", i, test)
275307

‎tpl/collections/where.go‎

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,15 @@ func (ns *Namespace) checkCondition(v, mv reflect.Value, op string) (bool, error
124124
iv := v.Int()
125125
ivp = &iv
126126
for i := 0; i < mv.Len(); i++ {
127-
if anInt := toInt(mv.Index(i)); anInt != -1 {
127+
if anInt, err := toInt(mv.Index(i)); err == nil {
128128
ima = append(ima, anInt)
129129
}
130-
131130
}
132131
case reflect.String:
133132
sv := v.String()
134133
svp = &sv
135134
for i := 0; i < mv.Len(); i++ {
136-
if aString := toString(mv.Index(i)); aString != "" {
135+
if aString, err := toString(mv.Index(i)); err == nil {
137136
sma = append(sma, aString)
138137
}
139138
}
@@ -382,26 +381,37 @@ func (ns *Namespace) checkWhereMap(seqv, kv, mv reflect.Value, path []string, op
382381
return rv.Interface(), nil
383382
}
384383

384+
// toFloat returns the int value if possible.
385+
func toFloat(v reflect.Value) (float64, error) {
386+
switch v.Kind() {
387+
case reflect.Float32, reflect.Float64:
388+
return v.Float(), nil
389+
case reflect.Interface:
390+
return toFloat(v.Elem())
391+
}
392+
return -1, errors.New("unable to convert value to float")
393+
}
394+
385395
// toInt returns the int value if possible, -1 if not.
386-
func toInt(v reflect.Value) int64 {
396+
func toInt(v reflect.Value) (int64, error) {
387397
switch v.Kind() {
388398
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
389-
return v.Int()
399+
return v.Int(), nil
390400
case reflect.Interface:
391401
return toInt(v.Elem())
392402
}
393-
return -1
403+
return -1, errors.New("unable to convert value to int")
394404
}
395405

396406
// toString returns the string value if possible, "" if not.
397-
func toString(v reflect.Value) string {
407+
func toString(v reflect.Value) (string, error) {
398408
switch v.Kind() {
399409
case reflect.String:
400-
return v.String()
410+
return v.String(), nil
401411
case reflect.Interface:
402412
return toString(v.Elem())
403413
}
404-
return ""
414+
return "", errors.New("unable to convert value to string")
405415
}
406416

407417
var (

0 commit comments

Comments
 (0)