aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/mitchellh/copystructure/copystructure.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mitchellh/copystructure/copystructure.go')
-rw-r--r--vendor/github.com/mitchellh/copystructure/copystructure.go87
1 files changed, 79 insertions, 8 deletions
diff --git a/vendor/github.com/mitchellh/copystructure/copystructure.go b/vendor/github.com/mitchellh/copystructure/copystructure.go
index 0e725ea..1404352 100644
--- a/vendor/github.com/mitchellh/copystructure/copystructure.go
+++ b/vendor/github.com/mitchellh/copystructure/copystructure.go
@@ -156,9 +156,13 @@ func (w *walker) Exit(l reflectwalk.Location) error {
156 } 156 }
157 157
158 switch l { 158 switch l {
159 case reflectwalk.Array:
160 fallthrough
159 case reflectwalk.Map: 161 case reflectwalk.Map:
160 fallthrough 162 fallthrough
161 case reflectwalk.Slice: 163 case reflectwalk.Slice:
164 w.replacePointerMaybe()
165
162 // Pop map off our container 166 // Pop map off our container
163 w.cs = w.cs[:len(w.cs)-1] 167 w.cs = w.cs[:len(w.cs)-1]
164 case reflectwalk.MapValue: 168 case reflectwalk.MapValue:
@@ -171,16 +175,27 @@ func (w *walker) Exit(l reflectwalk.Location) error {
171 // or in this case never adds it. We need to create a properly typed 175 // or in this case never adds it. We need to create a properly typed
172 // zero value so that this key can be set. 176 // zero value so that this key can be set.
173 if !mv.IsValid() { 177 if !mv.IsValid() {
174 mv = reflect.Zero(m.Type().Elem()) 178 mv = reflect.Zero(m.Elem().Type().Elem())
179 }
180 m.Elem().SetMapIndex(mk, mv)
181 case reflectwalk.ArrayElem:
182 // Pop off the value and the index and set it on the array
183 v := w.valPop()
184 i := w.valPop().Interface().(int)
185 if v.IsValid() {
186 a := w.cs[len(w.cs)-1]
187 ae := a.Elem().Index(i) // storing array as pointer on stack - so need Elem() call
188 if ae.CanSet() {
189 ae.Set(v)
190 }
175 } 191 }
176 m.SetMapIndex(mk, mv)
177 case reflectwalk.SliceElem: 192 case reflectwalk.SliceElem:
178 // Pop off the value and the index and set it on the slice 193 // Pop off the value and the index and set it on the slice
179 v := w.valPop() 194 v := w.valPop()
180 i := w.valPop().Interface().(int) 195 i := w.valPop().Interface().(int)
181 if v.IsValid() { 196 if v.IsValid() {
182 s := w.cs[len(w.cs)-1] 197 s := w.cs[len(w.cs)-1]
183 se := s.Index(i) 198 se := s.Elem().Index(i)
184 if se.CanSet() { 199 if se.CanSet() {
185 se.Set(v) 200 se.Set(v)
186 } 201 }
@@ -220,9 +235,9 @@ func (w *walker) Map(m reflect.Value) error {
220 // Create the map. If the map itself is nil, then just make a nil map 235 // Create the map. If the map itself is nil, then just make a nil map
221 var newMap reflect.Value 236 var newMap reflect.Value
222 if m.IsNil() { 237 if m.IsNil() {
223 newMap = reflect.Indirect(reflect.New(m.Type())) 238 newMap = reflect.New(m.Type())
224 } else { 239 } else {
225 newMap = reflect.MakeMap(m.Type()) 240 newMap = wrapPtr(reflect.MakeMap(m.Type()))
226 } 241 }
227 242
228 w.cs = append(w.cs, newMap) 243 w.cs = append(w.cs, newMap)
@@ -287,9 +302,9 @@ func (w *walker) Slice(s reflect.Value) error {
287 302
288 var newS reflect.Value 303 var newS reflect.Value
289 if s.IsNil() { 304 if s.IsNil() {
290 newS = reflect.Indirect(reflect.New(s.Type())) 305 newS = reflect.New(s.Type())
291 } else { 306 } else {
292 newS = reflect.MakeSlice(s.Type(), s.Len(), s.Cap()) 307 newS = wrapPtr(reflect.MakeSlice(s.Type(), s.Len(), s.Cap()))
293 } 308 }
294 309
295 w.cs = append(w.cs, newS) 310 w.cs = append(w.cs, newS)
@@ -309,6 +324,31 @@ func (w *walker) SliceElem(i int, elem reflect.Value) error {
309 return nil 324 return nil
310} 325}
311 326
327func (w *walker) Array(a reflect.Value) error {
328 if w.ignoring() {
329 return nil
330 }
331 w.lock(a)
332
333 newA := reflect.New(a.Type())
334
335 w.cs = append(w.cs, newA)
336 w.valPush(newA)
337 return nil
338}
339
340func (w *walker) ArrayElem(i int, elem reflect.Value) error {
341 if w.ignoring() {
342 return nil
343 }
344
345 // We don't write the array here because elem might still be
346 // arbitrarily complex. Just record the index and continue on.
347 w.valPush(reflect.ValueOf(i))
348
349 return nil
350}
351
312func (w *walker) Struct(s reflect.Value) error { 352func (w *walker) Struct(s reflect.Value) error {
313 if w.ignoring() { 353 if w.ignoring() {
314 return nil 354 return nil
@@ -326,7 +366,10 @@ func (w *walker) Struct(s reflect.Value) error {
326 return err 366 return err
327 } 367 }
328 368
329 v = reflect.ValueOf(dup) 369 // We need to put a pointer to the value on the value stack,
370 // so allocate a new pointer and set it.
371 v = reflect.New(s.Type())
372 reflect.Indirect(v).Set(reflect.ValueOf(dup))
330 } else { 373 } else {
331 // No copier, we copy ourselves and allow reflectwalk to guide 374 // No copier, we copy ourselves and allow reflectwalk to guide
332 // us deeper into the structure for copying. 375 // us deeper into the structure for copying.
@@ -405,6 +448,23 @@ func (w *walker) replacePointerMaybe() {
405 } 448 }
406 449
407 v := w.valPop() 450 v := w.valPop()
451
452 // If the expected type is a pointer to an interface of any depth,
453 // such as *interface{}, **interface{}, etc., then we need to convert
454 // the value "v" from *CONCRETE to *interface{} so types match for
455 // Set.
456 //
457 // Example if v is type *Foo where Foo is a struct, v would become
458 // *interface{} instead. This only happens if we have an interface expectation
459 // at this depth.
460 //
461 // For more info, see GH-16
462 if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)]; ok && iType.Kind() == reflect.Interface {
463 y := reflect.New(iType) // Create *interface{}
464 y.Elem().Set(reflect.Indirect(v)) // Assign "Foo" to interface{} (dereferenced)
465 v = y // v is now typed *interface{} (where *v = Foo)
466 }
467
408 for i := 1; i < w.ps[w.depth]; i++ { 468 for i := 1; i < w.ps[w.depth]; i++ {
409 if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok { 469 if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok {
410 iface := reflect.New(iType).Elem() 470 iface := reflect.New(iType).Elem()
@@ -475,3 +535,14 @@ func (w *walker) lock(v reflect.Value) {
475 locker.Lock() 535 locker.Lock()
476 w.locks[w.depth] = locker 536 w.locks[w.depth] = locker
477} 537}
538
539// wrapPtr is a helper that takes v and always make it *v. copystructure
540// stores things internally as pointers until the last moment before unwrapping
541func wrapPtr(v reflect.Value) reflect.Value {
542 if !v.IsValid() {
543 return v
544 }
545 vPtr := reflect.New(v.Type())
546 vPtr.Elem().Set(v)
547 return vPtr
548}