diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/ops.go')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/hcl/ops.go | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/ops.go b/vendor/github.com/hashicorp/hcl2/hcl/ops.go new file mode 100644 index 0000000..f4e30b0 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hcl/ops.go | |||
@@ -0,0 +1,147 @@ | |||
1 | package hcl | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/zclconf/go-cty/cty" | ||
7 | "github.com/zclconf/go-cty/cty/convert" | ||
8 | ) | ||
9 | |||
10 | // Index is a helper function that performs the same operation as the index | ||
11 | // operator in the HCL expression language. That is, the result is the | ||
12 | // same as it would be for collection[key] in a configuration expression. | ||
13 | // | ||
14 | // This is exported so that applications can perform indexing in a manner | ||
15 | // consistent with how the language does it, including handling of null and | ||
16 | // unknown values, etc. | ||
17 | // | ||
18 | // Diagnostics are produced if the given combination of values is not valid. | ||
19 | // Therefore a pointer to a source range must be provided to use in diagnostics, | ||
20 | // though nil can be provided if the calling application is going to | ||
21 | // ignore the subject of the returned diagnostics anyway. | ||
22 | func Index(collection, key cty.Value, srcRange *Range) (cty.Value, Diagnostics) { | ||
23 | if collection.IsNull() { | ||
24 | return cty.DynamicVal, Diagnostics{ | ||
25 | { | ||
26 | Severity: DiagError, | ||
27 | Summary: "Attempt to index null value", | ||
28 | Detail: "This value is null, so it does not have any indices.", | ||
29 | Subject: srcRange, | ||
30 | }, | ||
31 | } | ||
32 | } | ||
33 | if key.IsNull() { | ||
34 | return cty.DynamicVal, Diagnostics{ | ||
35 | { | ||
36 | Severity: DiagError, | ||
37 | Summary: "Invalid index", | ||
38 | Detail: "Can't use a null value as an indexing key.", | ||
39 | Subject: srcRange, | ||
40 | }, | ||
41 | } | ||
42 | } | ||
43 | ty := collection.Type() | ||
44 | kty := key.Type() | ||
45 | if kty == cty.DynamicPseudoType || ty == cty.DynamicPseudoType { | ||
46 | return cty.DynamicVal, nil | ||
47 | } | ||
48 | |||
49 | switch { | ||
50 | |||
51 | case ty.IsListType() || ty.IsTupleType() || ty.IsMapType(): | ||
52 | var wantType cty.Type | ||
53 | switch { | ||
54 | case ty.IsListType() || ty.IsTupleType(): | ||
55 | wantType = cty.Number | ||
56 | case ty.IsMapType(): | ||
57 | wantType = cty.String | ||
58 | default: | ||
59 | // should never happen | ||
60 | panic("don't know what key type we want") | ||
61 | } | ||
62 | |||
63 | key, keyErr := convert.Convert(key, wantType) | ||
64 | if keyErr != nil { | ||
65 | return cty.DynamicVal, Diagnostics{ | ||
66 | { | ||
67 | Severity: DiagError, | ||
68 | Summary: "Invalid index", | ||
69 | Detail: fmt.Sprintf( | ||
70 | "The given key does not identify an element in this collection value: %s.", | ||
71 | keyErr.Error(), | ||
72 | ), | ||
73 | Subject: srcRange, | ||
74 | }, | ||
75 | } | ||
76 | } | ||
77 | |||
78 | has := collection.HasIndex(key) | ||
79 | if !has.IsKnown() { | ||
80 | if ty.IsTupleType() { | ||
81 | return cty.DynamicVal, nil | ||
82 | } else { | ||
83 | return cty.UnknownVal(ty.ElementType()), nil | ||
84 | } | ||
85 | } | ||
86 | if has.False() { | ||
87 | return cty.DynamicVal, Diagnostics{ | ||
88 | { | ||
89 | Severity: DiagError, | ||
90 | Summary: "Invalid index", | ||
91 | Detail: "The given key does not identify an element in this collection value.", | ||
92 | Subject: srcRange, | ||
93 | }, | ||
94 | } | ||
95 | } | ||
96 | |||
97 | return collection.Index(key), nil | ||
98 | |||
99 | case ty.IsObjectType(): | ||
100 | key, keyErr := convert.Convert(key, cty.String) | ||
101 | if keyErr != nil { | ||
102 | return cty.DynamicVal, Diagnostics{ | ||
103 | { | ||
104 | Severity: DiagError, | ||
105 | Summary: "Invalid index", | ||
106 | Detail: fmt.Sprintf( | ||
107 | "The given key does not identify an element in this collection value: %s.", | ||
108 | keyErr.Error(), | ||
109 | ), | ||
110 | Subject: srcRange, | ||
111 | }, | ||
112 | } | ||
113 | } | ||
114 | if !collection.IsKnown() { | ||
115 | return cty.DynamicVal, nil | ||
116 | } | ||
117 | if !key.IsKnown() { | ||
118 | return cty.DynamicVal, nil | ||
119 | } | ||
120 | |||
121 | attrName := key.AsString() | ||
122 | |||
123 | if !ty.HasAttribute(attrName) { | ||
124 | return cty.DynamicVal, Diagnostics{ | ||
125 | { | ||
126 | Severity: DiagError, | ||
127 | Summary: "Invalid index", | ||
128 | Detail: "The given key does not identify an element in this collection value.", | ||
129 | Subject: srcRange, | ||
130 | }, | ||
131 | } | ||
132 | } | ||
133 | |||
134 | return collection.GetAttr(attrName), nil | ||
135 | |||
136 | default: | ||
137 | return cty.DynamicVal, Diagnostics{ | ||
138 | { | ||
139 | Severity: DiagError, | ||
140 | Summary: "Invalid index", | ||
141 | Detail: "This value does not have any indices.", | ||
142 | Subject: srcRange, | ||
143 | }, | ||
144 | } | ||
145 | } | ||
146 | |||
147 | } | ||