Skip to content

Commit

Permalink
Add array.slice builtin function
Browse files Browse the repository at this point in the history
Fixes open-policy-agent#1243

Signed-off-by: Ravi Soni <soniravi829@gmail.com>
  • Loading branch information
Ravi Soni authored and Ravi Soni committed Mar 28, 2019
1 parent 9d50ed6 commit d223284
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
14 changes: 14 additions & 0 deletions ast/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var DefaultBuiltins = [...]*Builtin{

// Arrays
ArrayConcat,
ArraySlice,

// Casting
ToNumber,
Expand Down Expand Up @@ -505,6 +506,19 @@ var ArrayConcat = &Builtin{
),
}

// ArraySlice returns a slice of a given array
var ArraySlice = &Builtin{
Name: "array.slice",
Decl: types.NewFunction(
types.Args(
types.NewArray(nil, types.A),
types.NewNumber(),
types.NewNumber(),
),
types.NewArray(nil, types.A),
),
}

/**
* Casting
*/
Expand Down
39 changes: 39 additions & 0 deletions topdown/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package topdown

import (
"fmt"

"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/topdown/builtins"
)
Expand Down Expand Up @@ -33,6 +35,43 @@ func builtinArrayConcat(a, b ast.Value) (ast.Value, error) {
return arrC, nil
}

func builtinArraySlice(a, i, j ast.Value) (ast.Value, error) {
arrA, err := builtins.ArrayOperand(a, 1)
if err != nil {
return nil, err
}

startIndex, err := builtins.IntOperand(i, 1)
if err != nil {
return nil, err
}

stopIndex, err := builtins.IntOperand(j, 2)
if err != nil {
return nil, err
}

// Don't allow negative indices for slicing
if startIndex < 0 || stopIndex < 0 {
return nil, fmt.Errorf("Invalid slicing operation: negative indices not allowed")
}

// stopIndex can't be less than startIndex
if stopIndex < startIndex {
return nil, fmt.Errorf("Invalid slicing operation: stopIndex can't be less than startIndex")
}

arrB := make(ast.Array, 0, stopIndex-startIndex)

for i := startIndex; i < stopIndex; i++ {
arrB = append(arrB, arrA[i])
}

return arrB, nil

}

func init() {
RegisterFunctionalBuiltin2(ast.ArrayConcat.Name, builtinArrayConcat)
RegisterFunctionalBuiltin3(ast.ArraySlice.Name, builtinArraySlice)
}
5 changes: 5 additions & 0 deletions topdown/array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ func TestTopDownArray(t *testing.T) {
{"concat", []string{`p = x { x = array.concat([1,2], [3,4]) }`}, "[1,2,3,4]"},
{"concat: err", []string{`p = x { x = array.concat(data.b, [3,4]) }`}, fmt.Errorf("operand 1 must be array")},
{"concat: err rhs", []string{`p = x { x = array.concat([1,2], data.b) }`}, fmt.Errorf("operand 2 must be array")},

{"slice", []string{`p = x { x = array.slice([1,2,3,4,5], 1, 3) }`}, "[2,3]"},
{"slice", []string{`p = x { x = array.slice([1,2,3], 0, 0) }`}, "[]"},
{"slice: err negative indices", []string{`p = x { x = array.slice([3,4], -1, 0) }`}, fmt.Errorf("Invalid slicing operation: negative indices not allowed")},
{"slice: err stopIndex < startIndex", []string{`p = x { x = array.slice([1,2,3], 2, 1) }`}, fmt.Errorf("Invalid slicing operation: stopIndex can't be less than startIndex")},
}

data := loadSmallTestData()
Expand Down

0 comments on commit d223284

Please sign in to comment.