| package funcs |
| |
| import ( |
| "math" |
| "math/big" |
| |
| "github.com/zclconf/go-cty/cty" |
| "github.com/zclconf/go-cty/cty/function" |
| "github.com/zclconf/go-cty/cty/gocty" |
| ) |
| |
| // LogFunc contructs a function that returns the logarithm of a given number in a given base. |
| var LogFunc = function.New(&function.Spec{ |
| Params: []function.Parameter{ |
| { |
| Name: "num", |
| Type: cty.Number, |
| }, |
| { |
| Name: "base", |
| Type: cty.Number, |
| }, |
| }, |
| Type: function.StaticReturnType(cty.Number), |
| Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { |
| var num float64 |
| if err := gocty.FromCtyValue(args[0], &num); err != nil { |
| return cty.UnknownVal(cty.String), err |
| } |
| |
| var base float64 |
| if err := gocty.FromCtyValue(args[1], &base); err != nil { |
| return cty.UnknownVal(cty.String), err |
| } |
| |
| return cty.NumberFloatVal(math.Log(num) / math.Log(base)), nil |
| }, |
| }) |
| |
| // PowFunc contructs a function that returns the logarithm of a given number in a given base. |
| var PowFunc = function.New(&function.Spec{ |
| Params: []function.Parameter{ |
| { |
| Name: "num", |
| Type: cty.Number, |
| }, |
| { |
| Name: "power", |
| Type: cty.Number, |
| }, |
| }, |
| Type: function.StaticReturnType(cty.Number), |
| Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { |
| var num float64 |
| if err := gocty.FromCtyValue(args[0], &num); err != nil { |
| return cty.UnknownVal(cty.String), err |
| } |
| |
| var power float64 |
| if err := gocty.FromCtyValue(args[1], &power); err != nil { |
| return cty.UnknownVal(cty.String), err |
| } |
| |
| return cty.NumberFloatVal(math.Pow(num, power)), nil |
| }, |
| }) |
| |
| // SignumFunc contructs a function that returns the closest whole number greater |
| // than or equal to the given value. |
| var SignumFunc = function.New(&function.Spec{ |
| Params: []function.Parameter{ |
| { |
| Name: "num", |
| Type: cty.Number, |
| }, |
| }, |
| Type: function.StaticReturnType(cty.Number), |
| Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { |
| var num int |
| if err := gocty.FromCtyValue(args[0], &num); err != nil { |
| return cty.UnknownVal(cty.String), err |
| } |
| switch { |
| case num < 0: |
| return cty.NumberIntVal(-1), nil |
| case num > 0: |
| return cty.NumberIntVal(+1), nil |
| default: |
| return cty.NumberIntVal(0), nil |
| } |
| }, |
| }) |
| |
| // ParseIntFunc contructs a function that parses a string argument and returns an integer of the specified base. |
| var ParseIntFunc = function.New(&function.Spec{ |
| Params: []function.Parameter{ |
| { |
| Name: "number", |
| Type: cty.DynamicPseudoType, |
| AllowMarked: true, |
| }, |
| { |
| Name: "base", |
| Type: cty.Number, |
| AllowMarked: true, |
| }, |
| }, |
| |
| Type: func(args []cty.Value) (cty.Type, error) { |
| if !args[0].Type().Equals(cty.String) { |
| return cty.Number, function.NewArgErrorf(0, "first argument must be a string, not %s", args[0].Type().FriendlyName()) |
| } |
| return cty.Number, nil |
| }, |
| |
| Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { |
| var numstr string |
| var base int |
| var err error |
| |
| numArg, numMarks := args[0].Unmark() |
| if err = gocty.FromCtyValue(numArg, &numstr); err != nil { |
| return cty.UnknownVal(cty.String), function.NewArgError(0, err) |
| } |
| |
| baseArg, baseMarks := args[1].Unmark() |
| if err = gocty.FromCtyValue(baseArg, &base); err != nil { |
| return cty.UnknownVal(cty.Number), function.NewArgError(1, err) |
| } |
| |
| if base < 2 || base > 62 { |
| return cty.UnknownVal(cty.Number), function.NewArgErrorf( |
| 1, |
| "base must be a whole number between 2 and 62 inclusive", |
| ) |
| } |
| |
| num, ok := (&big.Int{}).SetString(numstr, base) |
| if !ok { |
| return cty.UnknownVal(cty.Number), function.NewArgErrorf( |
| 0, |
| "cannot parse %s as a base %s integer", |
| redactIfSensitive(numstr, numMarks), |
| redactIfSensitive(base, baseMarks), |
| ) |
| } |
| |
| parsedNum := cty.NumberVal((&big.Float{}).SetInt(num)).WithMarks(numMarks, baseMarks) |
| |
| return parsedNum, nil |
| }, |
| }) |
| |
| // Log returns returns the logarithm of a given number in a given base. |
| func Log(num, base cty.Value) (cty.Value, error) { |
| return LogFunc.Call([]cty.Value{num, base}) |
| } |
| |
| // Pow returns the logarithm of a given number in a given base. |
| func Pow(num, power cty.Value) (cty.Value, error) { |
| return PowFunc.Call([]cty.Value{num, power}) |
| } |
| |
| // Signum determines the sign of a number, returning a number between -1 and |
| // 1 to represent the sign. |
| func Signum(num cty.Value) (cty.Value, error) { |
| return SignumFunc.Call([]cty.Value{num}) |
| } |
| |
| // ParseInt parses a string argument and returns an integer of the specified base. |
| func ParseInt(num cty.Value, base cty.Value) (cty.Value, error) { |
| return ParseIntFunc.Call([]cty.Value{num, base}) |
| } |