From 59293117986566b75d571391606a26ed4dcac16a Mon Sep 17 00:00:00 2001 From: netliomax25-code Date: Fri, 29 May 2026 11:55:59 +0530 Subject: [PATCH 1/2] handle arbitrary slice types in sort builtin --- builtin/builtin.go | 9 +++++++++ builtin/builtin_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/builtin/builtin.go b/builtin/builtin.go index 87e73614..2b37098e 100644 --- a/builtin/builtin.go +++ b/builtin/builtin.go @@ -996,6 +996,15 @@ var Builtins = []*Function{ for i, v := range in { array[i] = v } + default: + v := reflect.ValueOf(args[0]) + if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { + return nil, 0, fmt.Errorf("cannot sort %s", v.Kind()) + } + array = make([]any, v.Len()) + for i := 0; i < v.Len(); i++ { + array[i] = v.Index(i).Interface() + } } var desc bool diff --git a/builtin/builtin_test.go b/builtin/builtin_test.go index 0d0dec35..196f4530 100644 --- a/builtin/builtin_test.go +++ b/builtin/builtin_test.go @@ -653,6 +653,30 @@ func TestBuiltin_sort_i64(t *testing.T) { assert.Equal(t, []any{int64(1), int64(1), int64(1)}, out) } +func TestBuiltin_sort_non_standard_slice(t *testing.T) { + tests := []struct { + input string + env any + want any + }{ + {`sort(x)`, map[string]any{"x": []int64{3, 1, 2}}, []any{int64(1), int64(2), int64(3)}}, + {`sort(x)`, map[string]any{"x": []uint{3, 1, 2}}, []any{uint(1), uint(2), uint(3)}}, + {`sort(x, "desc")`, map[string]any{"x": []int32{1, 3, 2}}, []any{int32(3), int32(2), int32(1)}}, + } + + for _, test := range tests { + t.Run(test.input, func(t *testing.T) { + out, err := expr.Eval(test.input, test.env) + require.NoError(t, err) + assert.Equal(t, test.want, out) + }) + } + + _, err := expr.Eval(`sort(x)`, map[string]any{"x": 42}) + require.Error(t, err) + assert.Contains(t, err.Error(), "cannot sort int") +} + func TestBuiltin_bitOpsFunc(t *testing.T) { tests := []struct { input string From c39e59166dac805a655e08c92899f2a892bb7a49 Mon Sep 17 00:00:00 2001 From: netliomax25-code Date: Sat, 30 May 2026 11:30:34 +0530 Subject: [PATCH 2/2] limit sort reflection fallback to orderable element kinds --- builtin/builtin.go | 16 ++++++++++------ builtin/builtin_test.go | 4 ---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/builtin/builtin.go b/builtin/builtin.go index 2b37098e..eb8a77d2 100644 --- a/builtin/builtin.go +++ b/builtin/builtin.go @@ -998,12 +998,16 @@ var Builtins = []*Function{ } default: v := reflect.ValueOf(args[0]) - if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { - return nil, 0, fmt.Errorf("cannot sort %s", v.Kind()) - } - array = make([]any, v.Len()) - for i := 0; i < v.Len(); i++ { - array[i] = v.Index(i).Interface() + if v.Kind() == reflect.Slice || v.Kind() == reflect.Array { + switch v.Type().Elem().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Float32, reflect.Float64, reflect.String, reflect.Bool: + array = make([]any, v.Len()) + for i := 0; i < v.Len(); i++ { + array[i] = v.Index(i).Interface() + } + } } } diff --git a/builtin/builtin_test.go b/builtin/builtin_test.go index 196f4530..f1943925 100644 --- a/builtin/builtin_test.go +++ b/builtin/builtin_test.go @@ -671,10 +671,6 @@ func TestBuiltin_sort_non_standard_slice(t *testing.T) { assert.Equal(t, test.want, out) }) } - - _, err := expr.Eval(`sort(x)`, map[string]any{"x": 42}) - require.Error(t, err) - assert.Contains(t, err.Error(), "cannot sort int") } func TestBuiltin_bitOpsFunc(t *testing.T) {