Added the keys built-in
This commit is contained in:
parent
34a0c8e3ff
commit
ad746c05aa
|
@ -165,6 +165,29 @@ func indexBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
|||
return val, nil
|
||||
}
|
||||
|
||||
func keysBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||
if err := args.expectArgn(1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val := args.args[0]
|
||||
switch v := val.(type) {
|
||||
case hashable:
|
||||
keys := make(listObject, 0, v.Len())
|
||||
if err := v.Each(func(k string, _ object) error {
|
||||
keys = append(keys, strObject(k))
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return keys, nil
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func mapBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||
if err := args.expectArgn(2); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -50,6 +50,7 @@ func New(opts ...InstOption) *Inst {
|
|||
rootEC.addCmd("set", invokableFunc(setBuiltin))
|
||||
rootEC.addCmd("toUpper", invokableFunc(toUpperBuiltin))
|
||||
rootEC.addCmd("len", invokableFunc(lenBuiltin))
|
||||
rootEC.addCmd("keys", invokableFunc(keysBuiltin))
|
||||
rootEC.addCmd("index", invokableFunc(indexBuiltin))
|
||||
rootEC.addCmd("call", invokableFunc(callBuiltin))
|
||||
|
||||
|
|
|
@ -4,9 +4,10 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Builtins used for test
|
||||
|
@ -642,3 +643,57 @@ func TestBuiltins_Len(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuiltins_Keys(t *testing.T) {
|
||||
type testNested struct {
|
||||
Nested string
|
||||
Type string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
desc string
|
||||
expr string
|
||||
wantItems []string
|
||||
}{
|
||||
{desc: "keys of map", expr: `keys [alpha: "hello" bravo: "world"]`, wantItems: []string{"alpha", "bravo"}},
|
||||
{desc: "keys of go struct 1", expr: `goStruct | keys`, wantItems: []string{"Alpha", "Beta", "Gamma"}},
|
||||
{desc: "keys of go struct 2", expr: `index (goStruct) Gamma | keys`, wantItems: []string{"Nested", "Type"}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
outW := bytes.NewBuffer(nil)
|
||||
|
||||
inst := New(WithOut(outW), WithTestBuiltin())
|
||||
inst.SetBuiltin("goInt", func(ctx context.Context, args CallArgs) (any, error) {
|
||||
return []int{6, 5, 4}, nil
|
||||
})
|
||||
inst.SetBuiltin("goStruct", func(ctx context.Context, args CallArgs) (any, error) {
|
||||
return struct {
|
||||
Alpha string
|
||||
Beta string
|
||||
Gamma testNested
|
||||
hidden string
|
||||
missing string
|
||||
}{
|
||||
Alpha: "foo",
|
||||
Beta: "bar",
|
||||
Gamma: testNested{
|
||||
Nested: "ads",
|
||||
Type: "asd",
|
||||
},
|
||||
hidden: "hidden",
|
||||
missing: "missing",
|
||||
}, nil
|
||||
})
|
||||
|
||||
res, err := inst.Eval(ctx, tt.expr)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, res, len(tt.wantItems))
|
||||
for _, i := range tt.wantItems {
|
||||
assert.Contains(t, res, i)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue