Skip to content

Commit 28e2903

Browse files
committed
Add possibility to use "in" operator with maps and structs.
1 parent 5404e3f commit 28e2903

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

Diff for: eval_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,26 @@ var evalTests = []evalTest{
249249
nil,
250250
true,
251251
},
252+
{
253+
`"a" in {a:1, b:2}`,
254+
nil,
255+
true,
256+
},
257+
{
258+
`"Bar" in Foo`,
259+
struct{ Foo struct{ Bar bool } }{struct{ Bar bool }{true}},
260+
true,
261+
},
262+
{
263+
`"Bar" in Ptr`,
264+
struct{ Ptr *struct{ Bar bool } }{&struct{ Bar bool }{true}},
265+
true,
266+
},
267+
{
268+
`"Bar" in NilPtr`,
269+
struct{ NilPtr *bool }{nil},
270+
false,
271+
},
252272
{
253273
`0 in nil`,
254274
nil,
@@ -432,6 +452,21 @@ var evalErrorTests = []evalErrorTest{
432452
nil,
433453
`operator "in" not defined on string`,
434454
},
455+
{
456+
`nil in map`,
457+
map[string]interface{}{"map": map[string]interface{}{"true": "yes"}},
458+
`cannot use <nil> as index to map[string]interface {}`,
459+
},
460+
{
461+
`nil in foo`,
462+
map[string]interface{}{"foo": struct{ Bar bool }{true}},
463+
`cannot use <nil> as field name of struct { Bar bool }`,
464+
},
465+
{
466+
`true in foo`,
467+
map[string]interface{}{"foo": struct{ Bar bool }{true}},
468+
`cannot use bool as field name of struct { Bar bool }`,
469+
},
435470
{
436471
"len()",
437472
nil,

Diff for: runtime.go

+26
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,32 @@ func contains(needle interface{}, array interface{}) (bool, error) {
115115
}
116116
}
117117
return false, nil
118+
case reflect.Map:
119+
n := reflect.ValueOf(needle)
120+
if !n.IsValid() {
121+
return false, fmt.Errorf("cannot use %T as index to %T", needle, array)
122+
}
123+
value := v.MapIndex(n)
124+
if value.IsValid() {
125+
return true, nil
126+
}
127+
return false, nil
128+
case reflect.Struct:
129+
n := reflect.ValueOf(needle)
130+
if !n.IsValid() || n.Kind() != reflect.String {
131+
return false, fmt.Errorf("cannot use %T as field name of %T", needle, array)
132+
}
133+
value := v.FieldByName(n.String())
134+
if value.IsValid() {
135+
return true, nil
136+
}
137+
return false, nil
138+
case reflect.Ptr:
139+
value := v.Elem()
140+
if value.IsValid() && value.CanInterface() {
141+
return contains(needle, value.Interface())
142+
}
143+
return false, nil
118144
}
119145
return false, fmt.Errorf("operator \"in\" not defined on %T", array)
120146
}

0 commit comments

Comments
 (0)