Skip to content

Commit

Permalink
fix: add a field 'result' to get the result whose type is not []KCLRe… (
Browse files Browse the repository at this point in the history
#201)

fix: add a field 'result' to get the result whose type is not []KCLResult

Signed-off-by: zongz <[email protected]>
  • Loading branch information
zong-zhe authored Dec 21, 2023
1 parent 075d200 commit ccb9398
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 6 deletions.
42 changes: 42 additions & 0 deletions kclvm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,48 @@ a2 = App {
defer os.Remove(testdata_main_k)
}

func TestWithSelectorsReturnString(t *testing.T) {
const code = `
schema Person:
labels: {str:str}
alice = Person {
"labels": {"skin": "yellow"}
}
`
const testdata_main_k = "testdata/main_selector.k"
kfile, err := os.Create(testdata_main_k)
if err != nil {
t.Fatal(err)
}
kfile.Close()

result, err := kcl.Run(testdata_main_k,
kcl.WithCode(code),
kcl.WithSelectors("alice.labels.skin"),
)
assert2.Equal(t, err, nil)
resInStr, err := result.ToString()
assert2.Equal(t, err, nil)
assert2.Equal(t, resInStr, "yellow")

resInBool, err := result.ToBool()
assert2.Equal(t, err.Error(), "failed to convert result to *bool: type mismatch")
assert2.Equal(t, resInBool, (*bool)(nil))
resInF64, err := result.ToFloat64()
assert2.Equal(t, err.Error(), "failed to convert result to *float64: type mismatch")
assert2.Equal(t, resInF64, (*float64)(nil))
resInList, err := result.ToList()
assert2.Equal(t, err.Error(), "failed to convert result to *[]interface {}: type mismatch")
assert2.Equal(t, resInList, []interface{}(nil))
resInMap, err := result.ToMap()
assert2.Equal(t, err.Error(), "failed to convert result to *map[string]interface {}: type mismatch")
assert2.Equal(t, resInMap, map[string]interface{}(map[string]interface{}(nil)))

os.Remove(testdata_main_k)
defer os.Remove(testdata_main_k)
}

func _BenchmarkRunFilesParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
Expand Down
107 changes: 101 additions & 6 deletions pkg/kcl/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"

"github.com/chai2010/jsonv"
Expand All @@ -20,11 +21,101 @@ import (
type KclType = gpyrpc.KclType

type KCLResultList struct {
list []KCLResult
// When the list is empty, the result is the raw result.
list []KCLResult
// The result is the raw result whose type is not []KCLResult.
result interface{}
raw_json_result string
raw_yaml_result string
}

// ToString returns the result as string.
func (p *KCLResultList) ToString() (string, error) {
if p == nil || p.result == nil {
return "", fmt.Errorf("result is nil")
}
var resS string
err := p.ToType(&resS)
if err != nil {
return "", err
}
return resS, nil
}

// ToBool returns the result as bool.
func (p *KCLResultList) ToBool() (*bool, error) {
if p == nil || p.result == nil {
return nil, fmt.Errorf("result is nil")
}
var resB bool
err := p.ToType(&resB)
if err != nil {
return nil, err
}
return &resB, nil
}

// ToMap returns the result as map[string]interface{}.
func (p *KCLResultList) ToMap() (map[string]interface{}, error) {
if p == nil || p.result == nil {
return nil, fmt.Errorf("result is nil")
}
var resMap map[string]interface{}
err := p.ToType(&resMap)
if err != nil {
return nil, err
}
return resMap, nil
}

// ToFloat64 returns the result as float64.
func (p *KCLResultList) ToFloat64() (*float64, error) {
if p == nil || p.result == nil {
return nil, fmt.Errorf("result is nil")
}
var resF float64
err := p.ToType(&resF)
if err != nil {
return nil, err
}
return &resF, nil
}

// ToList returns the result as []interface{}.
func (p *KCLResultList) ToList() ([]interface{}, error) {
if p == nil || p.result == nil {
return nil, fmt.Errorf("result is nil")
}
var resList []interface{}
err := p.ToType(&resList)
if err != nil {
return nil, err
}
return resList, nil
}

// ToType returns the result as target type.
func (p *KCLResultList) ToType(target interface{}) error {
if p == nil || p.result == nil {
return fmt.Errorf("result is nil")
}

srcVal := reflect.ValueOf(p.result)
targetVal := reflect.ValueOf(target)

if targetVal.Kind() != reflect.Ptr || targetVal.IsNil() {
return fmt.Errorf("failed to convert result to %T", target)
}

if srcVal.Type() != targetVal.Elem().Type() {
return fmt.Errorf("failed to convert result to %T: type mismatch", target)
}

targetVal.Elem().Set(srcVal)

return nil
}

func (p *KCLResultList) Len() int {
return len(p.list)
}
Expand Down Expand Up @@ -262,13 +353,17 @@ func run(pathList []string, opts ...Option) (*KCLResultList, error) {
}

var mList []map[string]interface{}

if err := json.Unmarshal([]byte(resp.JsonResult), &mList); err != nil {
return nil, err
}
if len(mList) == 0 {
return nil, fmt.Errorf("kcl.Run: invalid result: %s", resp.JsonResult)
err = nil
if err := json.Unmarshal([]byte(resp.JsonResult), &result.result); err != nil {
return nil, err
}
if err != nil {
return nil, err
}
}

result.list = make([]KCLResult, 0, len(mList))
for _, m := range mList {
if len(m) != 0 {
result.list = append(result.list, m)
Expand Down

0 comments on commit ccb9398

Please sign in to comment.