github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/scanners/terraform/parser/funcs/number.go (about) 1 // Copied from github.com/hashicorp/terraform/internal/lang/funcs 2 package funcs 3 4 import ( 5 "math" 6 "math/big" 7 8 "github.com/zclconf/go-cty/cty" 9 "github.com/zclconf/go-cty/cty/function" 10 "github.com/zclconf/go-cty/cty/gocty" 11 ) 12 13 // LogFunc constructs a function that returns the logarithm of a given number in a given base. 14 var LogFunc = function.New(&function.Spec{ 15 Params: []function.Parameter{ 16 { 17 Name: "num", 18 Type: cty.Number, 19 }, 20 { 21 Name: "base", 22 Type: cty.Number, 23 }, 24 }, 25 Type: function.StaticReturnType(cty.Number), 26 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 27 var num float64 28 if err := gocty.FromCtyValue(args[0], &num); err != nil { 29 return cty.UnknownVal(cty.String), err 30 } 31 32 var base float64 33 if err := gocty.FromCtyValue(args[1], &base); err != nil { 34 return cty.UnknownVal(cty.String), err 35 } 36 37 return cty.NumberFloatVal(math.Log(num) / math.Log(base)), nil 38 }, 39 }) 40 41 // PowFunc constructs a function that returns the logarithm of a given number in a given base. 42 var PowFunc = function.New(&function.Spec{ 43 Params: []function.Parameter{ 44 { 45 Name: "num", 46 Type: cty.Number, 47 }, 48 { 49 Name: "power", 50 Type: cty.Number, 51 }, 52 }, 53 Type: function.StaticReturnType(cty.Number), 54 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 55 var num float64 56 if err := gocty.FromCtyValue(args[0], &num); err != nil { 57 return cty.UnknownVal(cty.String), err 58 } 59 60 var power float64 61 if err := gocty.FromCtyValue(args[1], &power); err != nil { 62 return cty.UnknownVal(cty.String), err 63 } 64 65 return cty.NumberFloatVal(math.Pow(num, power)), nil 66 }, 67 }) 68 69 // SignumFunc constructs a function that returns the closest whole number greater 70 // than or equal to the given value. 71 var SignumFunc = function.New(&function.Spec{ 72 Params: []function.Parameter{ 73 { 74 Name: "num", 75 Type: cty.Number, 76 }, 77 }, 78 Type: function.StaticReturnType(cty.Number), 79 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 80 var num int 81 if err := gocty.FromCtyValue(args[0], &num); err != nil { 82 return cty.UnknownVal(cty.String), err 83 } 84 switch { 85 case num < 0: 86 return cty.NumberIntVal(-1), nil 87 case num > 0: 88 return cty.NumberIntVal(+1), nil 89 default: 90 return cty.NumberIntVal(0), nil 91 } 92 }, 93 }) 94 95 // ParseIntFunc constructs a function that parses a string argument and returns an integer of the specified base. 96 var ParseIntFunc = function.New(&function.Spec{ 97 Params: []function.Parameter{ 98 { 99 Name: "number", 100 Type: cty.DynamicPseudoType, 101 }, 102 { 103 Name: "base", 104 Type: cty.Number, 105 }, 106 }, 107 108 Type: func(args []cty.Value) (cty.Type, error) { 109 if !args[0].Type().Equals(cty.String) { 110 return cty.Number, function.NewArgErrorf(0, "first argument must be a string, not %s", args[0].Type().FriendlyName()) 111 } 112 return cty.Number, nil 113 }, 114 115 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 116 var numstr string 117 var base int 118 var err error 119 120 if err = gocty.FromCtyValue(args[0], &numstr); err != nil { 121 return cty.UnknownVal(cty.String), function.NewArgError(0, err) 122 } 123 124 if err = gocty.FromCtyValue(args[1], &base); err != nil { 125 return cty.UnknownVal(cty.Number), function.NewArgError(1, err) 126 } 127 128 if base < 2 || base > 62 { 129 return cty.UnknownVal(cty.Number), function.NewArgErrorf( 130 1, 131 "base must be a whole number between 2 and 62 inclusive", 132 ) 133 } 134 135 num, ok := (&big.Int{}).SetString(numstr, base) 136 if !ok { 137 return cty.UnknownVal(cty.Number), function.NewArgErrorf( 138 0, 139 "cannot parse %q as a base %d integer", 140 numstr, 141 base, 142 ) 143 } 144 145 parsedNum := cty.NumberVal((&big.Float{}).SetInt(num)) 146 147 return parsedNum, nil 148 }, 149 }) 150 151 // Log returns returns the logarithm of a given number in a given base. 152 func Log(num, base cty.Value) (cty.Value, error) { 153 return LogFunc.Call([]cty.Value{num, base}) 154 } 155 156 // Pow returns the logarithm of a given number in a given base. 157 func Pow(num, power cty.Value) (cty.Value, error) { 158 return PowFunc.Call([]cty.Value{num, power}) 159 } 160 161 // Signum determines the sign of a number, returning a number between -1 and 162 // 1 to represent the sign. 163 func Signum(num cty.Value) (cty.Value, error) { 164 return SignumFunc.Call([]cty.Value{num}) 165 } 166 167 // ParseInt parses a string argument and returns an integer of the specified base. 168 func ParseInt(num cty.Value, base cty.Value) (cty.Value, error) { 169 return ParseIntFunc.Call([]cty.Value{num, base}) 170 }