From a65e6b2627def336184693a06dc943edd1038d13 Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Tue, 16 Apr 2024 05:37:04 +0000 Subject: [PATCH] Added support for interface types in bind --- cmdlang/userbuiltin.go | 2 +- cmdlang/userbuiltin_test.go | 54 ++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/cmdlang/userbuiltin.go b/cmdlang/userbuiltin.go index d6a24ea..ec19b0d 100644 --- a/cmdlang/userbuiltin.go +++ b/cmdlang/userbuiltin.go @@ -32,7 +32,7 @@ func (ca CallArgs) Bind(vars ...interface{}) error { if argValue.Type().Kind() != reflect.Pointer { continue - } else if argValue.Elem().Type() != poValue.Type() { + } else if !poValue.Type().AssignableTo(argValue.Elem().Type()) { continue } diff --git a/cmdlang/userbuiltin_test.go b/cmdlang/userbuiltin_test.go index d7e350e..5f42016 100644 --- a/cmdlang/userbuiltin_test.go +++ b/cmdlang/userbuiltin_test.go @@ -2,9 +2,10 @@ package cmdlang_test import ( "context" + "testing" + "github.com/lmika/cmdlang-proto/cmdlang" "github.com/stretchr/testify/assert" - "testing" ) func TestInst_SetBuiltin(t *testing.T) { @@ -89,3 +90,54 @@ func TestInst_SetBuiltin(t *testing.T) { } }) } + +func TestCallArgs_Bind(t *testing.T) { + t.Run("bind to an interface", func(t *testing.T) { + ctx := context.Background() + + inst := cmdlang.New() + inst.SetBuiltin("sa", func(ctx context.Context, args cmdlang.CallArgs) (any, error) { + return doStringA{this: "a val"}, nil + }) + inst.SetBuiltin("sb", func(ctx context.Context, args cmdlang.CallArgs) (any, error) { + return doStringB{left: "foo", right: "bar"}, nil + }) + inst.SetBuiltin("dostr", func(ctx context.Context, args cmdlang.CallArgs) (any, error) { + var ds doStringable + + if err := args.Bind(&ds); err != nil { + return nil, err + } + + return ds.DoString(), nil + }) + + va, err := inst.Eval(ctx, `dostr (sa)`) + assert.NoError(t, err) + assert.Equal(t, "do string A: a val", va) + + vb, err := inst.Eval(ctx, `dostr (sb)`) + assert.NoError(t, err) + assert.Equal(t, "do string B: foo bar", vb) + }) +} + +type doStringable interface { + DoString() string +} + +type doStringA struct { + this string +} + +func (da doStringA) DoString() string { + return "do string A: " + da.this +} + +type doStringB struct { + left, right string +} + +func (da doStringB) DoString() string { + return "do string B: " + da.left + " " + da.right +}