pkg/list: adding slice function
atm. cue only allows to retrieve slices by using [low:high] expression
similar to golang. since the slice expression is going to be deprecated
/ removed in future version this function adds the same functionality.
Change-Id: Ibd6e0c6e9a151d9eebc3763645b03b0a00478291
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3160
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/builtin_test.go b/cue/builtin_test.go
index 6e63183..d9f8748 100644
--- a/cue/builtin_test.go
+++ b/cue/builtin_test.go
@@ -171,6 +171,21 @@
test("list", `list.Product("foo")`),
`_|_(cannot use "foo" (type string) as list in argument 1 to list.Product)`,
}, {
+ test("list", `list.Slice([1, 2, 3, 4], 1, 3)`),
+ `[2,3]`,
+ }, {
+ test("list", `list.Slice([1, 2, 3, 4], -1, 3)`),
+ `_|_(error in call to list.Slice: negative slice index)`,
+ }, {
+ test("list", `list.Slice([1, 2, 3, 4], 3, 1)`),
+ `_|_(error in call to list.Slice: invalid slice index: 3 > 1)`,
+ }, {
+ test("list", `list.Slice([1, 2, 3, 4], 5, 5)`),
+ `_|_(error in call to list.Slice: slice bounds out of range)`,
+ }, {
+ test("list", `list.Slice([1, 2, 3, 4], 1, 5)`),
+ `_|_(error in call to list.Slice: slice bounds out of range)`,
+ }, {
test("list", `list.Sum([1, 2, 3, 4])`),
`10`,
}, {
diff --git a/cue/builtins.go b/cue/builtins.go
index efc4ffd..a2e2ff9 100644
--- a/cue/builtins.go
+++ b/cue/builtins.go
@@ -663,6 +663,32 @@
},
"list": &builtinPkg{
native: []*builtin{{
+ Name: "Slice",
+ Params: []kind{listKind, intKind, intKind},
+ Result: listKind,
+ Func: func(c *callCtxt) {
+ a, i, j := c.list(0), c.int(1), c.int(2)
+ c.ret, c.err = func() (interface{}, error) {
+ if i < 0 || j < 0 {
+ return nil, fmt.Errorf("negative slice index")
+ }
+
+ if i > j {
+ return nil, fmt.Errorf("invalid slice index: %v > %v", i, j)
+ }
+
+ if i > len(a) {
+ return nil, fmt.Errorf("slice bounds out of range")
+ }
+
+ if j > len(a) {
+ return nil, fmt.Errorf("slice bounds out of range")
+ }
+
+ return a[i:j], nil
+ }()
+ },
+ }, {
Name: "MinItems",
Params: []kind{listKind, intKind},
Result: boolKind,
diff --git a/pkg/list/list.go b/pkg/list/list.go
index 8955103..f06f94f 100644
--- a/pkg/list/list.go
+++ b/pkg/list/list.go
@@ -22,6 +22,37 @@
"cuelang.org/go/cue"
)
+// Slice extracts the consecutive elements from a list starting from position i
+// up till, but not including, position j, where 0 <= i < j <= len(a).
+//
+// For instance:
+//
+// Slice([1, 2, 3, 4], 1, 3)
+//
+// results in
+//
+// [2, 3]
+//
+func Slice(a []cue.Value, i, j int) ([]cue.Value, error) {
+ if i < 0 {
+ return nil, fmt.Errorf("negative slice index")
+ }
+
+ if i > j {
+ return nil, fmt.Errorf("invalid slice index: %v > %v", i, j)
+ }
+
+ if i > len(a) {
+ return nil, fmt.Errorf("slice bounds out of range")
+ }
+
+ if j > len(a) {
+ return nil, fmt.Errorf("slice bounds out of range")
+ }
+
+ return a[i:j], nil
+}
+
// MinItems reports whether a has at least n items.
func MinItems(a []cue.Value, n int) bool {
return len(a) <= n