github.com/rajeev159/opa@v0.45.0/topdown/bits.go (about) 1 // Copyright 2020 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 topdown 6 7 import ( 8 "math/big" 9 10 "github.com/open-policy-agent/opa/ast" 11 "github.com/open-policy-agent/opa/topdown/builtins" 12 ) 13 14 type bitsArity1 func(a *big.Int) (*big.Int, error) 15 type bitsArity2 func(a, b *big.Int) (*big.Int, error) 16 17 func bitsOr(a, b *big.Int) (*big.Int, error) { 18 return new(big.Int).Or(a, b), nil 19 } 20 21 func bitsAnd(a, b *big.Int) (*big.Int, error) { 22 return new(big.Int).And(a, b), nil 23 } 24 25 func bitsNegate(a *big.Int) (*big.Int, error) { 26 return new(big.Int).Not(a), nil 27 } 28 29 func bitsXOr(a, b *big.Int) (*big.Int, error) { 30 return new(big.Int).Xor(a, b), nil 31 } 32 33 func bitsShiftLeft(a, b *big.Int) (*big.Int, error) { 34 if b.Sign() == -1 { 35 return nil, builtins.NewOperandErr(2, "must be an unsigned integer number but got a negative integer") 36 } 37 shift := uint(b.Uint64()) 38 return new(big.Int).Lsh(a, shift), nil 39 } 40 41 func bitsShiftRight(a, b *big.Int) (*big.Int, error) { 42 if b.Sign() == -1 { 43 return nil, builtins.NewOperandErr(2, "must be an unsigned integer number but got a negative integer") 44 } 45 shift := uint(b.Uint64()) 46 return new(big.Int).Rsh(a, shift), nil 47 } 48 49 func builtinBitsArity1(fn bitsArity1) BuiltinFunc { 50 return func(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { 51 i, err := builtins.BigIntOperand(operands[0].Value, 1) 52 if err != nil { 53 return err 54 } 55 iOut, err := fn(i) 56 if err != nil { 57 return err 58 } 59 return iter(ast.NewTerm(builtins.IntToNumber(iOut))) 60 } 61 } 62 63 func builtinBitsArity2(fn bitsArity2) BuiltinFunc { 64 return func(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { 65 i1, err := builtins.BigIntOperand(operands[0].Value, 1) 66 if err != nil { 67 return err 68 } 69 i2, err := builtins.BigIntOperand(operands[1].Value, 2) 70 if err != nil { 71 return err 72 } 73 iOut, err := fn(i1, i2) 74 if err != nil { 75 return err 76 } 77 return iter(ast.NewTerm(builtins.IntToNumber(iOut))) 78 } 79 } 80 81 func init() { 82 RegisterBuiltinFunc(ast.BitsOr.Name, builtinBitsArity2(bitsOr)) 83 RegisterBuiltinFunc(ast.BitsAnd.Name, builtinBitsArity2(bitsAnd)) 84 RegisterBuiltinFunc(ast.BitsNegate.Name, builtinBitsArity1(bitsNegate)) 85 RegisterBuiltinFunc(ast.BitsXOr.Name, builtinBitsArity2(bitsXOr)) 86 RegisterBuiltinFunc(ast.BitsShiftLeft.Name, builtinBitsArity2(bitsShiftLeft)) 87 RegisterBuiltinFunc(ast.BitsShiftRight.Name, builtinBitsArity2(bitsShiftRight)) 88 }