diff options
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go')
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go | 140 |
1 files changed, 140 insertions, 0 deletions
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 | } | ||