aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/element_iterator.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/element_iterator.go')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/element_iterator.go191
1 files changed, 191 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/element_iterator.go b/vendor/github.com/zclconf/go-cty/cty/element_iterator.go
new file mode 100644
index 0000000..0bf84c7
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/element_iterator.go
@@ -0,0 +1,191 @@
1package cty
2
3import (
4 "sort"
5
6 "github.com/zclconf/go-cty/cty/set"
7)
8
9// ElementIterator is the interface type returned by Value.ElementIterator to
10// allow the caller to iterate over elements of a collection-typed value.
11//
12// Its usage pattern is as follows:
13//
14// it := val.ElementIterator()
15// for it.Next() {
16// key, val := it.Element()
17// // ...
18// }
19type ElementIterator interface {
20 Next() bool
21 Element() (key Value, value Value)
22}
23
24func canElementIterator(val Value) bool {
25 switch {
26 case val.ty.IsListType():
27 return true
28 case val.ty.IsMapType():
29 return true
30 case val.ty.IsSetType():
31 return true
32 case val.ty.IsTupleType():
33 return true
34 case val.ty.IsObjectType():
35 return true
36 default:
37 return false
38 }
39}
40
41func elementIterator(val Value) ElementIterator {
42 switch {
43 case val.ty.IsListType():
44 return &listElementIterator{
45 ety: val.ty.ElementType(),
46 vals: val.v.([]interface{}),
47 idx: -1,
48 }
49 case val.ty.IsMapType():
50 // We iterate the keys in a predictable lexicographical order so
51 // that results will always be stable given the same input map.
52 rawMap := val.v.(map[string]interface{})
53 keys := make([]string, 0, len(rawMap))
54 for key := range rawMap {
55 keys = append(keys, key)
56 }
57 sort.Strings(keys)
58
59 return &mapElementIterator{
60 ety: val.ty.ElementType(),
61 vals: rawMap,
62 keys: keys,
63 idx: -1,
64 }
65 case val.ty.IsSetType():
66 rawSet := val.v.(set.Set)
67 return &setElementIterator{
68 ety: val.ty.ElementType(),
69 setIt: rawSet.Iterator(),
70 }
71 case val.ty.IsTupleType():
72 return &tupleElementIterator{
73 etys: val.ty.TupleElementTypes(),
74 vals: val.v.([]interface{}),
75 idx: -1,
76 }
77 case val.ty.IsObjectType():
78 // We iterate the keys in a predictable lexicographical order so
79 // that results will always be stable given the same object type.
80 atys := val.ty.AttributeTypes()
81 keys := make([]string, 0, len(atys))
82 for key := range atys {
83 keys = append(keys, key)
84 }
85 sort.Strings(keys)
86
87 return &objectElementIterator{
88 atys: atys,
89 vals: val.v.(map[string]interface{}),
90 attrNames: keys,
91 idx: -1,
92 }
93 default:
94 panic("attempt to iterate on non-collection, non-tuple type")
95 }
96}
97
98type listElementIterator struct {
99 ety Type
100 vals []interface{}
101 idx int
102}
103
104func (it *listElementIterator) Element() (Value, Value) {
105 i := it.idx
106 return NumberIntVal(int64(i)), Value{
107 ty: it.ety,
108 v: it.vals[i],
109 }
110}
111
112func (it *listElementIterator) Next() bool {
113 it.idx++
114 return it.idx < len(it.vals)
115}
116
117type mapElementIterator struct {
118 ety Type
119 vals map[string]interface{}
120 keys []string
121 idx int
122}
123
124func (it *mapElementIterator) Element() (Value, Value) {
125 key := it.keys[it.idx]
126 return StringVal(key), Value{
127 ty: it.ety,
128 v: it.vals[key],
129 }
130}
131
132func (it *mapElementIterator) Next() bool {
133 it.idx++
134 return it.idx < len(it.keys)
135}
136
137type setElementIterator struct {
138 ety Type
139 setIt *set.Iterator
140}
141
142func (it *setElementIterator) Element() (Value, Value) {
143 val := Value{
144 ty: it.ety,
145 v: it.setIt.Value(),
146 }
147 return val, val
148}
149
150func (it *setElementIterator) Next() bool {
151 return it.setIt.Next()
152}
153
154type tupleElementIterator struct {
155 etys []Type
156 vals []interface{}
157 idx int
158}
159
160func (it *tupleElementIterator) Element() (Value, Value) {
161 i := it.idx
162 return NumberIntVal(int64(i)), Value{
163 ty: it.etys[i],
164 v: it.vals[i],
165 }
166}
167
168func (it *tupleElementIterator) Next() bool {
169 it.idx++
170 return it.idx < len(it.vals)
171}
172
173type objectElementIterator struct {
174 atys map[string]Type
175 vals map[string]interface{}
176 attrNames []string
177 idx int
178}
179
180func (it *objectElementIterator) Element() (Value, Value) {
181 key := it.attrNames[it.idx]
182 return StringVal(key), Value{
183 ty: it.atys[key],
184 v: it.vals[key],
185 }
186}
187
188func (it *objectElementIterator) Next() bool {
189 it.idx++
190 return it.idx < len(it.attrNames)
191}