diff options
Diffstat (limited to 'vendor/github.com/mitchellh/reflectwalk')
5 files changed, 399 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/reflectwalk/LICENSE b/vendor/github.com/mitchellh/reflectwalk/LICENSE new file mode 100644 index 0000000..f9c841a --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | The MIT License (MIT) | ||
2 | |||
3 | Copyright (c) 2013 Mitchell Hashimoto | ||
4 | |||
5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | of this software and associated documentation files (the "Software"), to deal | ||
7 | in the Software without restriction, including without limitation the rights | ||
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | copies of the Software, and to permit persons to whom the Software is | ||
10 | furnished to do so, subject to the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be included in | ||
13 | all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
21 | THE SOFTWARE. | ||
diff --git a/vendor/github.com/mitchellh/reflectwalk/README.md b/vendor/github.com/mitchellh/reflectwalk/README.md new file mode 100644 index 0000000..ac82cd2 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/README.md | |||
@@ -0,0 +1,6 @@ | |||
1 | # reflectwalk | ||
2 | |||
3 | reflectwalk is a Go library for "walking" a value in Go using reflection, | ||
4 | in the same way a directory tree can be "walked" on the filesystem. Walking | ||
5 | a complex structure can allow you to do manipulations on unknown structures | ||
6 | such as those decoded from JSON. | ||
diff --git a/vendor/github.com/mitchellh/reflectwalk/location.go b/vendor/github.com/mitchellh/reflectwalk/location.go new file mode 100644 index 0000000..7c59d76 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/location.go | |||
@@ -0,0 +1,17 @@ | |||
1 | package reflectwalk | ||
2 | |||
3 | //go:generate stringer -type=Location location.go | ||
4 | |||
5 | type Location uint | ||
6 | |||
7 | const ( | ||
8 | None Location = iota | ||
9 | Map | ||
10 | MapKey | ||
11 | MapValue | ||
12 | Slice | ||
13 | SliceElem | ||
14 | Struct | ||
15 | StructField | ||
16 | WalkLoc | ||
17 | ) | ||
diff --git a/vendor/github.com/mitchellh/reflectwalk/location_string.go b/vendor/github.com/mitchellh/reflectwalk/location_string.go new file mode 100644 index 0000000..d3cfe85 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/location_string.go | |||
@@ -0,0 +1,16 @@ | |||
1 | // generated by stringer -type=Location location.go; DO NOT EDIT | ||
2 | |||
3 | package reflectwalk | ||
4 | |||
5 | import "fmt" | ||
6 | |||
7 | const _Location_name = "NoneMapMapKeyMapValueSliceSliceElemStructStructFieldWalkLoc" | ||
8 | |||
9 | var _Location_index = [...]uint8{0, 4, 7, 13, 21, 26, 35, 41, 52, 59} | ||
10 | |||
11 | func (i Location) String() string { | ||
12 | if i+1 >= Location(len(_Location_index)) { | ||
13 | return fmt.Sprintf("Location(%d)", i) | ||
14 | } | ||
15 | return _Location_name[_Location_index[i]:_Location_index[i+1]] | ||
16 | } | ||
diff --git a/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go new file mode 100644 index 0000000..ec0a623 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go | |||
@@ -0,0 +1,339 @@ | |||
1 | // reflectwalk is a package that allows you to "walk" complex structures | ||
2 | // similar to how you may "walk" a filesystem: visiting every element one | ||
3 | // by one and calling callback functions allowing you to handle and manipulate | ||
4 | // those elements. | ||
5 | package reflectwalk | ||
6 | |||
7 | import ( | ||
8 | "errors" | ||
9 | "reflect" | ||
10 | ) | ||
11 | |||
12 | // PrimitiveWalker implementations are able to handle primitive values | ||
13 | // within complex structures. Primitive values are numbers, strings, | ||
14 | // booleans, funcs, chans. | ||
15 | // | ||
16 | // These primitive values are often members of more complex | ||
17 | // structures (slices, maps, etc.) that are walkable by other interfaces. | ||
18 | type PrimitiveWalker interface { | ||
19 | Primitive(reflect.Value) error | ||
20 | } | ||
21 | |||
22 | // InterfaceWalker implementations are able to handle interface values as they | ||
23 | // are encountered during the walk. | ||
24 | type InterfaceWalker interface { | ||
25 | Interface(reflect.Value) error | ||
26 | } | ||
27 | |||
28 | // MapWalker implementations are able to handle individual elements | ||
29 | // found within a map structure. | ||
30 | type MapWalker interface { | ||
31 | Map(m reflect.Value) error | ||
32 | MapElem(m, k, v reflect.Value) error | ||
33 | } | ||
34 | |||
35 | // SliceWalker implementations are able to handle slice elements found | ||
36 | // within complex structures. | ||
37 | type SliceWalker interface { | ||
38 | Slice(reflect.Value) error | ||
39 | SliceElem(int, reflect.Value) error | ||
40 | } | ||
41 | |||
42 | // StructWalker is an interface that has methods that are called for | ||
43 | // structs when a Walk is done. | ||
44 | type StructWalker interface { | ||
45 | Struct(reflect.Value) error | ||
46 | StructField(reflect.StructField, reflect.Value) error | ||
47 | } | ||
48 | |||
49 | // EnterExitWalker implementations are notified before and after | ||
50 | // they walk deeper into complex structures (into struct fields, | ||
51 | // into slice elements, etc.) | ||
52 | type EnterExitWalker interface { | ||
53 | Enter(Location) error | ||
54 | Exit(Location) error | ||
55 | } | ||
56 | |||
57 | // PointerWalker implementations are notified when the value they're | ||
58 | // walking is a pointer or not. Pointer is called for _every_ value whether | ||
59 | // it is a pointer or not. | ||
60 | type PointerWalker interface { | ||
61 | PointerEnter(bool) error | ||
62 | PointerExit(bool) error | ||
63 | } | ||
64 | |||
65 | // SkipEntry can be returned from walk functions to skip walking | ||
66 | // the value of this field. This is only valid in the following functions: | ||
67 | // | ||
68 | // - StructField: skips walking the struct value | ||
69 | // | ||
70 | var SkipEntry = errors.New("skip this entry") | ||
71 | |||
72 | // Walk takes an arbitrary value and an interface and traverses the | ||
73 | // value, calling callbacks on the interface if they are supported. | ||
74 | // The interface should implement one or more of the walker interfaces | ||
75 | // in this package, such as PrimitiveWalker, StructWalker, etc. | ||
76 | func Walk(data, walker interface{}) (err error) { | ||
77 | v := reflect.ValueOf(data) | ||
78 | ew, ok := walker.(EnterExitWalker) | ||
79 | if ok { | ||
80 | err = ew.Enter(WalkLoc) | ||
81 | } | ||
82 | |||
83 | if err == nil { | ||
84 | err = walk(v, walker) | ||
85 | } | ||
86 | |||
87 | if ok && err == nil { | ||
88 | err = ew.Exit(WalkLoc) | ||
89 | } | ||
90 | |||
91 | return | ||
92 | } | ||
93 | |||
94 | func walk(v reflect.Value, w interface{}) (err error) { | ||
95 | // Determine if we're receiving a pointer and if so notify the walker. | ||
96 | // The logic here is convoluted but very important (tests will fail if | ||
97 | // almost any part is changed). I will try to explain here. | ||
98 | // | ||
99 | // First, we check if the value is an interface, if so, we really need | ||
100 | // to check the interface's VALUE to see whether it is a pointer. | ||
101 | // | ||
102 | // Check whether the value is then a pointer. If so, then set pointer | ||
103 | // to true to notify the user. | ||
104 | // | ||
105 | // If we still have a pointer or an interface after the indirections, then | ||
106 | // we unwrap another level | ||
107 | // | ||
108 | // At this time, we also set "v" to be the dereferenced value. This is | ||
109 | // because once we've unwrapped the pointer we want to use that value. | ||
110 | pointer := false | ||
111 | pointerV := v | ||
112 | |||
113 | for { | ||
114 | if pointerV.Kind() == reflect.Interface { | ||
115 | if iw, ok := w.(InterfaceWalker); ok { | ||
116 | if err = iw.Interface(pointerV); err != nil { | ||
117 | return | ||
118 | } | ||
119 | } | ||
120 | |||
121 | pointerV = pointerV.Elem() | ||
122 | } | ||
123 | |||
124 | if pointerV.Kind() == reflect.Ptr { | ||
125 | pointer = true | ||
126 | v = reflect.Indirect(pointerV) | ||
127 | } | ||
128 | if pw, ok := w.(PointerWalker); ok { | ||
129 | if err = pw.PointerEnter(pointer); err != nil { | ||
130 | return | ||
131 | } | ||
132 | |||
133 | defer func(pointer bool) { | ||
134 | if err != nil { | ||
135 | return | ||
136 | } | ||
137 | |||
138 | err = pw.PointerExit(pointer) | ||
139 | }(pointer) | ||
140 | } | ||
141 | |||
142 | if pointer { | ||
143 | pointerV = v | ||
144 | } | ||
145 | pointer = false | ||
146 | |||
147 | // If we still have a pointer or interface we have to indirect another level. | ||
148 | switch pointerV.Kind() { | ||
149 | case reflect.Ptr, reflect.Interface: | ||
150 | continue | ||
151 | } | ||
152 | break | ||
153 | } | ||
154 | |||
155 | // We preserve the original value here because if it is an interface | ||
156 | // type, we want to pass that directly into the walkPrimitive, so that | ||
157 | // we can set it. | ||
158 | originalV := v | ||
159 | if v.Kind() == reflect.Interface { | ||
160 | v = v.Elem() | ||
161 | } | ||
162 | |||
163 | k := v.Kind() | ||
164 | if k >= reflect.Int && k <= reflect.Complex128 { | ||
165 | k = reflect.Int | ||
166 | } | ||
167 | |||
168 | switch k { | ||
169 | // Primitives | ||
170 | case reflect.Bool, reflect.Chan, reflect.Func, reflect.Int, reflect.String, reflect.Invalid: | ||
171 | err = walkPrimitive(originalV, w) | ||
172 | return | ||
173 | case reflect.Map: | ||
174 | err = walkMap(v, w) | ||
175 | return | ||
176 | case reflect.Slice: | ||
177 | err = walkSlice(v, w) | ||
178 | return | ||
179 | case reflect.Struct: | ||
180 | err = walkStruct(v, w) | ||
181 | return | ||
182 | default: | ||
183 | panic("unsupported type: " + k.String()) | ||
184 | } | ||
185 | } | ||
186 | |||
187 | func walkMap(v reflect.Value, w interface{}) error { | ||
188 | ew, ewok := w.(EnterExitWalker) | ||
189 | if ewok { | ||
190 | ew.Enter(Map) | ||
191 | } | ||
192 | |||
193 | if mw, ok := w.(MapWalker); ok { | ||
194 | if err := mw.Map(v); err != nil { | ||
195 | return err | ||
196 | } | ||
197 | } | ||
198 | |||
199 | for _, k := range v.MapKeys() { | ||
200 | kv := v.MapIndex(k) | ||
201 | |||
202 | if mw, ok := w.(MapWalker); ok { | ||
203 | if err := mw.MapElem(v, k, kv); err != nil { | ||
204 | return err | ||
205 | } | ||
206 | } | ||
207 | |||
208 | ew, ok := w.(EnterExitWalker) | ||
209 | if ok { | ||
210 | ew.Enter(MapKey) | ||
211 | } | ||
212 | |||
213 | if err := walk(k, w); err != nil { | ||
214 | return err | ||
215 | } | ||
216 | |||
217 | if ok { | ||
218 | ew.Exit(MapKey) | ||
219 | ew.Enter(MapValue) | ||
220 | } | ||
221 | |||
222 | if err := walk(kv, w); err != nil { | ||
223 | return err | ||
224 | } | ||
225 | |||
226 | if ok { | ||
227 | ew.Exit(MapValue) | ||
228 | } | ||
229 | } | ||
230 | |||
231 | if ewok { | ||
232 | ew.Exit(Map) | ||
233 | } | ||
234 | |||
235 | return nil | ||
236 | } | ||
237 | |||
238 | func walkPrimitive(v reflect.Value, w interface{}) error { | ||
239 | if pw, ok := w.(PrimitiveWalker); ok { | ||
240 | return pw.Primitive(v) | ||
241 | } | ||
242 | |||
243 | return nil | ||
244 | } | ||
245 | |||
246 | func walkSlice(v reflect.Value, w interface{}) (err error) { | ||
247 | ew, ok := w.(EnterExitWalker) | ||
248 | if ok { | ||
249 | ew.Enter(Slice) | ||
250 | } | ||
251 | |||
252 | if sw, ok := w.(SliceWalker); ok { | ||
253 | if err := sw.Slice(v); err != nil { | ||
254 | return err | ||
255 | } | ||
256 | } | ||
257 | |||
258 | for i := 0; i < v.Len(); i++ { | ||
259 | elem := v.Index(i) | ||
260 | |||
261 | if sw, ok := w.(SliceWalker); ok { | ||
262 | if err := sw.SliceElem(i, elem); err != nil { | ||
263 | return err | ||
264 | } | ||
265 | } | ||
266 | |||
267 | ew, ok := w.(EnterExitWalker) | ||
268 | if ok { | ||
269 | ew.Enter(SliceElem) | ||
270 | } | ||
271 | |||
272 | if err := walk(elem, w); err != nil { | ||
273 | return err | ||
274 | } | ||
275 | |||
276 | if ok { | ||
277 | ew.Exit(SliceElem) | ||
278 | } | ||
279 | } | ||
280 | |||
281 | ew, ok = w.(EnterExitWalker) | ||
282 | if ok { | ||
283 | ew.Exit(Slice) | ||
284 | } | ||
285 | |||
286 | return nil | ||
287 | } | ||
288 | |||
289 | func walkStruct(v reflect.Value, w interface{}) (err error) { | ||
290 | ew, ewok := w.(EnterExitWalker) | ||
291 | if ewok { | ||
292 | ew.Enter(Struct) | ||
293 | } | ||
294 | |||
295 | if sw, ok := w.(StructWalker); ok { | ||
296 | if err = sw.Struct(v); err != nil { | ||
297 | return | ||
298 | } | ||
299 | } | ||
300 | |||
301 | vt := v.Type() | ||
302 | for i := 0; i < vt.NumField(); i++ { | ||
303 | sf := vt.Field(i) | ||
304 | f := v.FieldByIndex([]int{i}) | ||
305 | |||
306 | if sw, ok := w.(StructWalker); ok { | ||
307 | err = sw.StructField(sf, f) | ||
308 | |||
309 | // SkipEntry just pretends this field doesn't even exist | ||
310 | if err == SkipEntry { | ||
311 | continue | ||
312 | } | ||
313 | |||
314 | if err != nil { | ||
315 | return | ||
316 | } | ||
317 | } | ||
318 | |||
319 | ew, ok := w.(EnterExitWalker) | ||
320 | if ok { | ||
321 | ew.Enter(StructField) | ||
322 | } | ||
323 | |||
324 | err = walk(f, w) | ||
325 | if err != nil { | ||
326 | return | ||
327 | } | ||
328 | |||
329 | if ok { | ||
330 | ew.Exit(StructField) | ||
331 | } | ||
332 | } | ||
333 | |||
334 | if ewok { | ||
335 | ew.Exit(Struct) | ||
336 | } | ||
337 | |||
338 | return nil | ||
339 | } | ||