github.com/rajeev159/opa@v0.45.0/topdown/builtins/builtins.go (about)

     1  // Copyright 2016 The OPA Authors.  All rights reserved.
     2  // Use of this source code is governed by an Apache2
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package builtins contains utilities for implementing built-in functions.
     6  package builtins
     7  
     8  import (
     9  	"fmt"
    10  	"math/big"
    11  	"strings"
    12  
    13  	"github.com/open-policy-agent/opa/ast"
    14  )
    15  
    16  // Cache defines the built-in cache used by the top-down evaluation. The keys
    17  // must be comparable and should not be of type string.
    18  type Cache map[interface{}]interface{}
    19  
    20  // Put updates the cache for the named built-in.
    21  func (c Cache) Put(k, v interface{}) {
    22  	c[k] = v
    23  }
    24  
    25  // Get returns the cached value for k.
    26  func (c Cache) Get(k interface{}) (interface{}, bool) {
    27  	v, ok := c[k]
    28  	return v, ok
    29  }
    30  
    31  // ErrOperand represents an invalid operand has been passed to a built-in
    32  // function. Built-ins should return ErrOperand to indicate a type error has
    33  // occurred.
    34  type ErrOperand string
    35  
    36  func (err ErrOperand) Error() string {
    37  	return string(err)
    38  }
    39  
    40  // NewOperandErr returns a generic operand error.
    41  func NewOperandErr(pos int, f string, a ...interface{}) error {
    42  	f = fmt.Sprintf("operand %v ", pos) + f
    43  	return ErrOperand(fmt.Sprintf(f, a...))
    44  }
    45  
    46  // NewOperandTypeErr returns an operand error indicating the operand's type was wrong.
    47  func NewOperandTypeErr(pos int, got ast.Value, expected ...string) error {
    48  
    49  	if len(expected) == 1 {
    50  		return NewOperandErr(pos, "must be %v but got %v", expected[0], ast.TypeName(got))
    51  	}
    52  
    53  	return NewOperandErr(pos, "must be one of {%v} but got %v", strings.Join(expected, ", "), ast.TypeName(got))
    54  }
    55  
    56  // NewOperandElementErr returns an operand error indicating an element in the
    57  // composite operand was wrong.
    58  func NewOperandElementErr(pos int, composite ast.Value, got ast.Value, expected ...string) error {
    59  
    60  	tpe := ast.TypeName(composite)
    61  
    62  	if len(expected) == 1 {
    63  		return NewOperandErr(pos, "must be %v of %vs but got %v containing %v", tpe, expected[0], tpe, ast.TypeName(got))
    64  	}
    65  
    66  	return NewOperandErr(pos, "must be %v of (any of) {%v} but got %v containing %v", tpe, strings.Join(expected, ", "), tpe, ast.TypeName(got))
    67  }
    68  
    69  // NewOperandEnumErr returns an operand error indicating a value was wrong.
    70  func NewOperandEnumErr(pos int, expected ...string) error {
    71  
    72  	if len(expected) == 1 {
    73  		return NewOperandErr(pos, "must be %v", expected[0])
    74  	}
    75  
    76  	return NewOperandErr(pos, "must be one of {%v}", strings.Join(expected, ", "))
    77  }
    78  
    79  // IntOperand converts x to an int. If the cast fails, a descriptive error is
    80  // returned.
    81  func IntOperand(x ast.Value, pos int) (int, error) {
    82  	n, ok := x.(ast.Number)
    83  	if !ok {
    84  		return 0, NewOperandTypeErr(pos, x, "number")
    85  	}
    86  
    87  	i, ok := n.Int()
    88  	if !ok {
    89  		return 0, NewOperandErr(pos, "must be integer number but got floating-point number")
    90  	}
    91  
    92  	return i, nil
    93  }
    94  
    95  // BigIntOperand converts x to a big int. If the cast fails, a descriptive error
    96  // is returned.
    97  func BigIntOperand(x ast.Value, pos int) (*big.Int, error) {
    98  	n, err := NumberOperand(x, 1)
    99  	if err != nil {
   100  		return nil, NewOperandTypeErr(pos, x, "integer")
   101  	}
   102  	bi, err := NumberToInt(n)
   103  	if err != nil {
   104  		return nil, NewOperandErr(pos, "must be integer number but got floating-point number")
   105  	}
   106  
   107  	return bi, nil
   108  }
   109  
   110  // NumberOperand converts x to a number. If the cast fails, a descriptive error is
   111  // returned.
   112  func NumberOperand(x ast.Value, pos int) (ast.Number, error) {
   113  	n, ok := x.(ast.Number)
   114  	if !ok {
   115  		return ast.Number(""), NewOperandTypeErr(pos, x, "number")
   116  	}
   117  	return n, nil
   118  }
   119  
   120  // SetOperand converts x to a set. If the cast fails, a descriptive error is
   121  // returned.
   122  func SetOperand(x ast.Value, pos int) (ast.Set, error) {
   123  	s, ok := x.(ast.Set)
   124  	if !ok {
   125  		return nil, NewOperandTypeErr(pos, x, "set")
   126  	}
   127  	return s, nil
   128  }
   129  
   130  // StringOperand converts x to a string. If the cast fails, a descriptive error is
   131  // returned.
   132  func StringOperand(x ast.Value, pos int) (ast.String, error) {
   133  	s, ok := x.(ast.String)
   134  	if !ok {
   135  		return ast.String(""), NewOperandTypeErr(pos, x, "string")
   136  	}
   137  	return s, nil
   138  }
   139  
   140  // ObjectOperand converts x to an object. If the cast fails, a descriptive
   141  // error is returned.
   142  func ObjectOperand(x ast.Value, pos int) (ast.Object, error) {
   143  	o, ok := x.(ast.Object)
   144  	if !ok {
   145  		return nil, NewOperandTypeErr(pos, x, "object")
   146  	}
   147  	return o, nil
   148  }
   149  
   150  // ArrayOperand converts x to an array. If the cast fails, a descriptive
   151  // error is returned.
   152  func ArrayOperand(x ast.Value, pos int) (*ast.Array, error) {
   153  	a, ok := x.(*ast.Array)
   154  	if !ok {
   155  		return ast.NewArray(), NewOperandTypeErr(pos, x, "array")
   156  	}
   157  	return a, nil
   158  }
   159  
   160  // NumberToFloat converts n to a big float.
   161  func NumberToFloat(n ast.Number) *big.Float {
   162  	r, ok := new(big.Float).SetString(string(n))
   163  	if !ok {
   164  		panic("illegal value")
   165  	}
   166  	return r
   167  }
   168  
   169  // FloatToNumber converts f to a number.
   170  func FloatToNumber(f *big.Float) ast.Number {
   171  	return ast.Number(f.Text('g', -1))
   172  }
   173  
   174  // NumberToInt converts n to a big int.
   175  // If n cannot be converted to an big int, an error is returned.
   176  func NumberToInt(n ast.Number) (*big.Int, error) {
   177  	f := NumberToFloat(n)
   178  	r, accuracy := f.Int(nil)
   179  	if accuracy != big.Exact {
   180  		return nil, fmt.Errorf("illegal value")
   181  	}
   182  	return r, nil
   183  }
   184  
   185  // IntToNumber converts i to a number.
   186  func IntToNumber(i *big.Int) ast.Number {
   187  	return ast.Number(i.String())
   188  }
   189  
   190  // StringSliceOperand converts x to a []string. If the cast fails, a descriptive error is
   191  // returned.
   192  func StringSliceOperand(x ast.Value, pos int) ([]string, error) {
   193  	a, err := ArrayOperand(x, pos)
   194  	if err != nil {
   195  		return nil, err
   196  	}
   197  
   198  	var f = make([]string, a.Len())
   199  	for k := 0; k < a.Len(); k++ {
   200  		b := a.Elem(k)
   201  		c, ok := b.Value.(ast.String)
   202  		if !ok {
   203  			return nil, NewOperandElementErr(pos, x, b.Value, "[]string")
   204  		}
   205  
   206  		f[k] = string(c)
   207  	}
   208  
   209  	return f, nil
   210  }
   211  
   212  // RuneSliceOperand converts x to a []rune. If the cast fails, a descriptive error is
   213  // returned.
   214  func RuneSliceOperand(x ast.Value, pos int) ([]rune, error) {
   215  	a, err := ArrayOperand(x, pos)
   216  	if err != nil {
   217  		return nil, err
   218  	}
   219  
   220  	var f = make([]rune, a.Len())
   221  	for k := 0; k < a.Len(); k++ {
   222  		b := a.Elem(k)
   223  		c, ok := b.Value.(ast.String)
   224  		if !ok {
   225  			return nil, NewOperandElementErr(pos, x, b.Value, "string")
   226  		}
   227  
   228  		d := []rune(string(c))
   229  		if len(d) != 1 {
   230  			return nil, NewOperandElementErr(pos, x, b.Value, "rune")
   231  		}
   232  
   233  		f[k] = d[0]
   234  	}
   235  
   236  	return f, nil
   237  }