aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/function
diff options
context:
space:
mode:
authorAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
committerAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
commit15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch)
tree255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/zclconf/go-cty/cty/function
parent07971ca38143c5faf951d152fba370ddcbe26ad5 (diff)
downloadterraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.gz
terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.zst
terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.zip
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
Updated via: go get github.com/hashicorp/terraform@sdk-v0.11-with-go-modules and go mod tidy
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/function')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/argument.go50
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/doc.go6
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/error.go50
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/function.go291
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go73
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go112
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go140
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go93
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go13
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go496
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go358
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl182
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go107
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go72
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go428
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go130
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go195
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go234
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go31
19 files changed, 3061 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/argument.go b/vendor/github.com/zclconf/go-cty/cty/function/argument.go
new file mode 100644
index 0000000..bfd3015
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/argument.go
@@ -0,0 +1,50 @@
1package function
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// Parameter represents a parameter to a function.
8type Parameter struct {
9 // Name is an optional name for the argument. This package ignores this
10 // value, but callers may use it for documentation, etc.
11 Name string
12
13 // A type that any argument for this parameter must conform to.
14 // cty.DynamicPseudoType can be used, either at top-level or nested
15 // in a parameterized type, to indicate that any type should be
16 // permitted, to allow the definition of type-generic functions.
17 Type cty.Type
18
19 // If AllowNull is set then null values may be passed into this
20 // argument's slot in both the type-check function and the implementation
21 // function. If not set, such values are rejected by the built-in
22 // checking rules.
23 AllowNull bool
24
25 // If AllowUnknown is set then unknown values may be passed into this
26 // argument's slot in the implementation function. If not set, any
27 // unknown values will cause the function to immediately return
28 // an unkonwn value without calling the implementation function, thus
29 // freeing the function implementer from dealing with this case.
30 AllowUnknown bool
31
32 // If AllowDynamicType is set then DynamicVal may be passed into this
33 // argument's slot in the implementation function. If not set, any
34 // dynamic values will cause the function to immediately return
35 // DynamicVal value without calling the implementation function, thus
36 // freeing the function implementer from dealing with this case.
37 //
38 // Note that DynamicVal is also unknown, so in order to receive dynamic
39 // *values* it is also necessary to set AllowUnknown.
40 //
41 // However, it is valid to set AllowDynamicType without AllowUnknown, in
42 // which case a dynamic value may be passed to the type checking function
43 // but will not make it to the *implementation* function. Instead, an
44 // unknown value of the type returned by the type-check function will be
45 // returned. This is suggested for functions that have a static return
46 // type since it allows the return value to be typed even if the input
47 // values are not, thus improving the type-check accuracy of derived
48 // values.
49 AllowDynamicType bool
50}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/doc.go b/vendor/github.com/zclconf/go-cty/cty/function/doc.go
new file mode 100644
index 0000000..393b311
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/doc.go
@@ -0,0 +1,6 @@
1// Package function builds on the functionality of cty by modeling functions
2// that operate on cty Values.
3//
4// Functions are, at their core, Go anonymous functions. However, this package
5// wraps around them utility functions for parameter type checking, etc.
6package function
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/error.go b/vendor/github.com/zclconf/go-cty/cty/function/error.go
new file mode 100644
index 0000000..2b56779
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/error.go
@@ -0,0 +1,50 @@
1package function
2
3import (
4 "fmt"
5 "runtime/debug"
6)
7
8// ArgError represents an error with one of the arguments in a call. The
9// attribute Index represents the zero-based index of the argument in question.
10//
11// Its error *may* be a cty.PathError, in which case the error actually
12// pertains to a nested value within the data structure passed as the argument.
13type ArgError struct {
14 error
15 Index int
16}
17
18func NewArgErrorf(i int, f string, args ...interface{}) error {
19 return ArgError{
20 error: fmt.Errorf(f, args...),
21 Index: i,
22 }
23}
24
25func NewArgError(i int, err error) error {
26 return ArgError{
27 error: err,
28 Index: i,
29 }
30}
31
32// PanicError indicates that a panic occurred while executing either a
33// function's type or implementation function. This is captured and wrapped
34// into a normal error so that callers (expected to be language runtimes)
35// are freed from having to deal with panics in buggy functions.
36type PanicError struct {
37 Value interface{}
38 Stack []byte
39}
40
41func errorForPanic(val interface{}) error {
42 return PanicError{
43 Value: val,
44 Stack: debug.Stack(),
45 }
46}
47
48func (e PanicError) Error() string {
49 return fmt.Sprintf("panic in function implementation: %s\n%s", e.Value, e.Stack)
50}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/function.go b/vendor/github.com/zclconf/go-cty/cty/function/function.go
new file mode 100644
index 0000000..162f7bf
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/function.go
@@ -0,0 +1,291 @@
1package function
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7)
8
9// Function represents a function. This is the main type in this package.
10type Function struct {
11 spec *Spec
12}
13
14// Spec is the specification of a function, used to instantiate
15// a new Function.
16type Spec struct {
17 // Params is a description of the positional parameters for the function.
18 // The standard checking logic rejects any calls that do not provide
19 // arguments conforming to this definition, freeing the function
20 // implementer from dealing with such inconsistencies.
21 Params []Parameter
22
23 // VarParam is an optional specification of additional "varargs" the
24 // function accepts. If this is non-nil then callers may provide an
25 // arbitrary number of additional arguments (after those matching with
26 // the fixed parameters in Params) that conform to the given specification,
27 // which will appear as additional values in the slices of values
28 // provided to the type and implementation functions.
29 VarParam *Parameter
30
31 // Type is the TypeFunc that decides the return type of the function
32 // given its arguments, which may be Unknown. See the documentation
33 // of TypeFunc for more information.
34 //
35 // Use StaticReturnType if the function's return type does not vary
36 // depending on its arguments.
37 Type TypeFunc
38
39 // Impl is the ImplFunc that implements the function's behavior.
40 //
41 // Functions are expected to behave as pure functions, and not create
42 // any visible side-effects.
43 //
44 // If a TypeFunc is also provided, the value returned from Impl *must*
45 // conform to the type it returns, or a call to the function will panic.
46 Impl ImplFunc
47}
48
49// New creates a new function with the given specification.
50//
51// After passing a Spec to this function, the caller must no longer read from
52// or mutate it.
53func New(spec *Spec) Function {
54 f := Function{
55 spec: spec,
56 }
57 return f
58}
59
60// TypeFunc is a callback type for determining the return type of a function
61// given its arguments.
62//
63// Any of the values passed to this function may be unknown, even if the
64// parameters are not configured to accept unknowns.
65//
66// If any of the given values are *not* unknown, the TypeFunc may use the
67// values for pre-validation and for choosing the return type. For example,
68// a hypothetical JSON-unmarshalling function could return
69// cty.DynamicPseudoType if the given JSON string is unknown, but return
70// a concrete type based on the JSON structure if the JSON string is already
71// known.
72type TypeFunc func(args []cty.Value) (cty.Type, error)
73
74// ImplFunc is a callback type for the main implementation of a function.
75//
76// "args" are the values for the arguments, and this slice will always be at
77// least as long as the argument definition slice for the function.
78//
79// "retType" is the type returned from the Type callback, included as a
80// convenience to avoid the need to re-compute the return type for generic
81// functions whose return type is a function of the arguments.
82type ImplFunc func(args []cty.Value, retType cty.Type) (cty.Value, error)
83
84// StaticReturnType returns a TypeFunc that always returns the given type.
85//
86// This is provided as a convenience for defining a function whose return
87// type does not depend on the argument types.
88func StaticReturnType(ty cty.Type) TypeFunc {
89 return func([]cty.Value) (cty.Type, error) {
90 return ty, nil
91 }
92}
93
94// ReturnType returns the return type of a function given a set of candidate
95// argument types, or returns an error if the given types are unacceptable.
96//
97// If the caller already knows values for at least some of the arguments
98// it can be better to call ReturnTypeForValues, since certain functions may
99// determine their return types from their values and return DynamicVal if
100// the values are unknown.
101func (f Function) ReturnType(argTypes []cty.Type) (cty.Type, error) {
102 vals := make([]cty.Value, len(argTypes))
103 for i, ty := range argTypes {
104 vals[i] = cty.UnknownVal(ty)
105 }
106 return f.ReturnTypeForValues(vals)
107}
108
109// ReturnTypeForValues is similar to ReturnType but can be used if the caller
110// already knows the values of some or all of the arguments, in which case
111// the function may be able to determine a more definite result if its
112// return type depends on the argument *values*.
113//
114// For any arguments whose values are not known, pass an Unknown value of
115// the appropriate type.
116func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error) {
117 var posArgs []cty.Value
118 var varArgs []cty.Value
119
120 if f.spec.VarParam == nil {
121 if len(args) != len(f.spec.Params) {
122 return cty.Type{}, fmt.Errorf(
123 "wrong number of arguments (%d required; %d given)",
124 len(f.spec.Params), len(args),
125 )
126 }
127
128 posArgs = args
129 varArgs = nil
130 } else {
131 if len(args) < len(f.spec.Params) {
132 return cty.Type{}, fmt.Errorf(
133 "wrong number of arguments (at least %d required; %d given)",
134 len(f.spec.Params), len(args),
135 )
136 }
137
138 posArgs = args[0:len(f.spec.Params)]
139 varArgs = args[len(f.spec.Params):]
140 }
141
142 for i, spec := range f.spec.Params {
143 val := posArgs[i]
144
145 if val.IsNull() && !spec.AllowNull {
146 return cty.Type{}, NewArgErrorf(i, "must not be null")
147 }
148
149 // AllowUnknown is ignored for type-checking, since we expect to be
150 // able to type check with unknown values. We *do* still need to deal
151 // with DynamicPseudoType here though, since the Type function might
152 // not be ready to deal with that.
153
154 if val.Type() == cty.DynamicPseudoType {
155 if !spec.AllowDynamicType {
156 return cty.DynamicPseudoType, nil
157 }
158 } else if errs := val.Type().TestConformance(spec.Type); errs != nil {
159 // For now we'll just return the first error in the set, since
160 // we don't have a good way to return the whole list here.
161 // Would be good to do something better at some point...
162 return cty.Type{}, NewArgError(i, errs[0])
163 }
164 }
165
166 if varArgs != nil {
167 spec := f.spec.VarParam
168 for i, val := range varArgs {
169 realI := i + len(posArgs)
170
171 if val.IsNull() && !spec.AllowNull {
172 return cty.Type{}, NewArgErrorf(realI, "must not be null")
173 }
174
175 if val.Type() == cty.DynamicPseudoType {
176 if !spec.AllowDynamicType {
177 return cty.DynamicPseudoType, nil
178 }
179 } else if errs := val.Type().TestConformance(spec.Type); errs != nil {
180 // For now we'll just return the first error in the set, since
181 // we don't have a good way to return the whole list here.
182 // Would be good to do something better at some point...
183 return cty.Type{}, NewArgError(i, errs[0])
184 }
185 }
186 }
187
188 // Intercept any panics from the function and return them as normal errors,
189 // so a calling language runtime doesn't need to deal with panics.
190 defer func() {
191 if r := recover(); r != nil {
192 ty = cty.NilType
193 err = errorForPanic(r)
194 }
195 }()
196
197 return f.spec.Type(args)
198}
199
200// Call actually calls the function with the given arguments, which must
201// conform to the function's parameter specification or an error will be
202// returned.
203func (f Function) Call(args []cty.Value) (val cty.Value, err error) {
204 expectedType, err := f.ReturnTypeForValues(args)
205 if err != nil {
206 return cty.NilVal, err
207 }
208
209 // Type checking already dealt with most situations relating to our
210 // parameter specification, but we still need to deal with unknown
211 // values.
212 posArgs := args[:len(f.spec.Params)]
213 varArgs := args[len(f.spec.Params):]
214
215 for i, spec := range f.spec.Params {
216 val := posArgs[i]
217
218 if !val.IsKnown() && !spec.AllowUnknown {
219 return cty.UnknownVal(expectedType), nil
220 }
221 }
222
223 if f.spec.VarParam != nil {
224 spec := f.spec.VarParam
225 for _, val := range varArgs {
226 if !val.IsKnown() && !spec.AllowUnknown {
227 return cty.UnknownVal(expectedType), nil
228 }
229 }
230 }
231
232 var retVal cty.Value
233 {
234 // Intercept any panics from the function and return them as normal errors,
235 // so a calling language runtime doesn't need to deal with panics.
236 defer func() {
237 if r := recover(); r != nil {
238 val = cty.NilVal
239 err = errorForPanic(r)
240 }
241 }()
242
243 retVal, err = f.spec.Impl(args, expectedType)
244 if err != nil {
245 return cty.NilVal, err
246 }
247 }
248
249 // Returned value must conform to what the Type function expected, to
250 // protect callers from having to deal with inconsistencies.
251 if errs := retVal.Type().TestConformance(expectedType); errs != nil {
252 panic(fmt.Errorf(
253 "returned value %#v does not conform to expected return type %#v: %s",
254 retVal, expectedType, errs[0],
255 ))
256 }
257
258 return retVal, nil
259}
260
261// ProxyFunc the type returned by the method Function.Proxy.
262type ProxyFunc func(args ...cty.Value) (cty.Value, error)
263
264// Proxy returns a function that can be called with cty.Value arguments
265// to run the function. This is provided as a convenience for when using
266// a function directly within Go code.
267func (f Function) Proxy() ProxyFunc {
268 return func(args ...cty.Value) (cty.Value, error) {
269 return f.Call(args)
270 }
271}
272
273// Params returns information about the function's fixed positional parameters.
274// This does not include information about any variadic arguments accepted;
275// for that, call VarParam.
276func (f Function) Params() []Parameter {
277 new := make([]Parameter, len(f.spec.Params))
278 copy(new, f.spec.Params)
279 return new
280}
281
282// VarParam returns information about the variadic arguments the function
283// expects, or nil if the function is not variadic.
284func (f Function) VarParam() *Parameter {
285 if f.spec.VarParam == nil {
286 return nil
287 }
288
289 ret := *f.spec.VarParam
290 return &ret
291}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go
new file mode 100644
index 0000000..a473d0e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go
@@ -0,0 +1,73 @@
1package stdlib
2
3import (
4 "github.com/zclconf/go-cty/cty"
5 "github.com/zclconf/go-cty/cty/function"
6)
7
8var NotFunc = function.New(&function.Spec{
9 Params: []function.Parameter{
10 {
11 Name: "val",
12 Type: cty.Bool,
13 AllowDynamicType: true,
14 },
15 },
16 Type: function.StaticReturnType(cty.Bool),
17 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
18 return args[0].Not(), nil
19 },
20})
21
22var AndFunc = function.New(&function.Spec{
23 Params: []function.Parameter{
24 {
25 Name: "a",
26 Type: cty.Bool,
27 AllowDynamicType: true,
28 },
29 {
30 Name: "b",
31 Type: cty.Bool,
32 AllowDynamicType: true,
33 },
34 },
35 Type: function.StaticReturnType(cty.Bool),
36 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
37 return args[0].And(args[1]), nil
38 },
39})
40
41var OrFunc = function.New(&function.Spec{
42 Params: []function.Parameter{
43 {
44 Name: "a",
45 Type: cty.Bool,
46 AllowDynamicType: true,
47 },
48 {
49 Name: "b",
50 Type: cty.Bool,
51 AllowDynamicType: true,
52 },
53 },
54 Type: function.StaticReturnType(cty.Bool),
55 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
56 return args[0].Or(args[1]), nil
57 },
58})
59
60// Not returns the logical complement of the given boolean value.
61func Not(num cty.Value) (cty.Value, error) {
62 return NotFunc.Call([]cty.Value{num})
63}
64
65// And returns true if and only if both of the given boolean values are true.
66func And(a, b cty.Value) (cty.Value, error) {
67 return AndFunc.Call([]cty.Value{a, b})
68}
69
70// Or returns true if either of the given boolean values are true.
71func Or(a, b cty.Value) (cty.Value, error) {
72 return OrFunc.Call([]cty.Value{a, b})
73}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go
new file mode 100644
index 0000000..a132e0c
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go
@@ -0,0 +1,112 @@
1package stdlib
2
3import (
4 "fmt"
5 "reflect"
6
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/function"
9 "github.com/zclconf/go-cty/cty/gocty"
10)
11
12// Bytes is a capsule type that can be used with the binary functions to
13// support applications that need to support raw buffers in addition to
14// UTF-8 strings.
15var Bytes = cty.Capsule("bytes", reflect.TypeOf([]byte(nil)))
16
17// BytesVal creates a new Bytes value from the given buffer, which must be
18// non-nil or this function will panic.
19//
20// Once a byte slice has been wrapped in a Bytes capsule, its underlying array
21// must be considered immutable.
22func BytesVal(buf []byte) cty.Value {
23 if buf == nil {
24 panic("can't make Bytes value from nil slice")
25 }
26
27 return cty.CapsuleVal(Bytes, &buf)
28}
29
30// BytesLen is a Function that returns the length of the buffer encapsulated
31// in a Bytes value.
32var BytesLenFunc = function.New(&function.Spec{
33 Params: []function.Parameter{
34 {
35 Name: "buf",
36 Type: Bytes,
37 AllowDynamicType: true,
38 },
39 },
40 Type: function.StaticReturnType(cty.Number),
41 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
42 bufPtr := args[0].EncapsulatedValue().(*[]byte)
43 return cty.NumberIntVal(int64(len(*bufPtr))), nil
44 },
45})
46
47// BytesSlice is a Function that returns a slice of the given Bytes value.
48var BytesSliceFunc = function.New(&function.Spec{
49 Params: []function.Parameter{
50 {
51 Name: "buf",
52 Type: Bytes,
53 AllowDynamicType: true,
54 },
55 {
56 Name: "offset",
57 Type: cty.Number,
58 AllowDynamicType: true,
59 },
60 {
61 Name: "length",
62 Type: cty.Number,
63 AllowDynamicType: true,
64 },
65 },
66 Type: function.StaticReturnType(Bytes),
67 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
68 bufPtr := args[0].EncapsulatedValue().(*[]byte)
69
70 var offset, length int
71
72 var err error
73 err = gocty.FromCtyValue(args[1], &offset)
74 if err != nil {
75 return cty.NilVal, err
76 }
77 err = gocty.FromCtyValue(args[2], &length)
78 if err != nil {
79 return cty.NilVal, err
80 }
81
82 if offset < 0 || length < 0 {
83 return cty.NilVal, fmt.Errorf("offset and length must be non-negative")
84 }
85
86 if offset > len(*bufPtr) {
87 return cty.NilVal, fmt.Errorf(
88 "offset %d is greater than total buffer length %d",
89 offset, len(*bufPtr),
90 )
91 }
92
93 end := offset + length
94
95 if end > len(*bufPtr) {
96 return cty.NilVal, fmt.Errorf(
97 "offset %d + length %d is greater than total buffer length %d",
98 offset, length, len(*bufPtr),
99 )
100 }
101
102 return BytesVal((*bufPtr)[offset:end]), nil
103 },
104})
105
106func BytesLen(buf cty.Value) (cty.Value, error) {
107 return BytesLenFunc.Call([]cty.Value{buf})
108}
109
110func BytesSlice(buf cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) {
111 return BytesSliceFunc.Call([]cty.Value{buf, offset, length})
112}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
new file mode 100644
index 0000000..967ba03
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
@@ -0,0 +1,140 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/function"
8 "github.com/zclconf/go-cty/cty/gocty"
9)
10
11var HasIndexFunc = function.New(&function.Spec{
12 Params: []function.Parameter{
13 {
14 Name: "collection",
15 Type: cty.DynamicPseudoType,
16 AllowDynamicType: true,
17 },
18 {
19 Name: "key",
20 Type: cty.DynamicPseudoType,
21 AllowDynamicType: true,
22 },
23 },
24 Type: func(args []cty.Value) (ret cty.Type, err error) {
25 collTy := args[0].Type()
26 if !(collTy.IsTupleType() || collTy.IsListType() || collTy.IsMapType() || collTy == cty.DynamicPseudoType) {
27 return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
28 }
29 return cty.Bool, nil
30 },
31 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
32 return args[0].HasIndex(args[1]), nil
33 },
34})
35
36var IndexFunc = function.New(&function.Spec{
37 Params: []function.Parameter{
38 {
39 Name: "collection",
40 Type: cty.DynamicPseudoType,
41 },
42 {
43 Name: "key",
44 Type: cty.DynamicPseudoType,
45 AllowDynamicType: true,
46 },
47 },
48 Type: func(args []cty.Value) (ret cty.Type, err error) {
49 collTy := args[0].Type()
50 key := args[1]
51 keyTy := key.Type()
52 switch {
53 case collTy.IsTupleType():
54 if keyTy != cty.Number && keyTy != cty.DynamicPseudoType {
55 return cty.NilType, fmt.Errorf("key for tuple must be number")
56 }
57 if !key.IsKnown() {
58 return cty.DynamicPseudoType, nil
59 }
60 var idx int
61 err := gocty.FromCtyValue(key, &idx)
62 if err != nil {
63 return cty.NilType, fmt.Errorf("invalid key for tuple: %s", err)
64 }
65
66 etys := collTy.TupleElementTypes()
67
68 if idx >= len(etys) || idx < 0 {
69 return cty.NilType, fmt.Errorf("key must be between 0 and %d inclusive", len(etys))
70 }
71
72 return etys[idx], nil
73
74 case collTy.IsListType():
75 if keyTy != cty.Number && keyTy != cty.DynamicPseudoType {
76 return cty.NilType, fmt.Errorf("key for list must be number")
77 }
78
79 return collTy.ElementType(), nil
80
81 case collTy.IsMapType():
82 if keyTy != cty.String && keyTy != cty.DynamicPseudoType {
83 return cty.NilType, fmt.Errorf("key for map must be string")
84 }
85
86 return collTy.ElementType(), nil
87
88 default:
89 return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
90 }
91 },
92 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
93 has, err := HasIndex(args[0], args[1])
94 if err != nil {
95 return cty.NilVal, err
96 }
97 if has.False() { // safe because collection and key are guaranteed known here
98 return cty.NilVal, fmt.Errorf("invalid index")
99 }
100
101 return args[0].Index(args[1]), nil
102 },
103})
104
105var LengthFunc = function.New(&function.Spec{
106 Params: []function.Parameter{
107 {
108 Name: "collection",
109 Type: cty.DynamicPseudoType,
110 AllowDynamicType: true,
111 },
112 },
113 Type: func(args []cty.Value) (ret cty.Type, err error) {
114 collTy := args[0].Type()
115 if !(collTy.IsTupleType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType) {
116 return cty.NilType, fmt.Errorf("collection must be a list, a map or a tuple")
117 }
118 return cty.Number, nil
119 },
120 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
121 return args[0].Length(), nil
122 },
123})
124
125// HasIndex determines whether the given collection can be indexed with the
126// given key.
127func HasIndex(collection cty.Value, key cty.Value) (cty.Value, error) {
128 return HasIndexFunc.Call([]cty.Value{collection, key})
129}
130
131// Index returns an element from the given collection using the given key,
132// or returns an error if there is no element for the given key.
133func Index(collection cty.Value, key cty.Value) (cty.Value, error) {
134 return IndexFunc.Call([]cty.Value{collection, key})
135}
136
137// Length returns the number of elements in the given collection.
138func Length(collection cty.Value) (cty.Value, error) {
139 return LengthFunc.Call([]cty.Value{collection})
140}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
new file mode 100644
index 0000000..5070a5a
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
@@ -0,0 +1,93 @@
1package stdlib
2
3import (
4 "encoding/csv"
5 "fmt"
6 "io"
7 "strings"
8
9 "github.com/zclconf/go-cty/cty"
10 "github.com/zclconf/go-cty/cty/function"
11)
12
13var CSVDecodeFunc = function.New(&function.Spec{
14 Params: []function.Parameter{
15 {
16 Name: "str",
17 Type: cty.String,
18 },
19 },
20 Type: func(args []cty.Value) (cty.Type, error) {
21 str := args[0]
22 if !str.IsKnown() {
23 return cty.DynamicPseudoType, nil
24 }
25
26 r := strings.NewReader(str.AsString())
27 cr := csv.NewReader(r)
28 headers, err := cr.Read()
29 if err == io.EOF {
30 return cty.DynamicPseudoType, fmt.Errorf("missing header line")
31 }
32 if err != nil {
33 return cty.DynamicPseudoType, err
34 }
35
36 atys := make(map[string]cty.Type, len(headers))
37 for _, name := range headers {
38 if _, exists := atys[name]; exists {
39 return cty.DynamicPseudoType, fmt.Errorf("duplicate column name %q", name)
40 }
41 atys[name] = cty.String
42 }
43 return cty.List(cty.Object(atys)), nil
44 },
45 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
46 ety := retType.ElementType()
47 atys := ety.AttributeTypes()
48 str := args[0]
49 r := strings.NewReader(str.AsString())
50 cr := csv.NewReader(r)
51 cr.FieldsPerRecord = len(atys)
52
53 // Read the header row first, since that'll tell us which indices
54 // map to which attribute names.
55 headers, err := cr.Read()
56 if err != nil {
57 return cty.DynamicVal, err
58 }
59
60 var rows []cty.Value
61 for {
62 cols, err := cr.Read()
63 if err == io.EOF {
64 break
65 }
66 if err != nil {
67 return cty.DynamicVal, err
68 }
69
70 vals := make(map[string]cty.Value, len(cols))
71 for i, str := range cols {
72 name := headers[i]
73 vals[name] = cty.StringVal(str)
74 }
75 rows = append(rows, cty.ObjectVal(vals))
76 }
77
78 if len(rows) == 0 {
79 return cty.ListValEmpty(ety), nil
80 }
81 return cty.ListVal(rows), nil
82 },
83})
84
85// CSVDecode parses the given CSV (RFC 4180) string and, if it is valid,
86// returns a list of objects representing the rows.
87//
88// The result is always a list of some object type. The first row of the
89// input is used to determine the object attributes, and subsequent rows
90// determine the values of those attributes.
91func CSVDecode(str cty.Value) (cty.Value, error) {
92 return CSVDecodeFunc.Call([]cty.Value{str})
93}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go
new file mode 100644
index 0000000..cfb613e
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/doc.go
@@ -0,0 +1,13 @@
1// Package stdlib is a collection of cty functions that are expected to be
2// generally useful, and are thus factored out into this shared library in
3// the hope that cty-using applications will have consistent behavior when
4// using these functions.
5//
6// See the parent package "function" for more information on the purpose
7// and usage of cty functions.
8//
9// This package contains both Go functions, which provide convenient access
10// to call the functions from Go code, and the Function objects themselves.
11// The latter follow the naming scheme of appending "Func" to the end of
12// the function name.
13package stdlib
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
new file mode 100644
index 0000000..fb24f20
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
@@ -0,0 +1,496 @@
1package stdlib
2
3import (
4 "bytes"
5 "fmt"
6 "math/big"
7 "strings"
8
9 "github.com/apparentlymart/go-textseg/textseg"
10
11 "github.com/zclconf/go-cty/cty"
12 "github.com/zclconf/go-cty/cty/convert"
13 "github.com/zclconf/go-cty/cty/function"
14 "github.com/zclconf/go-cty/cty/json"
15)
16
17//go:generate ragel -Z format_fsm.rl
18//go:generate gofmt -w format_fsm.go
19
20var FormatFunc = function.New(&function.Spec{
21 Params: []function.Parameter{
22 {
23 Name: "format",
24 Type: cty.String,
25 },
26 },
27 VarParam: &function.Parameter{
28 Name: "args",
29 Type: cty.DynamicPseudoType,
30 AllowNull: true,
31 },
32 Type: function.StaticReturnType(cty.String),
33 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
34 for _, arg := range args[1:] {
35 if !arg.IsWhollyKnown() {
36 // We require all nested values to be known because the only
37 // thing we can do for a collection/structural type is print
38 // it as JSON and that requires it to be wholly known.
39 return cty.UnknownVal(cty.String), nil
40 }
41 }
42 str, err := formatFSM(args[0].AsString(), args[1:])
43 return cty.StringVal(str), err
44 },
45})
46
47var FormatListFunc = function.New(&function.Spec{
48 Params: []function.Parameter{
49 {
50 Name: "format",
51 Type: cty.String,
52 },
53 },
54 VarParam: &function.Parameter{
55 Name: "args",
56 Type: cty.DynamicPseudoType,
57 AllowNull: true,
58 AllowUnknown: true,
59 },
60 Type: function.StaticReturnType(cty.List(cty.String)),
61 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
62 fmtVal := args[0]
63 args = args[1:]
64
65 if len(args) == 0 {
66 // With no arguments, this function is equivalent to Format, but
67 // returning a single-element list result.
68 result, err := Format(fmtVal, args...)
69 return cty.ListVal([]cty.Value{result}), err
70 }
71
72 fmtStr := fmtVal.AsString()
73
74 // Each of our arguments will be dealt with either as an iterator
75 // or as a single value. Iterators are used for sequence-type values
76 // (lists, sets, tuples) while everything else is treated as a
77 // single value. The sequences we iterate over are required to be
78 // all the same length.
79 iterLen := -1
80 lenChooser := -1
81 iterators := make([]cty.ElementIterator, len(args))
82 singleVals := make([]cty.Value, len(args))
83 for i, arg := range args {
84 argTy := arg.Type()
85 switch {
86 case (argTy.IsListType() || argTy.IsSetType() || argTy.IsTupleType()) && !arg.IsNull():
87 thisLen := arg.LengthInt()
88 if iterLen == -1 {
89 iterLen = thisLen
90 lenChooser = i
91 } else {
92 if thisLen != iterLen {
93 return cty.NullVal(cty.List(cty.String)), function.NewArgErrorf(
94 i+1,
95 "argument %d has length %d, which is inconsistent with argument %d of length %d",
96 i+1, thisLen,
97 lenChooser+1, iterLen,
98 )
99 }
100 }
101 iterators[i] = arg.ElementIterator()
102 default:
103 singleVals[i] = arg
104 }
105 }
106
107 if iterLen == 0 {
108 // If our sequences are all empty then our result must be empty.
109 return cty.ListValEmpty(cty.String), nil
110 }
111
112 if iterLen == -1 {
113 // If we didn't encounter any iterables at all then we're going
114 // to just do one iteration with items from singleVals.
115 iterLen = 1
116 }
117
118 ret := make([]cty.Value, 0, iterLen)
119 fmtArgs := make([]cty.Value, len(iterators))
120 Results:
121 for iterIdx := 0; iterIdx < iterLen; iterIdx++ {
122
123 // Construct our arguments for a single format call
124 for i := range fmtArgs {
125 switch {
126 case iterators[i] != nil:
127 iterator := iterators[i]
128 iterator.Next()
129 _, val := iterator.Element()
130 fmtArgs[i] = val
131 default:
132 fmtArgs[i] = singleVals[i]
133 }
134
135 // If any of the arguments to this call would be unknown then
136 // this particular result is unknown, but we'll keep going
137 // to see if any other iterations can produce known values.
138 if !fmtArgs[i].IsWhollyKnown() {
139 // We require all nested values to be known because the only
140 // thing we can do for a collection/structural type is print
141 // it as JSON and that requires it to be wholly known.
142 ret = append(ret, cty.UnknownVal(cty.String))
143 continue Results
144 }
145 }
146
147 str, err := formatFSM(fmtStr, fmtArgs)
148 if err != nil {
149 return cty.NullVal(cty.List(cty.String)), fmt.Errorf(
150 "error on format iteration %d: %s", iterIdx, err,
151 )
152 }
153
154 ret = append(ret, cty.StringVal(str))
155 }
156
157 return cty.ListVal(ret), nil
158 },
159})
160
161// Format produces a string representation of zero or more values using a
162// format string similar to the "printf" function in C.
163//
164// It supports the following "verbs":
165//
166// %% Literal percent sign, consuming no value
167// %v A default formatting of the value based on type, as described below.
168// %#v JSON serialization of the value
169// %t Converts to boolean and then produces "true" or "false"
170// %b Converts to number, requires integer, produces binary representation
171// %d Converts to number, requires integer, produces decimal representation
172// %o Converts to number, requires integer, produces octal representation
173// %x Converts to number, requires integer, produces hexadecimal representation
174// with lowercase letters
175// %X Like %x but with uppercase letters
176// %e Converts to number, produces scientific notation like -1.234456e+78
177// %E Like %e but with an uppercase "E" representing the exponent
178// %f Converts to number, produces decimal representation with fractional
179// part but no exponent, like 123.456
180// %g %e for large exponents or %f otherwise
181// %G %E for large exponents or %f otherwise
182// %s Converts to string and produces the string's characters
183// %q Converts to string and produces JSON-quoted string representation,
184// like %v.
185//
186// The default format selections made by %v are:
187//
188// string %s
189// number %g
190// bool %t
191// other %#v
192//
193// Null values produce the literal keyword "null" for %v and %#v, and produce
194// an error otherwise.
195//
196// Width is specified by an optional decimal number immediately preceding the
197// verb letter. If absent, the width is whatever is necessary to represent the
198// value. Precision is specified after the (optional) width by a period
199// followed by a decimal number. If no period is present, a default precision
200// is used. A period with no following number is invalid.
201// For examples:
202//
203// %f default width, default precision
204// %9f width 9, default precision
205// %.2f default width, precision 2
206// %9.2f width 9, precision 2
207//
208// Width and precision are measured in unicode characters (grapheme clusters).
209//
210// For most values, width is the minimum number of characters to output,
211// padding the formatted form with spaces if necessary.
212//
213// For strings, precision limits the length of the input to be formatted (not
214// the size of the output), truncating if necessary.
215//
216// For numbers, width sets the minimum width of the field and precision sets
217// the number of places after the decimal, if appropriate, except that for
218// %g/%G precision sets the total number of significant digits.
219//
220// The following additional symbols can be used immediately after the percent
221// introducer as flags:
222//
223// (a space) leave a space where the sign would be if number is positive
224// + Include a sign for a number even if it is positive (numeric only)
225// - Pad with spaces on the left rather than the right
226// 0 Pad with zeros rather than spaces.
227//
228// Flag characters are ignored for verbs that do not support them.
229//
230// By default, % sequences consume successive arguments starting with the first.
231// Introducing a [n] sequence immediately before the verb letter, where n is a
232// decimal integer, explicitly chooses a particular value argument by its
233// one-based index. Subsequent calls without an explicit index will then
234// proceed with n+1, n+2, etc.
235//
236// An error is produced if the format string calls for an impossible conversion
237// or accesses more values than are given. An error is produced also for
238// an unsupported format verb.
239func Format(format cty.Value, vals ...cty.Value) (cty.Value, error) {
240 args := make([]cty.Value, 0, len(vals)+1)
241 args = append(args, format)
242 args = append(args, vals...)
243 return FormatFunc.Call(args)
244}
245
246// FormatList applies the same formatting behavior as Format, but accepts
247// a mixture of list and non-list values as arguments. Any list arguments
248// passed must have the same length, which dictates the length of the
249// resulting list.
250//
251// Any non-list arguments are used repeatedly for each iteration over the
252// list arguments. The list arguments are iterated in order by key, so
253// corresponding items are formatted together.
254func FormatList(format cty.Value, vals ...cty.Value) (cty.Value, error) {
255 args := make([]cty.Value, 0, len(vals)+1)
256 args = append(args, format)
257 args = append(args, vals...)
258 return FormatListFunc.Call(args)
259}
260
261type formatVerb struct {
262 Raw string
263 Offset int
264
265 ArgNum int
266 Mode rune
267
268 Zero bool
269 Sharp bool
270 Plus bool
271 Minus bool
272 Space bool
273
274 HasPrec bool
275 Prec int
276
277 HasWidth bool
278 Width int
279}
280
281// formatAppend is called by formatFSM (generated by format_fsm.rl) for each
282// formatting sequence that is encountered.
283func formatAppend(verb *formatVerb, buf *bytes.Buffer, args []cty.Value) error {
284 argIdx := verb.ArgNum - 1
285 if argIdx >= len(args) {
286 return fmt.Errorf(
287 "not enough arguments for %q at %d: need index %d but have %d total",
288 verb.Raw, verb.Offset,
289 verb.ArgNum, len(args),
290 )
291 }
292 arg := args[argIdx]
293
294 if verb.Mode != 'v' && arg.IsNull() {
295 return fmt.Errorf("unsupported value for %q at %d: null value cannot be formatted", verb.Raw, verb.Offset)
296 }
297
298 // Normalize to make some things easier for downstream formatters
299 if !verb.HasWidth {
300 verb.Width = -1
301 }
302 if !verb.HasPrec {
303 verb.Prec = -1
304 }
305
306 // For our first pass we'll ensure the verb is supported and then fan
307 // out to other functions based on what conversion is needed.
308 switch verb.Mode {
309
310 case 'v':
311 return formatAppendAsIs(verb, buf, arg)
312
313 case 't':
314 return formatAppendBool(verb, buf, arg)
315
316 case 'b', 'd', 'o', 'x', 'X', 'e', 'E', 'f', 'g', 'G':
317 return formatAppendNumber(verb, buf, arg)
318
319 case 's', 'q':
320 return formatAppendString(verb, buf, arg)
321
322 default:
323 return fmt.Errorf("unsupported format verb %q in %q at offset %d", verb.Mode, verb.Raw, verb.Offset)
324 }
325}
326
327func formatAppendAsIs(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
328
329 if !verb.Sharp && !arg.IsNull() {
330 // Unless the caller overrode it with the sharp flag, we'll try some
331 // specialized formats before we fall back on JSON.
332 switch arg.Type() {
333 case cty.String:
334 fmted := arg.AsString()
335 fmted = formatPadWidth(verb, fmted)
336 buf.WriteString(fmted)
337 return nil
338 case cty.Number:
339 bf := arg.AsBigFloat()
340 fmted := bf.Text('g', -1)
341 fmted = formatPadWidth(verb, fmted)
342 buf.WriteString(fmted)
343 return nil
344 }
345 }
346
347 jb, err := json.Marshal(arg, arg.Type())
348 if err != nil {
349 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
350 }
351 fmted := formatPadWidth(verb, string(jb))
352 buf.WriteString(fmted)
353
354 return nil
355}
356
357func formatAppendBool(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
358 var err error
359 arg, err = convert.Convert(arg, cty.Bool)
360 if err != nil {
361 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
362 }
363
364 if arg.True() {
365 buf.WriteString("true")
366 } else {
367 buf.WriteString("false")
368 }
369 return nil
370}
371
372func formatAppendNumber(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
373 var err error
374 arg, err = convert.Convert(arg, cty.Number)
375 if err != nil {
376 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
377 }
378
379 switch verb.Mode {
380 case 'b', 'd', 'o', 'x', 'X':
381 return formatAppendInteger(verb, buf, arg)
382 default:
383 bf := arg.AsBigFloat()
384
385 // For floats our format syntax is a subset of Go's, so it's
386 // safe for us to just lean on the existing Go implementation.
387 fmtstr := formatStripIndexSegment(verb.Raw)
388 fmted := fmt.Sprintf(fmtstr, bf)
389 buf.WriteString(fmted)
390 return nil
391 }
392}
393
394func formatAppendInteger(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
395 bf := arg.AsBigFloat()
396 bi, acc := bf.Int(nil)
397 if acc != big.Exact {
398 return fmt.Errorf("unsupported value for %q at %d: an integer is required", verb.Raw, verb.Offset)
399 }
400
401 // For integers our format syntax is a subset of Go's, so it's
402 // safe for us to just lean on the existing Go implementation.
403 fmtstr := formatStripIndexSegment(verb.Raw)
404 fmted := fmt.Sprintf(fmtstr, bi)
405 buf.WriteString(fmted)
406 return nil
407}
408
409func formatAppendString(verb *formatVerb, buf *bytes.Buffer, arg cty.Value) error {
410 var err error
411 arg, err = convert.Convert(arg, cty.String)
412 if err != nil {
413 return fmt.Errorf("unsupported value for %q at %d: %s", verb.Raw, verb.Offset, err)
414 }
415
416 // We _cannot_ directly use the Go fmt.Sprintf implementation for strings
417 // because it measures widths and precisions in runes rather than grapheme
418 // clusters.
419
420 str := arg.AsString()
421 if verb.Prec > 0 {
422 strB := []byte(str)
423 pos := 0
424 wanted := verb.Prec
425 for i := 0; i < wanted; i++ {
426 next := strB[pos:]
427 if len(next) == 0 {
428 // ran out of characters before we hit our max width
429 break
430 }
431 d, _, _ := textseg.ScanGraphemeClusters(strB[pos:], true)
432 pos += d
433 }
434 str = str[:pos]
435 }
436
437 switch verb.Mode {
438 case 's':
439 fmted := formatPadWidth(verb, str)
440 buf.WriteString(fmted)
441 case 'q':
442 jb, err := json.Marshal(cty.StringVal(str), cty.String)
443 if err != nil {
444 // Should never happen, since we know this is a known, non-null string
445 panic(fmt.Errorf("failed to marshal %#v as JSON: %s", arg, err))
446 }
447 fmted := formatPadWidth(verb, string(jb))
448 buf.WriteString(fmted)
449 default:
450 // Should never happen because formatAppend should've already validated
451 panic(fmt.Errorf("invalid string formatting mode %q", verb.Mode))
452 }
453 return nil
454}
455
456func formatPadWidth(verb *formatVerb, fmted string) string {
457 if verb.Width < 0 {
458 return fmted
459 }
460
461 // Safe to ignore errors because ScanGraphemeClusters cannot produce errors
462 givenLen, _ := textseg.TokenCount([]byte(fmted), textseg.ScanGraphemeClusters)
463 wantLen := verb.Width
464 if givenLen >= wantLen {
465 return fmted
466 }
467
468 padLen := wantLen - givenLen
469 padChar := " "
470 if verb.Zero {
471 padChar = "0"
472 }
473 pads := strings.Repeat(padChar, padLen)
474
475 if verb.Minus {
476 return fmted + pads
477 }
478 return pads + fmted
479}
480
481// formatStripIndexSegment strips out any [nnn] segment present in a verb
482// string so that we can pass it through to Go's fmt.Sprintf with a single
483// argument. This is used in cases where we're just leaning on Go's formatter
484// because it's a superset of ours.
485func formatStripIndexSegment(rawVerb string) string {
486 // We assume the string has already been validated here, since we should
487 // only be using this function with strings that were accepted by our
488 // scanner in formatFSM.
489 start := strings.Index(rawVerb, "[")
490 end := strings.Index(rawVerb, "]")
491 if start == -1 || end == -1 {
492 return rawVerb
493 }
494
495 return rawVerb[:start] + rawVerb[end+1:]
496}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
new file mode 100644
index 0000000..86876ba
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.go
@@ -0,0 +1,358 @@
1// line 1 "format_fsm.rl"
2// This file is generated from format_fsm.rl. DO NOT EDIT.
3
4// line 5 "format_fsm.rl"
5
6package stdlib
7
8import (
9 "bytes"
10 "fmt"
11 "unicode/utf8"
12
13 "github.com/zclconf/go-cty/cty"
14)
15
16// line 20 "format_fsm.go"
17var _formatfsm_actions []byte = []byte{
18 0, 1, 0, 1, 1, 1, 2, 1, 4,
19 1, 5, 1, 6, 1, 7, 1, 8,
20 1, 9, 1, 10, 1, 11, 1, 14,
21 1, 16, 1, 17, 1, 18, 2, 3,
22 4, 2, 12, 10, 2, 12, 16, 2,
23 12, 18, 2, 13, 14, 2, 15, 10,
24 2, 15, 18,
25}
26
27var _formatfsm_key_offsets []byte = []byte{
28 0, 0, 14, 27, 34, 36, 39, 43,
29 51,
30}
31
32var _formatfsm_trans_keys []byte = []byte{
33 32, 35, 37, 43, 45, 46, 48, 91,
34 49, 57, 65, 90, 97, 122, 32, 35,
35 43, 45, 46, 48, 91, 49, 57, 65,
36 90, 97, 122, 91, 48, 57, 65, 90,
37 97, 122, 49, 57, 93, 48, 57, 65,
38 90, 97, 122, 46, 91, 48, 57, 65,
39 90, 97, 122, 37,
40}
41
42var _formatfsm_single_lengths []byte = []byte{
43 0, 8, 7, 1, 0, 1, 0, 2,
44 1,
45}
46
47var _formatfsm_range_lengths []byte = []byte{
48 0, 3, 3, 3, 1, 1, 2, 3,
49 0,
50}
51
52var _formatfsm_index_offsets []byte = []byte{
53 0, 0, 12, 23, 28, 30, 33, 36,
54 42,
55}
56
57var _formatfsm_indicies []byte = []byte{
58 1, 2, 3, 4, 5, 6, 7, 10,
59 8, 9, 9, 0, 1, 2, 4, 5,
60 6, 7, 10, 8, 9, 9, 0, 13,
61 11, 12, 12, 0, 14, 0, 15, 14,
62 0, 9, 9, 0, 16, 19, 17, 18,
63 18, 0, 20, 3,
64}
65
66var _formatfsm_trans_targs []byte = []byte{
67 0, 2, 2, 8, 2, 2, 3, 2,
68 7, 8, 4, 3, 8, 4, 5, 6,
69 3, 7, 8, 4, 1,
70}
71
72var _formatfsm_trans_actions []byte = []byte{
73 7, 17, 9, 3, 15, 13, 25, 11,
74 43, 29, 19, 27, 49, 46, 21, 0,
75 37, 23, 40, 34, 1,
76}
77
78var _formatfsm_eof_actions []byte = []byte{
79 0, 31, 31, 31, 31, 31, 31, 31,
80 5,
81}
82
83const formatfsm_start int = 8
84const formatfsm_first_final int = 8
85const formatfsm_error int = 0
86
87const formatfsm_en_main int = 8
88
89// line 19 "format_fsm.rl"
90
91func formatFSM(format string, a []cty.Value) (string, error) {
92 var buf bytes.Buffer
93 data := format
94 nextArg := 1 // arg numbers are 1-based
95 var verb formatVerb
96
97 // line 153 "format_fsm.rl"
98
99 // Ragel state
100 p := 0 // "Pointer" into data
101 pe := len(data) // End-of-data "pointer"
102 cs := 0 // current state (will be initialized by ragel-generated code)
103 ts := 0
104 te := 0
105 eof := pe
106
107 // Keep Go compiler happy even if generated code doesn't use these
108 _ = ts
109 _ = te
110 _ = eof
111
112 // line 121 "format_fsm.go"
113 {
114 cs = formatfsm_start
115 }
116
117 // line 126 "format_fsm.go"
118 {
119 var _klen int
120 var _trans int
121 var _acts int
122 var _nacts uint
123 var _keys int
124 if p == pe {
125 goto _test_eof
126 }
127 if cs == 0 {
128 goto _out
129 }
130 _resume:
131 _keys = int(_formatfsm_key_offsets[cs])
132 _trans = int(_formatfsm_index_offsets[cs])
133
134 _klen = int(_formatfsm_single_lengths[cs])
135 if _klen > 0 {
136 _lower := int(_keys)
137 var _mid int
138 _upper := int(_keys + _klen - 1)
139 for {
140 if _upper < _lower {
141 break
142 }
143
144 _mid = _lower + ((_upper - _lower) >> 1)
145 switch {
146 case data[p] < _formatfsm_trans_keys[_mid]:
147 _upper = _mid - 1
148 case data[p] > _formatfsm_trans_keys[_mid]:
149 _lower = _mid + 1
150 default:
151 _trans += int(_mid - int(_keys))
152 goto _match
153 }
154 }
155 _keys += _klen
156 _trans += _klen
157 }
158
159 _klen = int(_formatfsm_range_lengths[cs])
160 if _klen > 0 {
161 _lower := int(_keys)
162 var _mid int
163 _upper := int(_keys + (_klen << 1) - 2)
164 for {
165 if _upper < _lower {
166 break
167 }
168
169 _mid = _lower + (((_upper - _lower) >> 1) & ^1)
170 switch {
171 case data[p] < _formatfsm_trans_keys[_mid]:
172 _upper = _mid - 2
173 case data[p] > _formatfsm_trans_keys[_mid+1]:
174 _lower = _mid + 2
175 default:
176 _trans += int((_mid - int(_keys)) >> 1)
177 goto _match
178 }
179 }
180 _trans += _klen
181 }
182
183 _match:
184 _trans = int(_formatfsm_indicies[_trans])
185 cs = int(_formatfsm_trans_targs[_trans])
186
187 if _formatfsm_trans_actions[_trans] == 0 {
188 goto _again
189 }
190
191 _acts = int(_formatfsm_trans_actions[_trans])
192 _nacts = uint(_formatfsm_actions[_acts])
193 _acts++
194 for ; _nacts > 0; _nacts-- {
195 _acts++
196 switch _formatfsm_actions[_acts-1] {
197 case 0:
198 // line 29 "format_fsm.rl"
199
200 verb = formatVerb{
201 ArgNum: nextArg,
202 Prec: -1,
203 Width: -1,
204 }
205 ts = p
206
207 case 1:
208 // line 38 "format_fsm.rl"
209
210 buf.WriteByte(data[p])
211
212 case 4:
213 // line 49 "format_fsm.rl"
214
215 // We'll try to slurp a whole UTF-8 sequence here, to give the user
216 // better feedback.
217 r, _ := utf8.DecodeRuneInString(data[p:])
218 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
219
220 case 5:
221 // line 56 "format_fsm.rl"
222
223 verb.Sharp = true
224
225 case 6:
226 // line 59 "format_fsm.rl"
227
228 verb.Zero = true
229
230 case 7:
231 // line 62 "format_fsm.rl"
232
233 verb.Minus = true
234
235 case 8:
236 // line 65 "format_fsm.rl"
237
238 verb.Plus = true
239
240 case 9:
241 // line 68 "format_fsm.rl"
242
243 verb.Space = true
244
245 case 10:
246 // line 72 "format_fsm.rl"
247
248 verb.ArgNum = 0
249
250 case 11:
251 // line 75 "format_fsm.rl"
252
253 verb.ArgNum = (10 * verb.ArgNum) + (int(data[p]) - '0')
254
255 case 12:
256 // line 79 "format_fsm.rl"
257
258 verb.HasWidth = true
259
260 case 13:
261 // line 82 "format_fsm.rl"
262
263 verb.Width = 0
264
265 case 14:
266 // line 85 "format_fsm.rl"
267
268 verb.Width = (10 * verb.Width) + (int(data[p]) - '0')
269
270 case 15:
271 // line 89 "format_fsm.rl"
272
273 verb.HasPrec = true
274
275 case 16:
276 // line 92 "format_fsm.rl"
277
278 verb.Prec = 0
279
280 case 17:
281 // line 95 "format_fsm.rl"
282
283 verb.Prec = (10 * verb.Prec) + (int(data[p]) - '0')
284
285 case 18:
286 // line 99 "format_fsm.rl"
287
288 verb.Mode = rune(data[p])
289 te = p + 1
290 verb.Raw = data[ts:te]
291 verb.Offset = ts
292
293 err := formatAppend(&verb, &buf, a)
294 if err != nil {
295 return buf.String(), err
296 }
297 nextArg = verb.ArgNum + 1
298
299 // line 324 "format_fsm.go"
300 }
301 }
302
303 _again:
304 if cs == 0 {
305 goto _out
306 }
307 p++
308 if p != pe {
309 goto _resume
310 }
311 _test_eof:
312 {
313 }
314 if p == eof {
315 __acts := _formatfsm_eof_actions[cs]
316 __nacts := uint(_formatfsm_actions[__acts])
317 __acts++
318 for ; __nacts > 0; __nacts-- {
319 __acts++
320 switch _formatfsm_actions[__acts-1] {
321 case 2:
322 // line 42 "format_fsm.rl"
323
324 case 3:
325 // line 45 "format_fsm.rl"
326
327 return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
328
329 case 4:
330 // line 49 "format_fsm.rl"
331
332 // We'll try to slurp a whole UTF-8 sequence here, to give the user
333 // better feedback.
334 r, _ := utf8.DecodeRuneInString(data[p:])
335 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
336
337 // line 363 "format_fsm.go"
338 }
339 }
340 }
341
342 _out:
343 {
344 }
345 }
346
347 // line 171 "format_fsm.rl"
348
349 // If we fall out here without being in a final state then we've
350 // encountered something that the scanner can't match, which should
351 // be impossible (the scanner matches all bytes _somehow_) but we'll
352 // flag it anyway rather than just losing data from the end.
353 if cs < formatfsm_first_final {
354 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %i", p)
355 }
356
357 return buf.String(), nil
358}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
new file mode 100644
index 0000000..85d43bb
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format_fsm.rl
@@ -0,0 +1,182 @@
1// This file is generated from format_fsm.rl. DO NOT EDIT.
2%%{
3 # (except you are actually in scan_tokens.rl here, so edit away!)
4 machine formatfsm;
5}%%
6
7package stdlib
8
9import (
10 "bytes"
11 "fmt"
12 "unicode/utf8"
13
14 "github.com/zclconf/go-cty/cty"
15)
16
17%%{
18 write data;
19}%%
20
21func formatFSM(format string, a []cty.Value) (string, error) {
22 var buf bytes.Buffer
23 data := format
24 nextArg := 1 // arg numbers are 1-based
25 var verb formatVerb
26
27 %%{
28
29 action begin {
30 verb = formatVerb{
31 ArgNum: nextArg,
32 Prec: -1,
33 Width: -1,
34 }
35 ts = p
36 }
37
38 action emit {
39 buf.WriteByte(fc);
40 }
41
42 action finish_ok {
43 }
44
45 action finish_err {
46 return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
47 }
48
49 action err_char {
50 // We'll try to slurp a whole UTF-8 sequence here, to give the user
51 // better feedback.
52 r, _ := utf8.DecodeRuneInString(data[p:])
53 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
54 }
55
56 action flag_sharp {
57 verb.Sharp = true
58 }
59 action flag_zero {
60 verb.Zero = true
61 }
62 action flag_minus {
63 verb.Minus = true
64 }
65 action flag_plus {
66 verb.Plus = true
67 }
68 action flag_space {
69 verb.Space = true
70 }
71
72 action argidx_reset {
73 verb.ArgNum = 0
74 }
75 action argidx_num {
76 verb.ArgNum = (10 * verb.ArgNum) + (int(fc) - '0')
77 }
78
79 action has_width {
80 verb.HasWidth = true
81 }
82 action width_reset {
83 verb.Width = 0
84 }
85 action width_num {
86 verb.Width = (10 * verb.Width) + (int(fc) - '0')
87 }
88
89 action has_prec {
90 verb.HasPrec = true
91 }
92 action prec_reset {
93 verb.Prec = 0
94 }
95 action prec_num {
96 verb.Prec = (10 * verb.Prec) + (int(fc) - '0')
97 }
98
99 action mode {
100 verb.Mode = rune(fc)
101 te = p+1
102 verb.Raw = data[ts:te]
103 verb.Offset = ts
104
105 err := formatAppend(&verb, &buf, a)
106 if err != nil {
107 return buf.String(), err
108 }
109 nextArg = verb.ArgNum + 1
110 }
111
112 # a number that isn't zero and doesn't have a leading zero
113 num = [1-9] [0-9]*;
114
115 flags = (
116 '0' @flag_zero |
117 '#' @flag_sharp |
118 '-' @flag_minus |
119 '+' @flag_plus |
120 ' ' @flag_space
121 )*;
122
123 argidx = ((
124 '[' (num $argidx_num) ']'
125 ) >argidx_reset)?;
126
127 width = (
128 ( num $width_num ) >width_reset %has_width
129 )?;
130
131 precision = (
132 ('.' ( digit* $prec_num )) >prec_reset %has_prec
133 )?;
134
135 # We accept any letter here, but will be more picky in formatAppend
136 mode = ('a'..'z' | 'A'..'Z') @mode;
137
138 fmt_verb = (
139 '%' @begin
140 flags
141 width
142 precision
143 argidx
144 mode
145 );
146
147 main := (
148 [^%] @emit |
149 '%%' @emit |
150 fmt_verb
151 )* @/finish_err %/finish_ok $!err_char;
152
153 }%%
154
155 // Ragel state
156 p := 0 // "Pointer" into data
157 pe := len(data) // End-of-data "pointer"
158 cs := 0 // current state (will be initialized by ragel-generated code)
159 ts := 0
160 te := 0
161 eof := pe
162
163 // Keep Go compiler happy even if generated code doesn't use these
164 _ = ts
165 _ = te
166 _ = eof
167
168 %%{
169 write init;
170 write exec;
171 }%%
172
173 // If we fall out here without being in a final state then we've
174 // encountered something that the scanner can't match, which should
175 // be impossible (the scanner matches all bytes _somehow_) but we'll
176 // flag it anyway rather than just losing data from the end.
177 if cs < formatfsm_first_final {
178 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %i", p)
179 }
180
181 return buf.String(), nil
182}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go
new file mode 100644
index 0000000..6b31f26
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go
@@ -0,0 +1,107 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/convert"
8 "github.com/zclconf/go-cty/cty/function"
9)
10
11var EqualFunc = function.New(&function.Spec{
12 Params: []function.Parameter{
13 {
14 Name: "a",
15 Type: cty.DynamicPseudoType,
16 AllowUnknown: true,
17 AllowDynamicType: true,
18 AllowNull: true,
19 },
20 {
21 Name: "b",
22 Type: cty.DynamicPseudoType,
23 AllowUnknown: true,
24 AllowDynamicType: true,
25 AllowNull: true,
26 },
27 },
28 Type: function.StaticReturnType(cty.Bool),
29 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
30 return args[0].Equals(args[1]), nil
31 },
32})
33
34var NotEqualFunc = function.New(&function.Spec{
35 Params: []function.Parameter{
36 {
37 Name: "a",
38 Type: cty.DynamicPseudoType,
39 AllowUnknown: true,
40 AllowDynamicType: true,
41 AllowNull: true,
42 },
43 {
44 Name: "b",
45 Type: cty.DynamicPseudoType,
46 AllowUnknown: true,
47 AllowDynamicType: true,
48 AllowNull: true,
49 },
50 },
51 Type: function.StaticReturnType(cty.Bool),
52 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
53 return args[0].Equals(args[1]).Not(), nil
54 },
55})
56
57var CoalesceFunc = function.New(&function.Spec{
58 Params: []function.Parameter{},
59 VarParam: &function.Parameter{
60 Name: "vals",
61 Type: cty.DynamicPseudoType,
62 AllowUnknown: true,
63 AllowDynamicType: true,
64 AllowNull: true,
65 },
66 Type: func(args []cty.Value) (ret cty.Type, err error) {
67 argTypes := make([]cty.Type, len(args))
68 for i, val := range args {
69 argTypes[i] = val.Type()
70 }
71 retType, _ := convert.UnifyUnsafe(argTypes)
72 if retType == cty.NilType {
73 return cty.NilType, fmt.Errorf("all arguments must have the same type")
74 }
75 return retType, nil
76 },
77 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
78 for _, argVal := range args {
79 if !argVal.IsKnown() {
80 return cty.UnknownVal(retType), nil
81 }
82 if argVal.IsNull() {
83 continue
84 }
85
86 return convert.Convert(argVal, retType)
87 }
88 return cty.NilVal, fmt.Errorf("no non-null arguments")
89 },
90})
91
92// Equal determines whether the two given values are equal, returning a
93// bool value.
94func Equal(a cty.Value, b cty.Value) (cty.Value, error) {
95 return EqualFunc.Call([]cty.Value{a, b})
96}
97
98// NotEqual is the opposite of Equal.
99func NotEqual(a cty.Value, b cty.Value) (cty.Value, error) {
100 return NotEqualFunc.Call([]cty.Value{a, b})
101}
102
103// Coalesce returns the first of the given arguments that is not null. If
104// all arguments are null, an error is produced.
105func Coalesce(vals ...cty.Value) (cty.Value, error) {
106 return CoalesceFunc.Call(vals)
107}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go
new file mode 100644
index 0000000..07901c6
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go
@@ -0,0 +1,72 @@
1package stdlib
2
3import (
4 "github.com/zclconf/go-cty/cty"
5 "github.com/zclconf/go-cty/cty/function"
6 "github.com/zclconf/go-cty/cty/json"
7)
8
9var JSONEncodeFunc = function.New(&function.Spec{
10 Params: []function.Parameter{
11 {
12 Name: "val",
13 Type: cty.DynamicPseudoType,
14 AllowDynamicType: true,
15 },
16 },
17 Type: function.StaticReturnType(cty.String),
18 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
19 val := args[0]
20 if !val.IsWhollyKnown() {
21 // We can't serialize unknowns, so if the value is unknown or
22 // contains any _nested_ unknowns then our result must be
23 // unknown.
24 return cty.UnknownVal(retType), nil
25 }
26
27 buf, err := json.Marshal(val, val.Type())
28 if err != nil {
29 return cty.NilVal, err
30 }
31
32 return cty.StringVal(string(buf)), nil
33 },
34})
35
36var JSONDecodeFunc = function.New(&function.Spec{
37 Params: []function.Parameter{
38 {
39 Name: "str",
40 Type: cty.String,
41 },
42 },
43 Type: func(args []cty.Value) (cty.Type, error) {
44 str := args[0]
45 if !str.IsKnown() {
46 return cty.DynamicPseudoType, nil
47 }
48
49 buf := []byte(str.AsString())
50 return json.ImpliedType(buf)
51 },
52 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
53 buf := []byte(args[0].AsString())
54 return json.Unmarshal(buf, retType)
55 },
56})
57
58// JSONEncode returns a JSON serialization of the given value.
59func JSONEncode(val cty.Value) (cty.Value, error) {
60 return JSONEncodeFunc.Call([]cty.Value{val})
61}
62
63// JSONDecode parses the given JSON string and, if it is valid, returns the
64// value it represents.
65//
66// Note that applying JSONDecode to the result of JSONEncode may not produce
67// an identically-typed result, since JSON encoding is lossy for cty Types.
68// The resulting value will consist only of primitive types, object types, and
69// tuple types.
70func JSONDecode(str cty.Value) (cty.Value, error) {
71 return JSONDecodeFunc.Call([]cty.Value{str})
72}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
new file mode 100644
index 0000000..bd9b2e5
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
@@ -0,0 +1,428 @@
1package stdlib
2
3import (
4 "fmt"
5 "math/big"
6
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/function"
9)
10
11var AbsoluteFunc = function.New(&function.Spec{
12 Params: []function.Parameter{
13 {
14 Name: "num",
15 Type: cty.Number,
16 AllowDynamicType: true,
17 },
18 },
19 Type: function.StaticReturnType(cty.Number),
20 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
21 return args[0].Absolute(), nil
22 },
23})
24
25var AddFunc = function.New(&function.Spec{
26 Params: []function.Parameter{
27 {
28 Name: "a",
29 Type: cty.Number,
30 AllowDynamicType: true,
31 },
32 {
33 Name: "b",
34 Type: cty.Number,
35 AllowDynamicType: true,
36 },
37 },
38 Type: function.StaticReturnType(cty.Number),
39 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
40 // big.Float.Add can panic if the input values are opposing infinities,
41 // so we must catch that here in order to remain within
42 // the cty Function abstraction.
43 defer func() {
44 if r := recover(); r != nil {
45 if _, ok := r.(big.ErrNaN); ok {
46 ret = cty.NilVal
47 err = fmt.Errorf("can't compute sum of opposing infinities")
48 } else {
49 // not a panic we recognize
50 panic(r)
51 }
52 }
53 }()
54 return args[0].Add(args[1]), nil
55 },
56})
57
58var SubtractFunc = function.New(&function.Spec{
59 Params: []function.Parameter{
60 {
61 Name: "a",
62 Type: cty.Number,
63 AllowDynamicType: true,
64 },
65 {
66 Name: "b",
67 Type: cty.Number,
68 AllowDynamicType: true,
69 },
70 },
71 Type: function.StaticReturnType(cty.Number),
72 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
73 // big.Float.Sub can panic if the input values are infinities,
74 // so we must catch that here in order to remain within
75 // the cty Function abstraction.
76 defer func() {
77 if r := recover(); r != nil {
78 if _, ok := r.(big.ErrNaN); ok {
79 ret = cty.NilVal
80 err = fmt.Errorf("can't subtract infinity from itself")
81 } else {
82 // not a panic we recognize
83 panic(r)
84 }
85 }
86 }()
87 return args[0].Subtract(args[1]), nil
88 },
89})
90
91var MultiplyFunc = function.New(&function.Spec{
92 Params: []function.Parameter{
93 {
94 Name: "a",
95 Type: cty.Number,
96 AllowDynamicType: true,
97 },
98 {
99 Name: "b",
100 Type: cty.Number,
101 AllowDynamicType: true,
102 },
103 },
104 Type: function.StaticReturnType(cty.Number),
105 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
106 // big.Float.Mul can panic if the input values are both zero or both
107 // infinity, so we must catch that here in order to remain within
108 // the cty Function abstraction.
109 defer func() {
110 if r := recover(); r != nil {
111 if _, ok := r.(big.ErrNaN); ok {
112 ret = cty.NilVal
113 err = fmt.Errorf("can't multiply zero by infinity")
114 } else {
115 // not a panic we recognize
116 panic(r)
117 }
118 }
119 }()
120
121 return args[0].Multiply(args[1]), nil
122 },
123})
124
125var DivideFunc = function.New(&function.Spec{
126 Params: []function.Parameter{
127 {
128 Name: "a",
129 Type: cty.Number,
130 AllowDynamicType: true,
131 },
132 {
133 Name: "b",
134 Type: cty.Number,
135 AllowDynamicType: true,
136 },
137 },
138 Type: function.StaticReturnType(cty.Number),
139 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
140 // big.Float.Quo can panic if the input values are both zero or both
141 // infinity, so we must catch that here in order to remain within
142 // the cty Function abstraction.
143 defer func() {
144 if r := recover(); r != nil {
145 if _, ok := r.(big.ErrNaN); ok {
146 ret = cty.NilVal
147 err = fmt.Errorf("can't divide zero by zero or infinity by infinity")
148 } else {
149 // not a panic we recognize
150 panic(r)
151 }
152 }
153 }()
154
155 return args[0].Divide(args[1]), nil
156 },
157})
158
159var ModuloFunc = function.New(&function.Spec{
160 Params: []function.Parameter{
161 {
162 Name: "a",
163 Type: cty.Number,
164 AllowDynamicType: true,
165 },
166 {
167 Name: "b",
168 Type: cty.Number,
169 AllowDynamicType: true,
170 },
171 },
172 Type: function.StaticReturnType(cty.Number),
173 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
174 // big.Float.Mul can panic if the input values are both zero or both
175 // infinity, so we must catch that here in order to remain within
176 // the cty Function abstraction.
177 defer func() {
178 if r := recover(); r != nil {
179 if _, ok := r.(big.ErrNaN); ok {
180 ret = cty.NilVal
181 err = fmt.Errorf("can't use modulo with zero and infinity")
182 } else {
183 // not a panic we recognize
184 panic(r)
185 }
186 }
187 }()
188
189 return args[0].Modulo(args[1]), nil
190 },
191})
192
193var GreaterThanFunc = function.New(&function.Spec{
194 Params: []function.Parameter{
195 {
196 Name: "a",
197 Type: cty.Number,
198 AllowDynamicType: true,
199 },
200 {
201 Name: "b",
202 Type: cty.Number,
203 AllowDynamicType: true,
204 },
205 },
206 Type: function.StaticReturnType(cty.Bool),
207 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
208 return args[0].GreaterThan(args[1]), nil
209 },
210})
211
212var GreaterThanOrEqualToFunc = function.New(&function.Spec{
213 Params: []function.Parameter{
214 {
215 Name: "a",
216 Type: cty.Number,
217 AllowDynamicType: true,
218 },
219 {
220 Name: "b",
221 Type: cty.Number,
222 AllowDynamicType: true,
223 },
224 },
225 Type: function.StaticReturnType(cty.Bool),
226 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
227 return args[0].GreaterThanOrEqualTo(args[1]), nil
228 },
229})
230
231var LessThanFunc = function.New(&function.Spec{
232 Params: []function.Parameter{
233 {
234 Name: "a",
235 Type: cty.Number,
236 AllowDynamicType: true,
237 },
238 {
239 Name: "b",
240 Type: cty.Number,
241 AllowDynamicType: true,
242 },
243 },
244 Type: function.StaticReturnType(cty.Bool),
245 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
246 return args[0].LessThan(args[1]), nil
247 },
248})
249
250var LessThanOrEqualToFunc = function.New(&function.Spec{
251 Params: []function.Parameter{
252 {
253 Name: "a",
254 Type: cty.Number,
255 AllowDynamicType: true,
256 },
257 {
258 Name: "b",
259 Type: cty.Number,
260 AllowDynamicType: true,
261 },
262 },
263 Type: function.StaticReturnType(cty.Bool),
264 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
265 return args[0].LessThanOrEqualTo(args[1]), nil
266 },
267})
268
269var NegateFunc = function.New(&function.Spec{
270 Params: []function.Parameter{
271 {
272 Name: "num",
273 Type: cty.Number,
274 AllowDynamicType: true,
275 },
276 },
277 Type: function.StaticReturnType(cty.Number),
278 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
279 return args[0].Negate(), nil
280 },
281})
282
283var MinFunc = function.New(&function.Spec{
284 Params: []function.Parameter{},
285 VarParam: &function.Parameter{
286 Name: "numbers",
287 Type: cty.Number,
288 AllowDynamicType: true,
289 },
290 Type: function.StaticReturnType(cty.Number),
291 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
292 if len(args) == 0 {
293 return cty.NilVal, fmt.Errorf("must pass at least one number")
294 }
295
296 min := cty.PositiveInfinity
297 for _, num := range args {
298 if num.LessThan(min).True() {
299 min = num
300 }
301 }
302
303 return min, nil
304 },
305})
306
307var MaxFunc = function.New(&function.Spec{
308 Params: []function.Parameter{},
309 VarParam: &function.Parameter{
310 Name: "numbers",
311 Type: cty.Number,
312 AllowDynamicType: true,
313 },
314 Type: function.StaticReturnType(cty.Number),
315 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
316 if len(args) == 0 {
317 return cty.NilVal, fmt.Errorf("must pass at least one number")
318 }
319
320 max := cty.NegativeInfinity
321 for _, num := range args {
322 if num.GreaterThan(max).True() {
323 max = num
324 }
325 }
326
327 return max, nil
328 },
329})
330
331var IntFunc = function.New(&function.Spec{
332 Params: []function.Parameter{
333 {
334 Name: "num",
335 Type: cty.Number,
336 AllowDynamicType: true,
337 },
338 },
339 Type: function.StaticReturnType(cty.Number),
340 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
341 bf := args[0].AsBigFloat()
342 if bf.IsInt() {
343 return args[0], nil
344 }
345 bi, _ := bf.Int(nil)
346 bf = (&big.Float{}).SetInt(bi)
347 return cty.NumberVal(bf), nil
348 },
349})
350
351// Absolute returns the magnitude of the given number, without its sign.
352// That is, it turns negative values into positive values.
353func Absolute(num cty.Value) (cty.Value, error) {
354 return AbsoluteFunc.Call([]cty.Value{num})
355}
356
357// Add returns the sum of the two given numbers.
358func Add(a cty.Value, b cty.Value) (cty.Value, error) {
359 return AddFunc.Call([]cty.Value{a, b})
360}
361
362// Subtract returns the difference between the two given numbers.
363func Subtract(a cty.Value, b cty.Value) (cty.Value, error) {
364 return SubtractFunc.Call([]cty.Value{a, b})
365}
366
367// Multiply returns the product of the two given numbers.
368func Multiply(a cty.Value, b cty.Value) (cty.Value, error) {
369 return MultiplyFunc.Call([]cty.Value{a, b})
370}
371
372// Divide returns a divided by b, where both a and b are numbers.
373func Divide(a cty.Value, b cty.Value) (cty.Value, error) {
374 return DivideFunc.Call([]cty.Value{a, b})
375}
376
377// Negate returns the given number multipled by -1.
378func Negate(num cty.Value) (cty.Value, error) {
379 return NegateFunc.Call([]cty.Value{num})
380}
381
382// LessThan returns true if a is less than b.
383func LessThan(a cty.Value, b cty.Value) (cty.Value, error) {
384 return LessThanFunc.Call([]cty.Value{a, b})
385}
386
387// LessThanOrEqualTo returns true if a is less than b.
388func LessThanOrEqualTo(a cty.Value, b cty.Value) (cty.Value, error) {
389 return LessThanOrEqualToFunc.Call([]cty.Value{a, b})
390}
391
392// GreaterThan returns true if a is less than b.
393func GreaterThan(a cty.Value, b cty.Value) (cty.Value, error) {
394 return GreaterThanFunc.Call([]cty.Value{a, b})
395}
396
397// GreaterThanOrEqualTo returns true if a is less than b.
398func GreaterThanOrEqualTo(a cty.Value, b cty.Value) (cty.Value, error) {
399 return GreaterThanOrEqualToFunc.Call([]cty.Value{a, b})
400}
401
402// Modulo returns the remainder of a divided by b under integer division,
403// where both a and b are numbers.
404func Modulo(a cty.Value, b cty.Value) (cty.Value, error) {
405 return ModuloFunc.Call([]cty.Value{a, b})
406}
407
408// Min returns the minimum number from the given numbers.
409func Min(numbers ...cty.Value) (cty.Value, error) {
410 return MinFunc.Call(numbers)
411}
412
413// Max returns the maximum number from the given numbers.
414func Max(numbers ...cty.Value) (cty.Value, error) {
415 return MaxFunc.Call(numbers)
416}
417
418// Int removes the fractional component of the given number returning an
419// integer representing the whole number component, rounding towards zero.
420// For example, -1.5 becomes -1.
421//
422// If an infinity is passed to Int, an error is returned.
423func Int(num cty.Value) (cty.Value, error) {
424 if num == cty.PositiveInfinity || num == cty.NegativeInfinity {
425 return cty.NilVal, fmt.Errorf("can't truncate infinity to an integer")
426 }
427 return IntFunc.Call([]cty.Value{num})
428}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
new file mode 100644
index 0000000..e2c77c5
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
@@ -0,0 +1,130 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/convert"
8 "github.com/zclconf/go-cty/cty/function"
9)
10
11var ConcatFunc = function.New(&function.Spec{
12 Params: []function.Parameter{},
13 VarParam: &function.Parameter{
14 Name: "seqs",
15 Type: cty.DynamicPseudoType,
16 },
17 Type: func(args []cty.Value) (ret cty.Type, err error) {
18 if len(args) == 0 {
19 return cty.NilType, fmt.Errorf("at least one argument is required")
20 }
21
22 if args[0].Type().IsListType() {
23 // Possibly we're going to return a list, if all of our other
24 // args are also lists and we can find a common element type.
25 tys := make([]cty.Type, len(args))
26 for i, val := range args {
27 ty := val.Type()
28 if !ty.IsListType() {
29 tys = nil
30 break
31 }
32 tys[i] = ty
33 }
34
35 if tys != nil {
36 commonType, _ := convert.UnifyUnsafe(tys)
37 if commonType != cty.NilType {
38 return commonType, nil
39 }
40 }
41 }
42
43 etys := make([]cty.Type, 0, len(args))
44 for i, val := range args {
45 ety := val.Type()
46 switch {
47 case ety.IsTupleType():
48 etys = append(etys, ety.TupleElementTypes()...)
49 case ety.IsListType():
50 if !val.IsKnown() {
51 // We need to know the list to count its elements to
52 // build our tuple type, so any concat of an unknown
53 // list can't be typed yet.
54 return cty.DynamicPseudoType, nil
55 }
56
57 l := val.LengthInt()
58 subEty := ety.ElementType()
59 for j := 0; j < l; j++ {
60 etys = append(etys, subEty)
61 }
62 default:
63 return cty.NilType, function.NewArgErrorf(
64 i, "all arguments must be lists or tuples; got %s",
65 ety.FriendlyName(),
66 )
67 }
68 }
69 return cty.Tuple(etys), nil
70 },
71 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
72 switch {
73 case retType.IsListType():
74 // If retType is a list type then we know that all of the
75 // given values will be lists and that they will either be of
76 // retType or of something we can convert to retType.
77 vals := make([]cty.Value, 0, len(args))
78 for i, list := range args {
79 list, err = convert.Convert(list, retType)
80 if err != nil {
81 // Conversion might fail because we used UnifyUnsafe
82 // to choose our return type.
83 return cty.NilVal, function.NewArgError(i, err)
84 }
85
86 it := list.ElementIterator()
87 for it.Next() {
88 _, v := it.Element()
89 vals = append(vals, v)
90 }
91 }
92 if len(vals) == 0 {
93 return cty.ListValEmpty(retType.ElementType()), nil
94 }
95
96 return cty.ListVal(vals), nil
97 case retType.IsTupleType():
98 // If retType is a tuple type then we could have a mixture of
99 // lists and tuples but we know they all have known values
100 // (because our params don't AllowUnknown) and we know that
101 // concatenating them all together will produce a tuple of
102 // retType because of the work we did in the Type function above.
103 vals := make([]cty.Value, 0, len(args))
104
105 for _, seq := range args {
106 // Both lists and tuples support ElementIterator, so this is easy.
107 it := seq.ElementIterator()
108 for it.Next() {
109 _, v := it.Element()
110 vals = append(vals, v)
111 }
112 }
113
114 return cty.TupleVal(vals), nil
115 default:
116 // should never happen if Type is working correctly above
117 panic("unsupported return type")
118 }
119 },
120})
121
122// Concat takes one or more sequences (lists or tuples) and returns the single
123// sequence that results from concatenating them together in order.
124//
125// If all of the given sequences are lists of the same element type then the
126// result is a list of that type. Otherwise, the result is a of a tuple type
127// constructed from the given sequence types.
128func Concat(seqs ...cty.Value) (cty.Value, error) {
129 return ConcatFunc.Call(seqs)
130}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go
new file mode 100644
index 0000000..100078f
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go
@@ -0,0 +1,195 @@
1package stdlib
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty/convert"
7
8 "github.com/zclconf/go-cty/cty"
9 "github.com/zclconf/go-cty/cty/function"
10)
11
12var SetHasElementFunc = function.New(&function.Spec{
13 Params: []function.Parameter{
14 {
15 Name: "set",
16 Type: cty.Set(cty.DynamicPseudoType),
17 AllowDynamicType: true,
18 },
19 {
20 Name: "elem",
21 Type: cty.DynamicPseudoType,
22 AllowDynamicType: true,
23 },
24 },
25 Type: function.StaticReturnType(cty.Bool),
26 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
27 return args[0].HasElement(args[1]), nil
28 },
29})
30
31var SetUnionFunc = function.New(&function.Spec{
32 Params: []function.Parameter{
33 {
34 Name: "first_set",
35 Type: cty.Set(cty.DynamicPseudoType),
36 AllowDynamicType: true,
37 },
38 },
39 VarParam: &function.Parameter{
40 Name: "other_sets",
41 Type: cty.Set(cty.DynamicPseudoType),
42 AllowDynamicType: true,
43 },
44 Type: setOperationReturnType,
45 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
46 return s1.Union(s2)
47 }),
48})
49
50var SetIntersectionFunc = function.New(&function.Spec{
51 Params: []function.Parameter{
52 {
53 Name: "first_set",
54 Type: cty.Set(cty.DynamicPseudoType),
55 AllowDynamicType: true,
56 },
57 },
58 VarParam: &function.Parameter{
59 Name: "other_sets",
60 Type: cty.Set(cty.DynamicPseudoType),
61 AllowDynamicType: true,
62 },
63 Type: setOperationReturnType,
64 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
65 return s1.Intersection(s2)
66 }),
67})
68
69var SetSubtractFunc = function.New(&function.Spec{
70 Params: []function.Parameter{
71 {
72 Name: "a",
73 Type: cty.Set(cty.DynamicPseudoType),
74 AllowDynamicType: true,
75 },
76 {
77 Name: "b",
78 Type: cty.Set(cty.DynamicPseudoType),
79 AllowDynamicType: true,
80 },
81 },
82 Type: setOperationReturnType,
83 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
84 return s1.Subtract(s2)
85 }),
86})
87
88var SetSymmetricDifferenceFunc = function.New(&function.Spec{
89 Params: []function.Parameter{
90 {
91 Name: "first_set",
92 Type: cty.Set(cty.DynamicPseudoType),
93 AllowDynamicType: true,
94 },
95 },
96 VarParam: &function.Parameter{
97 Name: "other_sets",
98 Type: cty.Set(cty.DynamicPseudoType),
99 AllowDynamicType: true,
100 },
101 Type: setOperationReturnType,
102 Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
103 return s1.Subtract(s2)
104 }),
105})
106
107// SetHasElement determines whether the given set contains the given value as an
108// element.
109func SetHasElement(set cty.Value, elem cty.Value) (cty.Value, error) {
110 return SetHasElementFunc.Call([]cty.Value{set, elem})
111}
112
113// SetUnion returns a new set containing all of the elements from the given
114// sets, which must have element types that can all be converted to some
115// common type using the standard type unification rules. If conversion
116// is not possible, an error is returned.
117//
118// The union operation is performed after type conversion, which may result
119// in some previously-distinct values being conflated.
120//
121// At least one set must be provided.
122func SetUnion(sets ...cty.Value) (cty.Value, error) {
123 return SetUnionFunc.Call(sets)
124}
125
126// Intersection returns a new set containing the elements that exist
127// in all of the given sets, which must have element types that can all be
128// converted to some common type using the standard type unification rules.
129// If conversion is not possible, an error is returned.
130//
131// The intersection operation is performed after type conversion, which may
132// result in some previously-distinct values being conflated.
133//
134// At least one set must be provided.
135func SetIntersection(sets ...cty.Value) (cty.Value, error) {
136 return SetIntersectionFunc.Call(sets)
137}
138
139// SetSubtract returns a new set containing the elements from the
140// first set that are not present in the second set. The sets must have
141// element types that can both be converted to some common type using the
142// standard type unification rules. If conversion is not possible, an error
143// is returned.
144//
145// The subtract operation is performed after type conversion, which may
146// result in some previously-distinct values being conflated.
147func SetSubtract(a, b cty.Value) (cty.Value, error) {
148 return SetSubtractFunc.Call([]cty.Value{a, b})
149}
150
151// SetSymmetricDifference returns a new set containing elements that appear
152// in any of the given sets but not multiple. The sets must have
153// element types that can all be converted to some common type using the
154// standard type unification rules. If conversion is not possible, an error
155// is returned.
156//
157// The difference operation is performed after type conversion, which may
158// result in some previously-distinct values being conflated.
159func SetSymmetricDifference(sets ...cty.Value) (cty.Value, error) {
160 return SetSymmetricDifferenceFunc.Call(sets)
161}
162
163func setOperationReturnType(args []cty.Value) (ret cty.Type, err error) {
164 var etys []cty.Type
165 for _, arg := range args {
166 etys = append(etys, arg.Type().ElementType())
167 }
168 newEty, _ := convert.UnifyUnsafe(etys)
169 if newEty == cty.NilType {
170 return cty.NilType, fmt.Errorf("given sets must all have compatible element types")
171 }
172 return cty.Set(newEty), nil
173}
174
175func setOperationImpl(f func(s1, s2 cty.ValueSet) cty.ValueSet) function.ImplFunc {
176 return func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
177 first := args[0]
178 first, err = convert.Convert(first, retType)
179 if err != nil {
180 return cty.NilVal, function.NewArgError(0, err)
181 }
182
183 set := first.AsValueSet()
184 for i, arg := range args[1:] {
185 arg, err := convert.Convert(arg, retType)
186 if err != nil {
187 return cty.NilVal, function.NewArgError(i+1, err)
188 }
189
190 argSet := arg.AsValueSet()
191 set = f(set, argSet)
192 }
193 return cty.SetValFromValueSet(set), nil
194 }
195}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
new file mode 100644
index 0000000..d7c89fa
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
@@ -0,0 +1,234 @@
1package stdlib
2
3import (
4 "strings"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/function"
8 "github.com/zclconf/go-cty/cty/gocty"
9 "github.com/apparentlymart/go-textseg/textseg"
10)
11
12var UpperFunc = function.New(&function.Spec{
13 Params: []function.Parameter{
14 {
15 Name: "str",
16 Type: cty.String,
17 AllowDynamicType: true,
18 },
19 },
20 Type: function.StaticReturnType(cty.String),
21 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
22 in := args[0].AsString()
23 out := strings.ToUpper(in)
24 return cty.StringVal(out), nil
25 },
26})
27
28var LowerFunc = function.New(&function.Spec{
29 Params: []function.Parameter{
30 {
31 Name: "str",
32 Type: cty.String,
33 AllowDynamicType: true,
34 },
35 },
36 Type: function.StaticReturnType(cty.String),
37 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
38 in := args[0].AsString()
39 out := strings.ToLower(in)
40 return cty.StringVal(out), nil
41 },
42})
43
44var ReverseFunc = function.New(&function.Spec{
45 Params: []function.Parameter{
46 {
47 Name: "str",
48 Type: cty.String,
49 AllowDynamicType: true,
50 },
51 },
52 Type: function.StaticReturnType(cty.String),
53 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
54 in := []byte(args[0].AsString())
55 out := make([]byte, len(in))
56 pos := len(out)
57
58 inB := []byte(in)
59 for i := 0; i < len(in); {
60 d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
61 cluster := in[i : i+d]
62 pos -= len(cluster)
63 copy(out[pos:], cluster)
64 i += d
65 }
66
67 return cty.StringVal(string(out)), nil
68 },
69})
70
71var StrlenFunc = function.New(&function.Spec{
72 Params: []function.Parameter{
73 {
74 Name: "str",
75 Type: cty.String,
76 AllowDynamicType: true,
77 },
78 },
79 Type: function.StaticReturnType(cty.Number),
80 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
81 in := args[0].AsString()
82 l := 0
83
84 inB := []byte(in)
85 for i := 0; i < len(in); {
86 d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
87 l++
88 i += d
89 }
90
91 return cty.NumberIntVal(int64(l)), nil
92 },
93})
94
95var SubstrFunc = function.New(&function.Spec{
96 Params: []function.Parameter{
97 {
98 Name: "str",
99 Type: cty.String,
100 AllowDynamicType: true,
101 },
102 {
103 Name: "offset",
104 Type: cty.Number,
105 AllowDynamicType: true,
106 },
107 {
108 Name: "length",
109 Type: cty.Number,
110 AllowDynamicType: true,
111 },
112 },
113 Type: function.StaticReturnType(cty.String),
114 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
115 in := []byte(args[0].AsString())
116 var offset, length int
117
118 var err error
119 err = gocty.FromCtyValue(args[1], &offset)
120 if err != nil {
121 return cty.NilVal, err
122 }
123 err = gocty.FromCtyValue(args[2], &length)
124 if err != nil {
125 return cty.NilVal, err
126 }
127
128 if offset < 0 {
129 totalLenNum, err := Strlen(args[0])
130 if err != nil {
131 // should never happen
132 panic("Stdlen returned an error")
133 }
134
135 var totalLen int
136 err = gocty.FromCtyValue(totalLenNum, &totalLen)
137 if err != nil {
138 // should never happen
139 panic("Stdlen returned a non-int number")
140 }
141
142 offset += totalLen
143 }
144
145 sub := in
146 pos := 0
147 var i int
148
149 // First we'll seek forward to our offset
150 if offset > 0 {
151 for i = 0; i < len(sub); {
152 d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
153 i += d
154 pos++
155 if pos == offset {
156 break
157 }
158 if i >= len(in) {
159 return cty.StringVal(""), nil
160 }
161 }
162
163 sub = sub[i:]
164 }
165
166 if length < 0 {
167 // Taking the remainder of the string is a fast path since
168 // we can just return the rest of the buffer verbatim.
169 return cty.StringVal(string(sub)), nil
170 }
171
172 // Otherwise we need to start seeking forward again until we
173 // reach the length we want.
174 pos = 0
175 for i = 0; i < len(sub); {
176 d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
177 i += d
178 pos++
179 if pos == length {
180 break
181 }
182 }
183
184 sub = sub[:i]
185
186 return cty.StringVal(string(sub)), nil
187 },
188})
189
190// Upper is a Function that converts a given string to uppercase.
191func Upper(str cty.Value) (cty.Value, error) {
192 return UpperFunc.Call([]cty.Value{str})
193}
194
195// Lower is a Function that converts a given string to lowercase.
196func Lower(str cty.Value) (cty.Value, error) {
197 return LowerFunc.Call([]cty.Value{str})
198}
199
200// Reverse is a Function that reverses the order of the characters in the
201// given string.
202//
203// As usual, "character" for the sake of this function is a grapheme cluster,
204// so combining diacritics (for example) will be considered together as a
205// single character.
206func Reverse(str cty.Value) (cty.Value, error) {
207 return ReverseFunc.Call([]cty.Value{str})
208}
209
210// Strlen is a Function that returns the length of the given string in
211// characters.
212//
213// As usual, "character" for the sake of this function is a grapheme cluster,
214// so combining diacritics (for example) will be considered together as a
215// single character.
216func Strlen(str cty.Value) (cty.Value, error) {
217 return StrlenFunc.Call([]cty.Value{str})
218}
219
220// Substr is a Function that extracts a sequence of characters from another
221// string and creates a new string.
222//
223// As usual, "character" for the sake of this function is a grapheme cluster,
224// so combining diacritics (for example) will be considered together as a
225// single character.
226//
227// The "offset" index may be negative, in which case it is relative to the
228// end of the given string.
229//
230// The "length" may be -1, in which case the remainder of the string after
231// the given offset will be returned.
232func Substr(str cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) {
233 return SubstrFunc.Call([]cty.Value{str, offset, length})
234}
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go b/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go
new file mode 100644
index 0000000..3495550
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/function/unpredictable.go
@@ -0,0 +1,31 @@
1package function
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// Unpredictable wraps a given function such that it retains the same arguments
8// and type checking behavior but will return an unknown value when called.
9//
10// It is recommended that most functions be "pure", which is to say that they
11// will always produce the same value given particular input. However,
12// sometimes it is necessary to offer functions whose behavior depends on
13// some external state, such as reading a file or determining the current time.
14// In such cases, an unpredictable wrapper might be used to stand in for
15// the function during some sort of prior "checking" phase in order to delay
16// the actual effect until later.
17//
18// While Unpredictable can support a function that isn't pure in its
19// implementation, it still expects a function to be pure in its type checking
20// behavior, except for the special case of returning cty.DynamicPseudoType
21// if it is not yet able to predict its return value based on current argument
22// information.
23func Unpredictable(f Function) Function {
24 newSpec := *f.spec // shallow copy
25 newSpec.Impl = unpredictableImpl
26 return New(&newSpec)
27}
28
29func unpredictableImpl(args []cty.Value, retType cty.Type) (cty.Value, error) {
30 return cty.UnknownVal(retType), nil
31}