mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 01:53:42 +08:00 
			
		
		
		
	bump compose-go to version v2.1.3
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										21
									
								
								vendor/github.com/mitchellh/copystructure/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/mitchellh/copystructure/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,21 +0,0 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2014 Mitchell Hashimoto
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/mitchellh/copystructure/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/mitchellh/copystructure/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,21 +0,0 @@
 | 
			
		||||
# copystructure
 | 
			
		||||
 | 
			
		||||
copystructure is a Go library for deep copying values in Go.
 | 
			
		||||
 | 
			
		||||
This allows you to copy Go values that may contain reference values
 | 
			
		||||
such as maps, slices, or pointers, and copy their data as well instead
 | 
			
		||||
of just their references.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
Standard `go get`:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
$ go get github.com/mitchellh/copystructure
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Usage & Example
 | 
			
		||||
 | 
			
		||||
For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/copystructure).
 | 
			
		||||
 | 
			
		||||
The `Copy` function has examples associated with it there.
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/mitchellh/copystructure/copier_time.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/mitchellh/copystructure/copier_time.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,15 +0,0 @@
 | 
			
		||||
package copystructure
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	Copiers[reflect.TypeOf(time.Time{})] = timeCopier
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timeCopier(v interface{}) (interface{}, error) {
 | 
			
		||||
	// Just... copy it.
 | 
			
		||||
	return v.(time.Time), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										631
									
								
								vendor/github.com/mitchellh/copystructure/copystructure.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										631
									
								
								vendor/github.com/mitchellh/copystructure/copystructure.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,631 +0,0 @@
 | 
			
		||||
package copystructure
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/mitchellh/reflectwalk"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const tagKey = "copy"
 | 
			
		||||
 | 
			
		||||
// Copy returns a deep copy of v.
 | 
			
		||||
//
 | 
			
		||||
// Copy is unable to copy unexported fields in a struct (lowercase field names).
 | 
			
		||||
// Unexported fields can't be reflected by the Go runtime and therefore
 | 
			
		||||
// copystructure can't perform any data copies.
 | 
			
		||||
//
 | 
			
		||||
// For structs, copy behavior can be controlled with struct tags. For example:
 | 
			
		||||
//
 | 
			
		||||
//   struct {
 | 
			
		||||
//     Name string
 | 
			
		||||
//     Data *bytes.Buffer `copy:"shallow"`
 | 
			
		||||
//   }
 | 
			
		||||
//
 | 
			
		||||
// The available tag values are:
 | 
			
		||||
//
 | 
			
		||||
// * "ignore" - The field will be ignored, effectively resulting in it being
 | 
			
		||||
//   assigned the zero value in the copy.
 | 
			
		||||
//
 | 
			
		||||
// * "shallow" - The field will be be shallow copied. This means that references
 | 
			
		||||
//   values such as pointers, maps, slices, etc. will be directly assigned
 | 
			
		||||
//   versus deep copied.
 | 
			
		||||
//
 | 
			
		||||
func Copy(v interface{}) (interface{}, error) {
 | 
			
		||||
	return Config{}.Copy(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopierFunc is a function that knows how to deep copy a specific type.
 | 
			
		||||
// Register these globally with the Copiers variable.
 | 
			
		||||
type CopierFunc func(interface{}) (interface{}, error)
 | 
			
		||||
 | 
			
		||||
// Copiers is a map of types that behave specially when they are copied.
 | 
			
		||||
// If a type is found in this map while deep copying, this function
 | 
			
		||||
// will be called to copy it instead of attempting to copy all fields.
 | 
			
		||||
//
 | 
			
		||||
// The key should be the type, obtained using: reflect.TypeOf(value with type).
 | 
			
		||||
//
 | 
			
		||||
// It is unsafe to write to this map after Copies have started. If you
 | 
			
		||||
// are writing to this map while also copying, wrap all modifications to
 | 
			
		||||
// this map as well as to Copy in a mutex.
 | 
			
		||||
var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc)
 | 
			
		||||
 | 
			
		||||
// ShallowCopiers is a map of pointer types that behave specially
 | 
			
		||||
// when they are copied.  If a type is found in this map while deep
 | 
			
		||||
// copying, the pointer value will be shallow copied and not walked
 | 
			
		||||
// into.
 | 
			
		||||
//
 | 
			
		||||
// The key should be the type, obtained using: reflect.TypeOf(value
 | 
			
		||||
// with type).
 | 
			
		||||
//
 | 
			
		||||
// It is unsafe to write to this map after Copies have started. If you
 | 
			
		||||
// are writing to this map while also copying, wrap all modifications to
 | 
			
		||||
// this map as well as to Copy in a mutex.
 | 
			
		||||
var ShallowCopiers map[reflect.Type]struct{} = make(map[reflect.Type]struct{})
 | 
			
		||||
 | 
			
		||||
// Must is a helper that wraps a call to a function returning
 | 
			
		||||
// (interface{}, error) and panics if the error is non-nil. It is intended
 | 
			
		||||
// for use in variable initializations and should only be used when a copy
 | 
			
		||||
// error should be a crashing case.
 | 
			
		||||
func Must(v interface{}, err error) interface{} {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic("copy error: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true")
 | 
			
		||||
 | 
			
		||||
type Config struct {
 | 
			
		||||
	// Lock any types that are a sync.Locker and are not a mutex while copying.
 | 
			
		||||
	// If there is an RLocker method, use that to get the sync.Locker.
 | 
			
		||||
	Lock bool
 | 
			
		||||
 | 
			
		||||
	// Copiers is a map of types associated with a CopierFunc. Use the global
 | 
			
		||||
	// Copiers map if this is nil.
 | 
			
		||||
	Copiers map[reflect.Type]CopierFunc
 | 
			
		||||
 | 
			
		||||
	// ShallowCopiers is a map of pointer types that when they are
 | 
			
		||||
	// shallow copied no matter where they are encountered. Use the
 | 
			
		||||
	// global ShallowCopiers if this is nil.
 | 
			
		||||
	ShallowCopiers map[reflect.Type]struct{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c Config) Copy(v interface{}) (interface{}, error) {
 | 
			
		||||
	if c.Lock && reflect.ValueOf(v).Kind() != reflect.Ptr {
 | 
			
		||||
		return nil, errPointerRequired
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w := new(walker)
 | 
			
		||||
	if c.Lock {
 | 
			
		||||
		w.useLocks = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c.Copiers == nil {
 | 
			
		||||
		c.Copiers = Copiers
 | 
			
		||||
	}
 | 
			
		||||
	w.copiers = c.Copiers
 | 
			
		||||
 | 
			
		||||
	if c.ShallowCopiers == nil {
 | 
			
		||||
		c.ShallowCopiers = ShallowCopiers
 | 
			
		||||
	}
 | 
			
		||||
	w.shallowCopiers = c.ShallowCopiers
 | 
			
		||||
 | 
			
		||||
	err := reflectwalk.Walk(v, w)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get the result. If the result is nil, then we want to turn it
 | 
			
		||||
	// into a typed nil if we can.
 | 
			
		||||
	result := w.Result
 | 
			
		||||
	if result == nil {
 | 
			
		||||
		val := reflect.ValueOf(v)
 | 
			
		||||
		result = reflect.Indirect(reflect.New(val.Type())).Interface()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return the key used to index interfaces types we've seen. Store the number
 | 
			
		||||
// of pointers in the upper 32bits, and the depth in the lower 32bits. This is
 | 
			
		||||
// easy to calculate, easy to match a key with our current depth, and we don't
 | 
			
		||||
// need to deal with initializing and cleaning up nested maps or slices.
 | 
			
		||||
func ifaceKey(pointers, depth int) uint64 {
 | 
			
		||||
	return uint64(pointers)<<32 | uint64(depth)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type walker struct {
 | 
			
		||||
	Result interface{}
 | 
			
		||||
 | 
			
		||||
	copiers        map[reflect.Type]CopierFunc
 | 
			
		||||
	shallowCopiers map[reflect.Type]struct{}
 | 
			
		||||
	depth          int
 | 
			
		||||
	ignoreDepth    int
 | 
			
		||||
	vals           []reflect.Value
 | 
			
		||||
	cs             []reflect.Value
 | 
			
		||||
 | 
			
		||||
	// This stores the number of pointers we've walked over, indexed by depth.
 | 
			
		||||
	ps []int
 | 
			
		||||
 | 
			
		||||
	// If an interface is indirected by a pointer, we need to know the type of
 | 
			
		||||
	// interface to create when creating the new value.  Store the interface
 | 
			
		||||
	// types here, indexed by both the walk depth and the number of pointers
 | 
			
		||||
	// already seen at that depth. Use ifaceKey to calculate the proper uint64
 | 
			
		||||
	// value.
 | 
			
		||||
	ifaceTypes map[uint64]reflect.Type
 | 
			
		||||
 | 
			
		||||
	// any locks we've taken, indexed by depth
 | 
			
		||||
	locks []sync.Locker
 | 
			
		||||
	// take locks while walking the structure
 | 
			
		||||
	useLocks bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Enter(l reflectwalk.Location) error {
 | 
			
		||||
	w.depth++
 | 
			
		||||
 | 
			
		||||
	// ensure we have enough elements to index via w.depth
 | 
			
		||||
	for w.depth >= len(w.locks) {
 | 
			
		||||
		w.locks = append(w.locks, nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for len(w.ps) < w.depth+1 {
 | 
			
		||||
		w.ps = append(w.ps, 0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Exit(l reflectwalk.Location) error {
 | 
			
		||||
	locker := w.locks[w.depth]
 | 
			
		||||
	w.locks[w.depth] = nil
 | 
			
		||||
	if locker != nil {
 | 
			
		||||
		defer locker.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// clear out pointers and interfaces as we exit the stack
 | 
			
		||||
	w.ps[w.depth] = 0
 | 
			
		||||
 | 
			
		||||
	for k := range w.ifaceTypes {
 | 
			
		||||
		mask := uint64(^uint32(0))
 | 
			
		||||
		if k&mask == uint64(w.depth) {
 | 
			
		||||
			delete(w.ifaceTypes, k)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.depth--
 | 
			
		||||
	if w.ignoreDepth > w.depth {
 | 
			
		||||
		w.ignoreDepth = 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch l {
 | 
			
		||||
	case reflectwalk.Array:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case reflectwalk.Map:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case reflectwalk.Slice:
 | 
			
		||||
		w.replacePointerMaybe()
 | 
			
		||||
 | 
			
		||||
		// Pop map off our container
 | 
			
		||||
		w.cs = w.cs[:len(w.cs)-1]
 | 
			
		||||
	case reflectwalk.MapValue:
 | 
			
		||||
		// Pop off the key and value
 | 
			
		||||
		mv := w.valPop()
 | 
			
		||||
		mk := w.valPop()
 | 
			
		||||
		m := w.cs[len(w.cs)-1]
 | 
			
		||||
 | 
			
		||||
		// If mv is the zero value, SetMapIndex deletes the key form the map,
 | 
			
		||||
		// or in this case never adds it. We need to create a properly typed
 | 
			
		||||
		// zero value so that this key can be set.
 | 
			
		||||
		if !mv.IsValid() {
 | 
			
		||||
			mv = reflect.Zero(m.Elem().Type().Elem())
 | 
			
		||||
		}
 | 
			
		||||
		m.Elem().SetMapIndex(mk, mv)
 | 
			
		||||
	case reflectwalk.ArrayElem:
 | 
			
		||||
		// Pop off the value and the index and set it on the array
 | 
			
		||||
		v := w.valPop()
 | 
			
		||||
		i := w.valPop().Interface().(int)
 | 
			
		||||
		if v.IsValid() {
 | 
			
		||||
			a := w.cs[len(w.cs)-1]
 | 
			
		||||
			ae := a.Elem().Index(i) // storing array as pointer on stack - so need Elem() call
 | 
			
		||||
			if ae.CanSet() {
 | 
			
		||||
				ae.Set(v)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case reflectwalk.SliceElem:
 | 
			
		||||
		// Pop off the value and the index and set it on the slice
 | 
			
		||||
		v := w.valPop()
 | 
			
		||||
		i := w.valPop().Interface().(int)
 | 
			
		||||
		if v.IsValid() {
 | 
			
		||||
			s := w.cs[len(w.cs)-1]
 | 
			
		||||
			se := s.Elem().Index(i)
 | 
			
		||||
			if se.CanSet() {
 | 
			
		||||
				se.Set(v)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case reflectwalk.Struct:
 | 
			
		||||
		w.replacePointerMaybe()
 | 
			
		||||
 | 
			
		||||
		// Remove the struct from the container stack
 | 
			
		||||
		w.cs = w.cs[:len(w.cs)-1]
 | 
			
		||||
	case reflectwalk.StructField:
 | 
			
		||||
		// Pop off the value and the field
 | 
			
		||||
		v := w.valPop()
 | 
			
		||||
		f := w.valPop().Interface().(reflect.StructField)
 | 
			
		||||
		if v.IsValid() {
 | 
			
		||||
			s := w.cs[len(w.cs)-1]
 | 
			
		||||
			sf := reflect.Indirect(s).FieldByName(f.Name)
 | 
			
		||||
 | 
			
		||||
			if sf.CanSet() {
 | 
			
		||||
				sf.Set(v)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case reflectwalk.WalkLoc:
 | 
			
		||||
		// Clear out the slices for GC
 | 
			
		||||
		w.cs = nil
 | 
			
		||||
		w.vals = nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Map(m reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	w.lock(m)
 | 
			
		||||
 | 
			
		||||
	// Create the map. If the map itself is nil, then just make a nil map
 | 
			
		||||
	var newMap reflect.Value
 | 
			
		||||
	if m.IsNil() {
 | 
			
		||||
		newMap = reflect.New(m.Type())
 | 
			
		||||
	} else {
 | 
			
		||||
		newMap = wrapPtr(reflect.MakeMap(m.Type()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.cs = append(w.cs, newMap)
 | 
			
		||||
	w.valPush(newMap)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) MapElem(m, k, v reflect.Value) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) PointerEnter(v bool) error {
 | 
			
		||||
	if v {
 | 
			
		||||
		w.ps[w.depth]++
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) PointerExit(v bool) error {
 | 
			
		||||
	if v {
 | 
			
		||||
		w.ps[w.depth]--
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Pointer(v reflect.Value) error {
 | 
			
		||||
	if _, ok := w.shallowCopiers[v.Type()]; ok {
 | 
			
		||||
		// Shallow copy this value. Use the same logic as primitive, then
 | 
			
		||||
		// return skip.
 | 
			
		||||
		if err := w.Primitive(v); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return reflectwalk.SkipEntry
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Interface(v reflect.Value) error {
 | 
			
		||||
	if !v.IsValid() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if w.ifaceTypes == nil {
 | 
			
		||||
		w.ifaceTypes = make(map[uint64]reflect.Type)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)] = v.Type()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Primitive(v reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	w.lock(v)
 | 
			
		||||
 | 
			
		||||
	// IsValid verifies the v is non-zero and CanInterface verifies
 | 
			
		||||
	// that we're allowed to read this value (unexported fields).
 | 
			
		||||
	var newV reflect.Value
 | 
			
		||||
	if v.IsValid() && v.CanInterface() {
 | 
			
		||||
		newV = reflect.New(v.Type())
 | 
			
		||||
		newV.Elem().Set(v)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.valPush(newV)
 | 
			
		||||
	w.replacePointerMaybe()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Slice(s reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	w.lock(s)
 | 
			
		||||
 | 
			
		||||
	var newS reflect.Value
 | 
			
		||||
	if s.IsNil() {
 | 
			
		||||
		newS = reflect.New(s.Type())
 | 
			
		||||
	} else {
 | 
			
		||||
		newS = wrapPtr(reflect.MakeSlice(s.Type(), s.Len(), s.Cap()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.cs = append(w.cs, newS)
 | 
			
		||||
	w.valPush(newS)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) SliceElem(i int, elem reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We don't write the slice here because elem might still be
 | 
			
		||||
	// arbitrarily complex. Just record the index and continue on.
 | 
			
		||||
	w.valPush(reflect.ValueOf(i))
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Array(a reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	w.lock(a)
 | 
			
		||||
 | 
			
		||||
	newA := reflect.New(a.Type())
 | 
			
		||||
 | 
			
		||||
	w.cs = append(w.cs, newA)
 | 
			
		||||
	w.valPush(newA)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) ArrayElem(i int, elem reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We don't write the array here because elem might still be
 | 
			
		||||
	// arbitrarily complex. Just record the index and continue on.
 | 
			
		||||
	w.valPush(reflect.ValueOf(i))
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) Struct(s reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	w.lock(s)
 | 
			
		||||
 | 
			
		||||
	var v reflect.Value
 | 
			
		||||
	if c, ok := w.copiers[s.Type()]; ok {
 | 
			
		||||
		// We have a Copier for this struct, so we use that copier to
 | 
			
		||||
		// get the copy, and we ignore anything deeper than this.
 | 
			
		||||
		w.ignoreDepth = w.depth
 | 
			
		||||
 | 
			
		||||
		dup, err := c(s.Interface())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// We need to put a pointer to the value on the value stack,
 | 
			
		||||
		// so allocate a new pointer and set it.
 | 
			
		||||
		v = reflect.New(s.Type())
 | 
			
		||||
		reflect.Indirect(v).Set(reflect.ValueOf(dup))
 | 
			
		||||
	} else {
 | 
			
		||||
		// No copier, we copy ourselves and allow reflectwalk to guide
 | 
			
		||||
		// us deeper into the structure for copying.
 | 
			
		||||
		v = reflect.New(s.Type())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Push the value onto the value stack for setting the struct field,
 | 
			
		||||
	// and add the struct itself to the containers stack in case we walk
 | 
			
		||||
	// deeper so that its own fields can be modified.
 | 
			
		||||
	w.valPush(v)
 | 
			
		||||
	w.cs = append(w.cs, v)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) StructField(f reflect.StructField, v reflect.Value) error {
 | 
			
		||||
	if w.ignoring() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If PkgPath is non-empty, this is a private (unexported) field.
 | 
			
		||||
	// We do not set this unexported since the Go runtime doesn't allow us.
 | 
			
		||||
	if f.PkgPath != "" {
 | 
			
		||||
		return reflectwalk.SkipEntry
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch f.Tag.Get(tagKey) {
 | 
			
		||||
	case "shallow":
 | 
			
		||||
		// If we're shallow copying then assign the value directly to the
 | 
			
		||||
		// struct and skip the entry.
 | 
			
		||||
		if v.IsValid() {
 | 
			
		||||
			s := w.cs[len(w.cs)-1]
 | 
			
		||||
			sf := reflect.Indirect(s).FieldByName(f.Name)
 | 
			
		||||
			if sf.CanSet() {
 | 
			
		||||
				sf.Set(v)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return reflectwalk.SkipEntry
 | 
			
		||||
 | 
			
		||||
	case "ignore":
 | 
			
		||||
		// Do nothing
 | 
			
		||||
		return reflectwalk.SkipEntry
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Push the field onto the stack, we'll handle it when we exit
 | 
			
		||||
	// the struct field in Exit...
 | 
			
		||||
	w.valPush(reflect.ValueOf(f))
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ignore causes the walker to ignore any more values until we exit this on
 | 
			
		||||
func (w *walker) ignore() {
 | 
			
		||||
	w.ignoreDepth = w.depth
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) ignoring() bool {
 | 
			
		||||
	return w.ignoreDepth > 0 && w.depth >= w.ignoreDepth
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) pointerPeek() bool {
 | 
			
		||||
	return w.ps[w.depth] > 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) valPop() reflect.Value {
 | 
			
		||||
	result := w.vals[len(w.vals)-1]
 | 
			
		||||
	w.vals = w.vals[:len(w.vals)-1]
 | 
			
		||||
 | 
			
		||||
	// If we're out of values, that means we popped everything off. In
 | 
			
		||||
	// this case, we reset the result so the next pushed value becomes
 | 
			
		||||
	// the result.
 | 
			
		||||
	if len(w.vals) == 0 {
 | 
			
		||||
		w.Result = nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) valPush(v reflect.Value) {
 | 
			
		||||
	w.vals = append(w.vals, v)
 | 
			
		||||
 | 
			
		||||
	// If we haven't set the result yet, then this is the result since
 | 
			
		||||
	// it is the first (outermost) value we're seeing.
 | 
			
		||||
	if w.Result == nil && v.IsValid() {
 | 
			
		||||
		w.Result = v.Interface()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) replacePointerMaybe() {
 | 
			
		||||
	// Determine the last pointer value. If it is NOT a pointer, then
 | 
			
		||||
	// we need to push that onto the stack.
 | 
			
		||||
	if !w.pointerPeek() {
 | 
			
		||||
		w.valPush(reflect.Indirect(w.valPop()))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v := w.valPop()
 | 
			
		||||
 | 
			
		||||
	// If the expected type is a pointer to an interface of any depth,
 | 
			
		||||
	// such as *interface{}, **interface{}, etc., then we need to convert
 | 
			
		||||
	// the value "v" from *CONCRETE to *interface{} so types match for
 | 
			
		||||
	// Set.
 | 
			
		||||
	//
 | 
			
		||||
	// Example if v is type *Foo where Foo is a struct, v would become
 | 
			
		||||
	// *interface{} instead. This only happens if we have an interface expectation
 | 
			
		||||
	// at this depth.
 | 
			
		||||
	//
 | 
			
		||||
	// For more info, see GH-16
 | 
			
		||||
	if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)]; ok && iType.Kind() == reflect.Interface {
 | 
			
		||||
		y := reflect.New(iType)           // Create *interface{}
 | 
			
		||||
		y.Elem().Set(reflect.Indirect(v)) // Assign "Foo" to interface{} (dereferenced)
 | 
			
		||||
		v = y                             // v is now typed *interface{} (where *v = Foo)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 1; i < w.ps[w.depth]; i++ {
 | 
			
		||||
		if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok {
 | 
			
		||||
			iface := reflect.New(iType).Elem()
 | 
			
		||||
			iface.Set(v)
 | 
			
		||||
			v = iface
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p := reflect.New(v.Type())
 | 
			
		||||
		p.Elem().Set(v)
 | 
			
		||||
		v = p
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.valPush(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// if this value is a Locker, lock it and add it to the locks slice
 | 
			
		||||
func (w *walker) lock(v reflect.Value) {
 | 
			
		||||
	if !w.useLocks {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !v.IsValid() || !v.CanInterface() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type rlocker interface {
 | 
			
		||||
		RLocker() sync.Locker
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var locker sync.Locker
 | 
			
		||||
 | 
			
		||||
	// We can't call Interface() on a value directly, since that requires
 | 
			
		||||
	// a copy. This is OK, since the pointer to a value which is a sync.Locker
 | 
			
		||||
	// is also a sync.Locker.
 | 
			
		||||
	if v.Kind() == reflect.Ptr {
 | 
			
		||||
		switch l := v.Interface().(type) {
 | 
			
		||||
		case rlocker:
 | 
			
		||||
			// don't lock a mutex directly
 | 
			
		||||
			if _, ok := l.(*sync.RWMutex); !ok {
 | 
			
		||||
				locker = l.RLocker()
 | 
			
		||||
			}
 | 
			
		||||
		case sync.Locker:
 | 
			
		||||
			locker = l
 | 
			
		||||
		}
 | 
			
		||||
	} else if v.CanAddr() {
 | 
			
		||||
		switch l := v.Addr().Interface().(type) {
 | 
			
		||||
		case rlocker:
 | 
			
		||||
			// don't lock a mutex directly
 | 
			
		||||
			if _, ok := l.(*sync.RWMutex); !ok {
 | 
			
		||||
				locker = l.RLocker()
 | 
			
		||||
			}
 | 
			
		||||
		case sync.Locker:
 | 
			
		||||
			locker = l
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// still no callable locker
 | 
			
		||||
	if locker == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// don't lock a mutex directly
 | 
			
		||||
	switch locker.(type) {
 | 
			
		||||
	case *sync.Mutex, *sync.RWMutex:
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	locker.Lock()
 | 
			
		||||
	w.locks[w.depth] = locker
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// wrapPtr is a helper that takes v and always make it *v. copystructure
 | 
			
		||||
// stores things internally as pointers until the last moment before unwrapping
 | 
			
		||||
func wrapPtr(v reflect.Value) reflect.Value {
 | 
			
		||||
	if !v.IsValid() {
 | 
			
		||||
		return v
 | 
			
		||||
	}
 | 
			
		||||
	vPtr := reflect.New(v.Type())
 | 
			
		||||
	vPtr.Elem().Set(v)
 | 
			
		||||
	return vPtr
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/mitchellh/reflectwalk/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/mitchellh/reflectwalk/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
			
		||||
language: go
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/mitchellh/reflectwalk/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/mitchellh/reflectwalk/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,21 +0,0 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2013 Mitchell Hashimoto
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/mitchellh/reflectwalk/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/mitchellh/reflectwalk/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +0,0 @@
 | 
			
		||||
# reflectwalk
 | 
			
		||||
 | 
			
		||||
reflectwalk is a Go library for "walking" a value in Go using reflection,
 | 
			
		||||
in the same way a directory tree can be "walked" on the filesystem. Walking
 | 
			
		||||
a complex structure can allow you to do manipulations on unknown structures
 | 
			
		||||
such as those decoded from JSON.
 | 
			
		||||
							
								
								
									
										19
									
								
								vendor/github.com/mitchellh/reflectwalk/location.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/mitchellh/reflectwalk/location.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,19 +0,0 @@
 | 
			
		||||
package reflectwalk
 | 
			
		||||
 | 
			
		||||
//go:generate stringer -type=Location location.go
 | 
			
		||||
 | 
			
		||||
type Location uint
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	None Location = iota
 | 
			
		||||
	Map
 | 
			
		||||
	MapKey
 | 
			
		||||
	MapValue
 | 
			
		||||
	Slice
 | 
			
		||||
	SliceElem
 | 
			
		||||
	Array
 | 
			
		||||
	ArrayElem
 | 
			
		||||
	Struct
 | 
			
		||||
	StructField
 | 
			
		||||
	WalkLoc
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/github.com/mitchellh/reflectwalk/location_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/mitchellh/reflectwalk/location_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,16 +0,0 @@
 | 
			
		||||
// Code generated by "stringer -type=Location location.go"; DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package reflectwalk
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
const _Location_name = "NoneMapMapKeyMapValueSliceSliceElemArrayArrayElemStructStructFieldWalkLoc"
 | 
			
		||||
 | 
			
		||||
var _Location_index = [...]uint8{0, 4, 7, 13, 21, 26, 35, 40, 49, 55, 66, 73}
 | 
			
		||||
 | 
			
		||||
func (i Location) String() string {
 | 
			
		||||
	if i >= Location(len(_Location_index)-1) {
 | 
			
		||||
		return fmt.Sprintf("Location(%d)", i)
 | 
			
		||||
	}
 | 
			
		||||
	return _Location_name[_Location_index[i]:_Location_index[i+1]]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										420
									
								
								vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										420
									
								
								vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,420 +0,0 @@
 | 
			
		||||
// reflectwalk is a package that allows you to "walk" complex structures
 | 
			
		||||
// similar to how you may "walk" a filesystem: visiting every element one
 | 
			
		||||
// by one and calling callback functions allowing you to handle and manipulate
 | 
			
		||||
// those elements.
 | 
			
		||||
package reflectwalk
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PrimitiveWalker implementations are able to handle primitive values
 | 
			
		||||
// within complex structures. Primitive values are numbers, strings,
 | 
			
		||||
// booleans, funcs, chans.
 | 
			
		||||
//
 | 
			
		||||
// These primitive values are often members of more complex
 | 
			
		||||
// structures (slices, maps, etc.) that are walkable by other interfaces.
 | 
			
		||||
type PrimitiveWalker interface {
 | 
			
		||||
	Primitive(reflect.Value) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InterfaceWalker implementations are able to handle interface values as they
 | 
			
		||||
// are encountered during the walk.
 | 
			
		||||
type InterfaceWalker interface {
 | 
			
		||||
	Interface(reflect.Value) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapWalker implementations are able to handle individual elements
 | 
			
		||||
// found within a map structure.
 | 
			
		||||
type MapWalker interface {
 | 
			
		||||
	Map(m reflect.Value) error
 | 
			
		||||
	MapElem(m, k, v reflect.Value) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SliceWalker implementations are able to handle slice elements found
 | 
			
		||||
// within complex structures.
 | 
			
		||||
type SliceWalker interface {
 | 
			
		||||
	Slice(reflect.Value) error
 | 
			
		||||
	SliceElem(int, reflect.Value) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ArrayWalker implementations are able to handle array elements found
 | 
			
		||||
// within complex structures.
 | 
			
		||||
type ArrayWalker interface {
 | 
			
		||||
	Array(reflect.Value) error
 | 
			
		||||
	ArrayElem(int, reflect.Value) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StructWalker is an interface that has methods that are called for
 | 
			
		||||
// structs when a Walk is done.
 | 
			
		||||
type StructWalker interface {
 | 
			
		||||
	Struct(reflect.Value) error
 | 
			
		||||
	StructField(reflect.StructField, reflect.Value) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnterExitWalker implementations are notified before and after
 | 
			
		||||
// they walk deeper into complex structures (into struct fields,
 | 
			
		||||
// into slice elements, etc.)
 | 
			
		||||
type EnterExitWalker interface {
 | 
			
		||||
	Enter(Location) error
 | 
			
		||||
	Exit(Location) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PointerWalker implementations are notified when the value they're
 | 
			
		||||
// walking is a pointer or not. Pointer is called for _every_ value whether
 | 
			
		||||
// it is a pointer or not.
 | 
			
		||||
type PointerWalker interface {
 | 
			
		||||
	PointerEnter(bool) error
 | 
			
		||||
	PointerExit(bool) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PointerValueWalker implementations are notified with the value of
 | 
			
		||||
// a particular pointer when a pointer is walked. Pointer is called
 | 
			
		||||
// right before PointerEnter.
 | 
			
		||||
type PointerValueWalker interface {
 | 
			
		||||
	Pointer(reflect.Value) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SkipEntry can be returned from walk functions to skip walking
 | 
			
		||||
// the value of this field. This is only valid in the following functions:
 | 
			
		||||
//
 | 
			
		||||
//   - Struct: skips all fields from being walked
 | 
			
		||||
//   - StructField: skips walking the struct value
 | 
			
		||||
//
 | 
			
		||||
var SkipEntry = errors.New("skip this entry")
 | 
			
		||||
 | 
			
		||||
// Walk takes an arbitrary value and an interface and traverses the
 | 
			
		||||
// value, calling callbacks on the interface if they are supported.
 | 
			
		||||
// The interface should implement one or more of the walker interfaces
 | 
			
		||||
// in this package, such as PrimitiveWalker, StructWalker, etc.
 | 
			
		||||
func Walk(data, walker interface{}) (err error) {
 | 
			
		||||
	v := reflect.ValueOf(data)
 | 
			
		||||
	ew, ok := walker.(EnterExitWalker)
 | 
			
		||||
	if ok {
 | 
			
		||||
		err = ew.Enter(WalkLoc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		err = walk(v, walker)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ok && err == nil {
 | 
			
		||||
		err = ew.Exit(WalkLoc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func walk(v reflect.Value, w interface{}) (err error) {
 | 
			
		||||
	// Determine if we're receiving a pointer and if so notify the walker.
 | 
			
		||||
	// The logic here is convoluted but very important (tests will fail if
 | 
			
		||||
	// almost any part is changed). I will try to explain here.
 | 
			
		||||
	//
 | 
			
		||||
	// First, we check if the value is an interface, if so, we really need
 | 
			
		||||
	// to check the interface's VALUE to see whether it is a pointer.
 | 
			
		||||
	//
 | 
			
		||||
	// Check whether the value is then a pointer. If so, then set pointer
 | 
			
		||||
	// to true to notify the user.
 | 
			
		||||
	//
 | 
			
		||||
	// If we still have a pointer or an interface after the indirections, then
 | 
			
		||||
	// we unwrap another level
 | 
			
		||||
	//
 | 
			
		||||
	// At this time, we also set "v" to be the dereferenced value. This is
 | 
			
		||||
	// because once we've unwrapped the pointer we want to use that value.
 | 
			
		||||
	pointer := false
 | 
			
		||||
	pointerV := v
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		if pointerV.Kind() == reflect.Interface {
 | 
			
		||||
			if iw, ok := w.(InterfaceWalker); ok {
 | 
			
		||||
				if err = iw.Interface(pointerV); err != nil {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			pointerV = pointerV.Elem()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if pointerV.Kind() == reflect.Ptr {
 | 
			
		||||
			if pw, ok := w.(PointerValueWalker); ok {
 | 
			
		||||
				if err = pw.Pointer(pointerV); err != nil {
 | 
			
		||||
					if err == SkipEntry {
 | 
			
		||||
						// Skip the rest of this entry but clear the error
 | 
			
		||||
						return nil
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			pointer = true
 | 
			
		||||
			v = reflect.Indirect(pointerV)
 | 
			
		||||
		}
 | 
			
		||||
		if pw, ok := w.(PointerWalker); ok {
 | 
			
		||||
			if err = pw.PointerEnter(pointer); err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			defer func(pointer bool) {
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				err = pw.PointerExit(pointer)
 | 
			
		||||
			}(pointer)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if pointer {
 | 
			
		||||
			pointerV = v
 | 
			
		||||
		}
 | 
			
		||||
		pointer = false
 | 
			
		||||
 | 
			
		||||
		// If we still have a pointer or interface we have to indirect another level.
 | 
			
		||||
		switch pointerV.Kind() {
 | 
			
		||||
		case reflect.Ptr, reflect.Interface:
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We preserve the original value here because if it is an interface
 | 
			
		||||
	// type, we want to pass that directly into the walkPrimitive, so that
 | 
			
		||||
	// we can set it.
 | 
			
		||||
	originalV := v
 | 
			
		||||
	if v.Kind() == reflect.Interface {
 | 
			
		||||
		v = v.Elem()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k := v.Kind()
 | 
			
		||||
	if k >= reflect.Int && k <= reflect.Complex128 {
 | 
			
		||||
		k = reflect.Int
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch k {
 | 
			
		||||
	// Primitives
 | 
			
		||||
	case reflect.Bool, reflect.Chan, reflect.Func, reflect.Int, reflect.String, reflect.Invalid:
 | 
			
		||||
		err = walkPrimitive(originalV, w)
 | 
			
		||||
		return
 | 
			
		||||
	case reflect.Map:
 | 
			
		||||
		err = walkMap(v, w)
 | 
			
		||||
		return
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		err = walkSlice(v, w)
 | 
			
		||||
		return
 | 
			
		||||
	case reflect.Struct:
 | 
			
		||||
		err = walkStruct(v, w)
 | 
			
		||||
		return
 | 
			
		||||
	case reflect.Array:
 | 
			
		||||
		err = walkArray(v, w)
 | 
			
		||||
		return
 | 
			
		||||
	default:
 | 
			
		||||
		panic("unsupported type: " + k.String())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func walkMap(v reflect.Value, w interface{}) error {
 | 
			
		||||
	ew, ewok := w.(EnterExitWalker)
 | 
			
		||||
	if ewok {
 | 
			
		||||
		ew.Enter(Map)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if mw, ok := w.(MapWalker); ok {
 | 
			
		||||
		if err := mw.Map(v); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, k := range v.MapKeys() {
 | 
			
		||||
		kv := v.MapIndex(k)
 | 
			
		||||
 | 
			
		||||
		if mw, ok := w.(MapWalker); ok {
 | 
			
		||||
			if err := mw.MapElem(v, k, kv); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ew, ok := w.(EnterExitWalker)
 | 
			
		||||
		if ok {
 | 
			
		||||
			ew.Enter(MapKey)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := walk(k, w); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ok {
 | 
			
		||||
			ew.Exit(MapKey)
 | 
			
		||||
			ew.Enter(MapValue)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// get the map value again as it may have changed in the MapElem call
 | 
			
		||||
		if err := walk(v.MapIndex(k), w); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ok {
 | 
			
		||||
			ew.Exit(MapValue)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ewok {
 | 
			
		||||
		ew.Exit(Map)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func walkPrimitive(v reflect.Value, w interface{}) error {
 | 
			
		||||
	if pw, ok := w.(PrimitiveWalker); ok {
 | 
			
		||||
		return pw.Primitive(v)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func walkSlice(v reflect.Value, w interface{}) (err error) {
 | 
			
		||||
	ew, ok := w.(EnterExitWalker)
 | 
			
		||||
	if ok {
 | 
			
		||||
		ew.Enter(Slice)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if sw, ok := w.(SliceWalker); ok {
 | 
			
		||||
		if err := sw.Slice(v); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < v.Len(); i++ {
 | 
			
		||||
		elem := v.Index(i)
 | 
			
		||||
 | 
			
		||||
		if sw, ok := w.(SliceWalker); ok {
 | 
			
		||||
			if err := sw.SliceElem(i, elem); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ew, ok := w.(EnterExitWalker)
 | 
			
		||||
		if ok {
 | 
			
		||||
			ew.Enter(SliceElem)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := walk(elem, w); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ok {
 | 
			
		||||
			ew.Exit(SliceElem)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ew, ok = w.(EnterExitWalker)
 | 
			
		||||
	if ok {
 | 
			
		||||
		ew.Exit(Slice)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func walkArray(v reflect.Value, w interface{}) (err error) {
 | 
			
		||||
	ew, ok := w.(EnterExitWalker)
 | 
			
		||||
	if ok {
 | 
			
		||||
		ew.Enter(Array)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if aw, ok := w.(ArrayWalker); ok {
 | 
			
		||||
		if err := aw.Array(v); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < v.Len(); i++ {
 | 
			
		||||
		elem := v.Index(i)
 | 
			
		||||
 | 
			
		||||
		if aw, ok := w.(ArrayWalker); ok {
 | 
			
		||||
			if err := aw.ArrayElem(i, elem); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ew, ok := w.(EnterExitWalker)
 | 
			
		||||
		if ok {
 | 
			
		||||
			ew.Enter(ArrayElem)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := walk(elem, w); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ok {
 | 
			
		||||
			ew.Exit(ArrayElem)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ew, ok = w.(EnterExitWalker)
 | 
			
		||||
	if ok {
 | 
			
		||||
		ew.Exit(Array)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func walkStruct(v reflect.Value, w interface{}) (err error) {
 | 
			
		||||
	ew, ewok := w.(EnterExitWalker)
 | 
			
		||||
	if ewok {
 | 
			
		||||
		ew.Enter(Struct)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	skip := false
 | 
			
		||||
	if sw, ok := w.(StructWalker); ok {
 | 
			
		||||
		err = sw.Struct(v)
 | 
			
		||||
		if err == SkipEntry {
 | 
			
		||||
			skip = true
 | 
			
		||||
			err = nil
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !skip {
 | 
			
		||||
		vt := v.Type()
 | 
			
		||||
		for i := 0; i < vt.NumField(); i++ {
 | 
			
		||||
			sf := vt.Field(i)
 | 
			
		||||
			f := v.FieldByIndex([]int{i})
 | 
			
		||||
 | 
			
		||||
			if sw, ok := w.(StructWalker); ok {
 | 
			
		||||
				err = sw.StructField(sf, f)
 | 
			
		||||
 | 
			
		||||
				// SkipEntry just pretends this field doesn't even exist
 | 
			
		||||
				if err == SkipEntry {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ew, ok := w.(EnterExitWalker)
 | 
			
		||||
			if ok {
 | 
			
		||||
				ew.Enter(StructField)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = walk(f, w)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if ok {
 | 
			
		||||
				ew.Exit(StructField)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ewok {
 | 
			
		||||
		ew.Exit(Struct)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user