diff options
author | appilon <apilon@hashicorp.com> | 2019-02-27 16:43:31 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-27 16:43:31 -0500 |
commit | 844b5a68d8af4791755b8f0ad293cc99f5959183 (patch) | |
tree | 255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/zclconf/go-cty/cty/function/stdlib | |
parent | 303b299eeb6b06e939e35905e4b34cb410dd9dc3 (diff) | |
parent | 15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (diff) | |
download | terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.tar.gz terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.tar.zst terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.zip |
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[MODULES] Switch to Go Modules
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/function/stdlib')
14 files changed, 2633 insertions, 0 deletions
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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
4 | "github.com/zclconf/go-cty/cty" | ||
5 | "github.com/zclconf/go-cty/cty/function" | ||
6 | ) | ||
7 | |||
8 | var 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 | |||
22 | var 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 | |||
41 | var 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. | ||
61 | func 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. | ||
66 | func 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. | ||
71 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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. | ||
15 | var 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. | ||
22 | func 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. | ||
32 | var 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. | ||
48 | var 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 | |||
106 | func BytesLen(buf cty.Value) (cty.Value, error) { | ||
107 | return BytesLenFunc.Call([]cty.Value{buf}) | ||
108 | } | ||
109 | |||
110 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
11 | var 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 | |||
36 | var 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 | |||
105 | var 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. | ||
127 | func 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. | ||
133 | func 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. | ||
138 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
13 | var 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. | ||
91 | func 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. | ||
13 | package 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
20 | var 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 | |||
47 | var 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. | ||
239 | func 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. | ||
254 | func 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 | |||
261 | type 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. | ||
283 | func 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 | |||
327 | func 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 | |||
357 | func 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 | |||
372 | func 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 | |||
394 | func 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 | |||
409 | func 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 | |||
456 | func 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. | ||
485 | func 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 | |||
6 | package stdlib | ||
7 | |||
8 | import ( | ||
9 | "bytes" | ||
10 | "fmt" | ||
11 | "unicode/utf8" | ||
12 | |||
13 | "github.com/zclconf/go-cty/cty" | ||
14 | ) | ||
15 | |||
16 | // line 20 "format_fsm.go" | ||
17 | var _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 | |||
27 | var _formatfsm_key_offsets []byte = []byte{ | ||
28 | 0, 0, 14, 27, 34, 36, 39, 43, | ||
29 | 51, | ||
30 | } | ||
31 | |||
32 | var _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 | |||
42 | var _formatfsm_single_lengths []byte = []byte{ | ||
43 | 0, 8, 7, 1, 0, 1, 0, 2, | ||
44 | 1, | ||
45 | } | ||
46 | |||
47 | var _formatfsm_range_lengths []byte = []byte{ | ||
48 | 0, 3, 3, 3, 1, 1, 2, 3, | ||
49 | 0, | ||
50 | } | ||
51 | |||
52 | var _formatfsm_index_offsets []byte = []byte{ | ||
53 | 0, 0, 12, 23, 28, 30, 33, 36, | ||
54 | 42, | ||
55 | } | ||
56 | |||
57 | var _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 | |||
66 | var _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 | |||
72 | var _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 | |||
78 | var _formatfsm_eof_actions []byte = []byte{ | ||
79 | 0, 31, 31, 31, 31, 31, 31, 31, | ||
80 | 5, | ||
81 | } | ||
82 | |||
83 | const formatfsm_start int = 8 | ||
84 | const formatfsm_first_final int = 8 | ||
85 | const formatfsm_error int = 0 | ||
86 | |||
87 | const formatfsm_en_main int = 8 | ||
88 | |||
89 | // line 19 "format_fsm.rl" | ||
90 | |||
91 | func 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 | |||
7 | package stdlib | ||
8 | |||
9 | import ( | ||
10 | "bytes" | ||
11 | "fmt" | ||
12 | "unicode/utf8" | ||
13 | |||
14 | "github.com/zclconf/go-cty/cty" | ||
15 | ) | ||
16 | |||
17 | %%{ | ||
18 | write data; | ||
19 | }%% | ||
20 | |||
21 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
11 | var 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 | |||
34 | var 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 | |||
57 | var 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. | ||
94 | func 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. | ||
99 | func 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. | ||
105 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
9 | var 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 | |||
36 | var 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. | ||
59 | func 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. | ||
70 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "math/big" | ||
6 | |||
7 | "github.com/zclconf/go-cty/cty" | ||
8 | "github.com/zclconf/go-cty/cty/function" | ||
9 | ) | ||
10 | |||
11 | var 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 | |||
25 | var 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 | |||
58 | var 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 | |||
91 | var 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 | |||
125 | var 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 | |||
159 | var 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 | |||
193 | var 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 | |||
212 | var 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 | |||
231 | var 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 | |||
250 | var 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 | |||
269 | var 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 | |||
283 | var 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 | |||
307 | var 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 | |||
331 | var 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. | ||
353 | func 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. | ||
358 | func 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. | ||
363 | func 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. | ||
368 | func 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. | ||
373 | func 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. | ||
378 | func 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. | ||
383 | func 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. | ||
388 | func 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. | ||
393 | func 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. | ||
398 | func 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. | ||
404 | func 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. | ||
409 | func Min(numbers ...cty.Value) (cty.Value, error) { | ||
410 | return MinFunc.Call(numbers) | ||
411 | } | ||
412 | |||
413 | // Max returns the maximum number from the given numbers. | ||
414 | func 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. | ||
423 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
11 | var 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. | ||
128 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
12 | var 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 | |||
31 | var 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 | |||
50 | var 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 | |||
69 | var 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 | |||
88 | var 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. | ||
109 | func 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. | ||
122 | func 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. | ||
135 | func 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. | ||
147 | func 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. | ||
159 | func SetSymmetricDifference(sets ...cty.Value) (cty.Value, error) { | ||
160 | return SetSymmetricDifferenceFunc.Call(sets) | ||
161 | } | ||
162 | |||
163 | func 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 | |||
175 | func 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 @@ | |||
1 | package stdlib | ||
2 | |||
3 | import ( | ||
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 | |||
12 | var 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 | |||
28 | var 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 | |||
44 | var 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 | |||
71 | var 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 | |||
95 | var 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. | ||
191 | func 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. | ||
196 | func 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. | ||
206 | func 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. | ||
216 | func 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. | ||
232 | func Substr(str cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) { | ||
233 | return SubstrFunc.Call([]cty.Value{str, offset, length}) | ||
234 | } | ||