porting functions
This commit is contained in:
parent
4ad3676934
commit
602b59cdc4
|
@ -27,7 +27,129 @@ var CeilFunc = function.New(&function.Spec{
|
|||
},
|
||||
})
|
||||
|
||||
// FloorFunc contructs a function that returns the closest whole number lesser
|
||||
// than or equal to the given value.
|
||||
var FloorFunc = 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 val float64
|
||||
if err := gocty.FromCtyValue(args[0], &val); err != nil {
|
||||
return cty.UnknownVal(cty.String), err
|
||||
}
|
||||
return cty.NumberIntVal(int64(math.Floor(val))), nil
|
||||
},
|
||||
})
|
||||
|
||||
// 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
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
// Ceil returns the closest whole number greater than or equal to the given value.
|
||||
func Ceil(num cty.Value) (cty.Value, error) {
|
||||
return CeilFunc.Call([]cty.Value{num})
|
||||
}
|
||||
|
||||
// Floor returns the closest whole number lesser than or equal to the given value.
|
||||
func Floor(num cty.Value) (cty.Value, error) {
|
||||
return FloorFunc.Call([]cty.Value{num})
|
||||
}
|
||||
|
||||
// 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})
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestCeil(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("Ceil(%#v)", test.Num), func(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("ceil(%#v)", test.Num), func(t *testing.T) {
|
||||
got, err := Ceil(test.Num)
|
||||
|
||||
if test.Err {
|
||||
|
@ -44,3 +44,216 @@ func TestCeil(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloor(t *testing.T) {
|
||||
tests := []struct {
|
||||
Num cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.NumberFloatVal(-1.8),
|
||||
cty.NumberFloatVal(-2),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(1.2),
|
||||
cty.NumberFloatVal(1),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("floor(%#v)", test.Num), func(t *testing.T) {
|
||||
got, err := Floor(test.Num)
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
tests := []struct {
|
||||
Num cty.Value
|
||||
Base cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.NumberFloatVal(1),
|
||||
cty.NumberFloatVal(10),
|
||||
cty.NumberFloatVal(0),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(10),
|
||||
cty.NumberFloatVal(10),
|
||||
cty.NumberFloatVal(1),
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
cty.NumberFloatVal(0),
|
||||
cty.NumberFloatVal(10),
|
||||
cty.NegativeInfinity,
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(10),
|
||||
cty.NumberFloatVal(0),
|
||||
cty.NumberFloatVal(-0),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("log(%#v, %#v)", test.Num, test.Base), func(t *testing.T) {
|
||||
got, err := Log(test.Num, test.Base)
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPow(t *testing.T) {
|
||||
tests := []struct {
|
||||
Num cty.Value
|
||||
Power cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.NumberFloatVal(1),
|
||||
cty.NumberFloatVal(0),
|
||||
cty.NumberFloatVal(1),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(1),
|
||||
cty.NumberFloatVal(1),
|
||||
cty.NumberFloatVal(1),
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
cty.NumberFloatVal(2),
|
||||
cty.NumberFloatVal(0),
|
||||
cty.NumberFloatVal(1),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(2),
|
||||
cty.NumberFloatVal(1),
|
||||
cty.NumberFloatVal(2),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(3),
|
||||
cty.NumberFloatVal(2),
|
||||
cty.NumberFloatVal(9),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(-3),
|
||||
cty.NumberFloatVal(2),
|
||||
cty.NumberFloatVal(9),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(2),
|
||||
cty.NumberFloatVal(-2),
|
||||
cty.NumberFloatVal(0.25),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(0),
|
||||
cty.NumberFloatVal(2),
|
||||
cty.NumberFloatVal(0),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("pow(%#v, %#v)", test.Num, test.Power), func(t *testing.T) {
|
||||
got, err := Pow(test.Num, test.Power)
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignum(t *testing.T) {
|
||||
tests := []struct {
|
||||
Num cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.NumberFloatVal(0),
|
||||
cty.NumberFloatVal(0),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(12),
|
||||
cty.NumberFloatVal(1),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.NumberFloatVal(-29),
|
||||
cty.NumberFloatVal(-1),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("signum(%#v)", test.Num), func(t *testing.T) {
|
||||
got, err := Signum(test.Num)
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package funcs
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
@ -110,6 +111,21 @@ var SplitFunc = function.New(&function.Spec{
|
|||
},
|
||||
})
|
||||
|
||||
// ChompFunc constructions a function that removes newline characters at the end of a string.
|
||||
var ChompFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
{
|
||||
Name: "str",
|
||||
Type: cty.String,
|
||||
},
|
||||
},
|
||||
Type: function.StaticReturnType(cty.String),
|
||||
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||
newlines := regexp.MustCompile(`(?:\r\n?|\n)*\z`)
|
||||
return cty.StringVal(newlines.ReplaceAllString(args[0].AsString(), "")), nil
|
||||
},
|
||||
})
|
||||
|
||||
// Join concatenates together the string elements of one or more lists with a
|
||||
// given separator.
|
||||
func Join(sep cty.Value, lists ...cty.Value) (cty.Value, error) {
|
||||
|
@ -130,3 +146,8 @@ func Sort(list cty.Value) (cty.Value, error) {
|
|||
func Split(sep, str cty.Value) (cty.Value, error) {
|
||||
return SplitFunc.Call([]cty.Value{sep, str})
|
||||
}
|
||||
|
||||
// Chomp removes newline characters at the end of a string.
|
||||
func Chomp(str cty.Value) (cty.Value, error) {
|
||||
return ChompFunc.Call([]cty.Value{str})
|
||||
}
|
||||
|
|
|
@ -244,3 +244,66 @@ func TestSplit(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChomp(t *testing.T) {
|
||||
tests := []struct {
|
||||
String cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.StringVal("hello world"),
|
||||
cty.StringVal("hello world"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("goodbye\ncruel\nworld"),
|
||||
cty.StringVal("goodbye\ncruel\nworld"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("goodbye\ncruel\nworld\n"),
|
||||
cty.StringVal("goodbye\ncruel\nworld"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("goodbye\ncruel\nworld\n\n\n\n"),
|
||||
cty.StringVal("goodbye\ncruel\nworld"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("goodbye\r\nwindows\r\nworld\r\n"),
|
||||
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("goodbye\r\nwindows\r\nworld\r\n\r\n\r\n\r\n"),
|
||||
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("chomp(%#v)", test.String), func(t *testing.T) {
|
||||
got, err := Chomp(test.String)
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
|||
"base64sha512": funcs.Base64Sha512Func,
|
||||
"bcrypt": funcs.BcryptFunc,
|
||||
"ceil": funcs.CeilFunc,
|
||||
"chomp": unimplFunc, // TODO
|
||||
"chomp": funcs.ChompFunc,
|
||||
"cidrhost": unimplFunc, // TODO
|
||||
"cidrnetmask": unimplFunc, // TODO
|
||||
"cidrsubnet": unimplFunc, // TODO
|
||||
|
@ -56,7 +56,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
|||
"filebase64": funcs.MakeFileFunc(s.BaseDir, true),
|
||||
"matchkeys": unimplFunc, // TODO
|
||||
"flatten": unimplFunc, // TODO
|
||||
"floor": unimplFunc, // TODO
|
||||
"floor": funcs.FloorFunc,
|
||||
"format": stdlib.FormatFunc,
|
||||
"formatlist": stdlib.FormatListFunc,
|
||||
"indent": unimplFunc, // TODO
|
||||
|
@ -67,7 +67,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
|||
"keys": unimplFunc, // TODO
|
||||
"length": funcs.LengthFunc,
|
||||
"list": unimplFunc, // TODO
|
||||
"log": unimplFunc, // TODO
|
||||
"log": funcs.LogFunc,
|
||||
"lookup": unimplFunc, // TODO
|
||||
"lower": stdlib.LowerFunc,
|
||||
"map": unimplFunc, // TODO
|
||||
|
@ -76,7 +76,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
|||
"merge": unimplFunc, // TODO
|
||||
"min": stdlib.MinFunc,
|
||||
"pathexpand": funcs.PathExpandFunc,
|
||||
"pow": unimplFunc, // TODO
|
||||
"pow": funcs.PowFunc,
|
||||
"replace": unimplFunc, // TODO
|
||||
"rsadecrypt": funcs.RsaDecryptFunc,
|
||||
"sha1": funcs.Sha1Func,
|
||||
|
|
|
@ -3,13 +3,12 @@ layout: "functions"
|
|||
page_title: "log function"
|
||||
sidebar_current: "docs-funcs-numeric-log"
|
||||
description: |-
|
||||
The log function returns the closest whole number less than or equal to
|
||||
the given value.
|
||||
The log function returns the logarithm of a given number in a given base.
|
||||
---
|
||||
|
||||
# `log` Function
|
||||
|
||||
`log` returns the the logarithm of a given number in a given base.
|
||||
`log` returns the logarithm of a given number in a given base.
|
||||
|
||||
```hcl
|
||||
log(number, base)
|
||||
|
|
Loading…
Reference in New Issue