...

Source file src/github.com/mitchellh/copystructure/copystructure.go

Documentation: github.com/mitchellh/copystructure

     1  package copystructure
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"sync"
     7  
     8  	"github.com/mitchellh/reflectwalk"
     9  )
    10  
    11  const tagKey = "copy"
    12  
    13  // Copy returns a deep copy of v.
    14  //
    15  // Copy is unable to copy unexported fields in a struct (lowercase field names).
    16  // Unexported fields can't be reflected by the Go runtime and therefore
    17  // copystructure can't perform any data copies.
    18  //
    19  // For structs, copy behavior can be controlled with struct tags. For example:
    20  //
    21  //   struct {
    22  //     Name string
    23  //     Data *bytes.Buffer `copy:"shallow"`
    24  //   }
    25  //
    26  // The available tag values are:
    27  //
    28  // * "ignore" - The field will be ignored, effectively resulting in it being
    29  //   assigned the zero value in the copy.
    30  //
    31  // * "shallow" - The field will be be shallow copied. This means that references
    32  //   values such as pointers, maps, slices, etc. will be directly assigned
    33  //   versus deep copied.
    34  //
    35  func Copy(v interface{}) (interface{}, error) {
    36  	return Config{}.Copy(v)
    37  }
    38  
    39  // CopierFunc is a function that knows how to deep copy a specific type.
    40  // Register these globally with the Copiers variable.
    41  type CopierFunc func(interface{}) (interface{}, error)
    42  
    43  // Copiers is a map of types that behave specially when they are copied.
    44  // If a type is found in this map while deep copying, this function
    45  // will be called to copy it instead of attempting to copy all fields.
    46  //
    47  // The key should be the type, obtained using: reflect.TypeOf(value with type).
    48  //
    49  // It is unsafe to write to this map after Copies have started. If you
    50  // are writing to this map while also copying, wrap all modifications to
    51  // this map as well as to Copy in a mutex.
    52  var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc)
    53  
    54  // ShallowCopiers is a map of pointer types that behave specially
    55  // when they are copied.  If a type is found in this map while deep
    56  // copying, the pointer value will be shallow copied and not walked
    57  // into.
    58  //
    59  // The key should be the type, obtained using: reflect.TypeOf(value
    60  // with type).
    61  //
    62  // It is unsafe to write to this map after Copies have started. If you
    63  // are writing to this map while also copying, wrap all modifications to
    64  // this map as well as to Copy in a mutex.
    65  var ShallowCopiers map[reflect.Type]struct{} = make(map[reflect.Type]struct{})
    66  
    67  // Must is a helper that wraps a call to a function returning
    68  // (interface{}, error) and panics if the error is non-nil. It is intended
    69  // for use in variable initializations and should only be used when a copy
    70  // error should be a crashing case.
    71  func Must(v interface{}, err error) interface{} {
    72  	if err != nil {
    73  		panic("copy error: " + err.Error())
    74  	}
    75  
    76  	return v
    77  }
    78  
    79  var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true")
    80  
    81  type Config struct {
    82  	// Lock any types that are a sync.Locker and are not a mutex while copying.
    83  	// If there is an RLocker method, use that to get the sync.Locker.
    84  	Lock bool
    85  
    86  	// Copiers is a map of types associated with a CopierFunc. Use the global
    87  	// Copiers map if this is nil.
    88  	Copiers map[reflect.Type]CopierFunc
    89  
    90  	// ShallowCopiers is a map of pointer types that when they are
    91  	// shallow copied no matter where they are encountered. Use the
    92  	// global ShallowCopiers if this is nil.
    93  	ShallowCopiers map[reflect.Type]struct{}
    94  }
    95  
    96  func (c Config) Copy(v interface{}) (interface{}, error) {
    97  	if c.Lock && reflect.ValueOf(v).Kind() != reflect.Ptr {
    98  		return nil, errPointerRequired
    99  	}
   100  
   101  	w := new(walker)
   102  	if c.Lock {
   103  		w.useLocks = true
   104  	}
   105  
   106  	if c.Copiers == nil {
   107  		c.Copiers = Copiers
   108  	}
   109  	w.copiers = c.Copiers
   110  
   111  	if c.ShallowCopiers == nil {
   112  		c.ShallowCopiers = ShallowCopiers
   113  	}
   114  	w.shallowCopiers = c.ShallowCopiers
   115  
   116  	err := reflectwalk.Walk(v, w)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  
   121  	// Get the result. If the result is nil, then we want to turn it
   122  	// into a typed nil if we can.
   123  	result := w.Result
   124  	if result == nil {
   125  		val := reflect.ValueOf(v)
   126  		result = reflect.Indirect(reflect.New(val.Type())).Interface()
   127  	}
   128  
   129  	return result, nil
   130  }
   131  
   132  // Return the key used to index interfaces types we've seen. Store the number
   133  // of pointers in the upper 32bits, and the depth in the lower 32bits. This is
   134  // easy to calculate, easy to match a key with our current depth, and we don't
   135  // need to deal with initializing and cleaning up nested maps or slices.
   136  func ifaceKey(pointers, depth int) uint64 {
   137  	return uint64(pointers)<<32 | uint64(depth)
   138  }
   139  
   140  type walker struct {
   141  	Result interface{}
   142  
   143  	copiers        map[reflect.Type]CopierFunc
   144  	shallowCopiers map[reflect.Type]struct{}
   145  	depth          int
   146  	ignoreDepth    int
   147  	vals           []reflect.Value
   148  	cs             []reflect.Value
   149  
   150  	// This stores the number of pointers we've walked over, indexed by depth.
   151  	ps []int
   152  
   153  	// If an interface is indirected by a pointer, we need to know the type of
   154  	// interface to create when creating the new value.  Store the interface
   155  	// types here, indexed by both the walk depth and the number of pointers
   156  	// already seen at that depth. Use ifaceKey to calculate the proper uint64
   157  	// value.
   158  	ifaceTypes map[uint64]reflect.Type
   159  
   160  	// any locks we've taken, indexed by depth
   161  	locks []sync.Locker
   162  	// take locks while walking the structure
   163  	useLocks bool
   164  }
   165  
   166  func (w *walker) Enter(l reflectwalk.Location) error {
   167  	w.depth++
   168  
   169  	// ensure we have enough elements to index via w.depth
   170  	for w.depth >= len(w.locks) {
   171  		w.locks = append(w.locks, nil)
   172  	}
   173  
   174  	for len(w.ps) < w.depth+1 {
   175  		w.ps = append(w.ps, 0)
   176  	}
   177  
   178  	return nil
   179  }
   180  
   181  func (w *walker) Exit(l reflectwalk.Location) error {
   182  	locker := w.locks[w.depth]
   183  	w.locks[w.depth] = nil
   184  	if locker != nil {
   185  		defer locker.Unlock()
   186  	}
   187  
   188  	// clear out pointers and interfaces as we exit the stack
   189  	w.ps[w.depth] = 0
   190  
   191  	for k := range w.ifaceTypes {
   192  		mask := uint64(^uint32(0))
   193  		if k&mask == uint64(w.depth) {
   194  			delete(w.ifaceTypes, k)
   195  		}
   196  	}
   197  
   198  	w.depth--
   199  	if w.ignoreDepth > w.depth {
   200  		w.ignoreDepth = 0
   201  	}
   202  
   203  	if w.ignoring() {
   204  		return nil
   205  	}
   206  
   207  	switch l {
   208  	case reflectwalk.Array:
   209  		fallthrough
   210  	case reflectwalk.Map:
   211  		fallthrough
   212  	case reflectwalk.Slice:
   213  		w.replacePointerMaybe()
   214  
   215  		// Pop map off our container
   216  		w.cs = w.cs[:len(w.cs)-1]
   217  	case reflectwalk.MapValue:
   218  		// Pop off the key and value
   219  		mv := w.valPop()
   220  		mk := w.valPop()
   221  		m := w.cs[len(w.cs)-1]
   222  
   223  		// If mv is the zero value, SetMapIndex deletes the key form the map,
   224  		// or in this case never adds it. We need to create a properly typed
   225  		// zero value so that this key can be set.
   226  		if !mv.IsValid() {
   227  			mv = reflect.Zero(m.Elem().Type().Elem())
   228  		}
   229  		m.Elem().SetMapIndex(mk, mv)
   230  	case reflectwalk.ArrayElem:
   231  		// Pop off the value and the index and set it on the array
   232  		v := w.valPop()
   233  		i := w.valPop().Interface().(int)
   234  		if v.IsValid() {
   235  			a := w.cs[len(w.cs)-1]
   236  			ae := a.Elem().Index(i) // storing array as pointer on stack - so need Elem() call
   237  			if ae.CanSet() {
   238  				ae.Set(v)
   239  			}
   240  		}
   241  	case reflectwalk.SliceElem:
   242  		// Pop off the value and the index and set it on the slice
   243  		v := w.valPop()
   244  		i := w.valPop().Interface().(int)
   245  		if v.IsValid() {
   246  			s := w.cs[len(w.cs)-1]
   247  			se := s.Elem().Index(i)
   248  			if se.CanSet() {
   249  				se.Set(v)
   250  			}
   251  		}
   252  	case reflectwalk.Struct:
   253  		w.replacePointerMaybe()
   254  
   255  		// Remove the struct from the container stack
   256  		w.cs = w.cs[:len(w.cs)-1]
   257  	case reflectwalk.StructField:
   258  		// Pop off the value and the field
   259  		v := w.valPop()
   260  		f := w.valPop().Interface().(reflect.StructField)
   261  		if v.IsValid() {
   262  			s := w.cs[len(w.cs)-1]
   263  			sf := reflect.Indirect(s).FieldByName(f.Name)
   264  
   265  			if sf.CanSet() {
   266  				sf.Set(v)
   267  			}
   268  		}
   269  	case reflectwalk.WalkLoc:
   270  		// Clear out the slices for GC
   271  		w.cs = nil
   272  		w.vals = nil
   273  	}
   274  
   275  	return nil
   276  }
   277  
   278  func (w *walker) Map(m reflect.Value) error {
   279  	if w.ignoring() {
   280  		return nil
   281  	}
   282  	w.lock(m)
   283  
   284  	// Create the map. If the map itself is nil, then just make a nil map
   285  	var newMap reflect.Value
   286  	if m.IsNil() {
   287  		newMap = reflect.New(m.Type())
   288  	} else {
   289  		newMap = wrapPtr(reflect.MakeMap(m.Type()))
   290  	}
   291  
   292  	w.cs = append(w.cs, newMap)
   293  	w.valPush(newMap)
   294  	return nil
   295  }
   296  
   297  func (w *walker) MapElem(m, k, v reflect.Value) error {
   298  	return nil
   299  }
   300  
   301  func (w *walker) PointerEnter(v bool) error {
   302  	if v {
   303  		w.ps[w.depth]++
   304  	}
   305  	return nil
   306  }
   307  
   308  func (w *walker) PointerExit(v bool) error {
   309  	if v {
   310  		w.ps[w.depth]--
   311  	}
   312  	return nil
   313  }
   314  
   315  func (w *walker) Pointer(v reflect.Value) error {
   316  	if _, ok := w.shallowCopiers[v.Type()]; ok {
   317  		// Shallow copy this value. Use the same logic as primitive, then
   318  		// return skip.
   319  		if err := w.Primitive(v); err != nil {
   320  			return err
   321  		}
   322  
   323  		return reflectwalk.SkipEntry
   324  	}
   325  
   326  	return nil
   327  }
   328  
   329  func (w *walker) Interface(v reflect.Value) error {
   330  	if !v.IsValid() {
   331  		return nil
   332  	}
   333  	if w.ifaceTypes == nil {
   334  		w.ifaceTypes = make(map[uint64]reflect.Type)
   335  	}
   336  
   337  	w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)] = v.Type()
   338  	return nil
   339  }
   340  
   341  func (w *walker) Primitive(v reflect.Value) error {
   342  	if w.ignoring() {
   343  		return nil
   344  	}
   345  	w.lock(v)
   346  
   347  	// IsValid verifies the v is non-zero and CanInterface verifies
   348  	// that we're allowed to read this value (unexported fields).
   349  	var newV reflect.Value
   350  	if v.IsValid() && v.CanInterface() {
   351  		newV = reflect.New(v.Type())
   352  		newV.Elem().Set(v)
   353  	}
   354  
   355  	w.valPush(newV)
   356  	w.replacePointerMaybe()
   357  	return nil
   358  }
   359  
   360  func (w *walker) Slice(s reflect.Value) error {
   361  	if w.ignoring() {
   362  		return nil
   363  	}
   364  	w.lock(s)
   365  
   366  	var newS reflect.Value
   367  	if s.IsNil() {
   368  		newS = reflect.New(s.Type())
   369  	} else {
   370  		newS = wrapPtr(reflect.MakeSlice(s.Type(), s.Len(), s.Cap()))
   371  	}
   372  
   373  	w.cs = append(w.cs, newS)
   374  	w.valPush(newS)
   375  	return nil
   376  }
   377  
   378  func (w *walker) SliceElem(i int, elem reflect.Value) error {
   379  	if w.ignoring() {
   380  		return nil
   381  	}
   382  
   383  	// We don't write the slice here because elem might still be
   384  	// arbitrarily complex. Just record the index and continue on.
   385  	w.valPush(reflect.ValueOf(i))
   386  
   387  	return nil
   388  }
   389  
   390  func (w *walker) Array(a reflect.Value) error {
   391  	if w.ignoring() {
   392  		return nil
   393  	}
   394  	w.lock(a)
   395  
   396  	newA := reflect.New(a.Type())
   397  
   398  	w.cs = append(w.cs, newA)
   399  	w.valPush(newA)
   400  	return nil
   401  }
   402  
   403  func (w *walker) ArrayElem(i int, elem reflect.Value) error {
   404  	if w.ignoring() {
   405  		return nil
   406  	}
   407  
   408  	// We don't write the array here because elem might still be
   409  	// arbitrarily complex. Just record the index and continue on.
   410  	w.valPush(reflect.ValueOf(i))
   411  
   412  	return nil
   413  }
   414  
   415  func (w *walker) Struct(s reflect.Value) error {
   416  	if w.ignoring() {
   417  		return nil
   418  	}
   419  	w.lock(s)
   420  
   421  	var v reflect.Value
   422  	if c, ok := w.copiers[s.Type()]; ok {
   423  		// We have a Copier for this struct, so we use that copier to
   424  		// get the copy, and we ignore anything deeper than this.
   425  		w.ignoreDepth = w.depth
   426  
   427  		dup, err := c(s.Interface())
   428  		if err != nil {
   429  			return err
   430  		}
   431  
   432  		// We need to put a pointer to the value on the value stack,
   433  		// so allocate a new pointer and set it.
   434  		v = reflect.New(s.Type())
   435  		reflect.Indirect(v).Set(reflect.ValueOf(dup))
   436  	} else {
   437  		// No copier, we copy ourselves and allow reflectwalk to guide
   438  		// us deeper into the structure for copying.
   439  		v = reflect.New(s.Type())
   440  	}
   441  
   442  	// Push the value onto the value stack for setting the struct field,
   443  	// and add the struct itself to the containers stack in case we walk
   444  	// deeper so that its own fields can be modified.
   445  	w.valPush(v)
   446  	w.cs = append(w.cs, v)
   447  
   448  	return nil
   449  }
   450  
   451  func (w *walker) StructField(f reflect.StructField, v reflect.Value) error {
   452  	if w.ignoring() {
   453  		return nil
   454  	}
   455  
   456  	// If PkgPath is non-empty, this is a private (unexported) field.
   457  	// We do not set this unexported since the Go runtime doesn't allow us.
   458  	if f.PkgPath != "" {
   459  		return reflectwalk.SkipEntry
   460  	}
   461  
   462  	switch f.Tag.Get(tagKey) {
   463  	case "shallow":
   464  		// If we're shallow copying then assign the value directly to the
   465  		// struct and skip the entry.
   466  		if v.IsValid() {
   467  			s := w.cs[len(w.cs)-1]
   468  			sf := reflect.Indirect(s).FieldByName(f.Name)
   469  			if sf.CanSet() {
   470  				sf.Set(v)
   471  			}
   472  		}
   473  
   474  		return reflectwalk.SkipEntry
   475  
   476  	case "ignore":
   477  		// Do nothing
   478  		return reflectwalk.SkipEntry
   479  	}
   480  
   481  	// Push the field onto the stack, we'll handle it when we exit
   482  	// the struct field in Exit...
   483  	w.valPush(reflect.ValueOf(f))
   484  
   485  	return nil
   486  }
   487  
   488  // ignore causes the walker to ignore any more values until we exit this on
   489  func (w *walker) ignore() {
   490  	w.ignoreDepth = w.depth
   491  }
   492  
   493  func (w *walker) ignoring() bool {
   494  	return w.ignoreDepth > 0 && w.depth >= w.ignoreDepth
   495  }
   496  
   497  func (w *walker) pointerPeek() bool {
   498  	return w.ps[w.depth] > 0
   499  }
   500  
   501  func (w *walker) valPop() reflect.Value {
   502  	result := w.vals[len(w.vals)-1]
   503  	w.vals = w.vals[:len(w.vals)-1]
   504  
   505  	// If we're out of values, that means we popped everything off. In
   506  	// this case, we reset the result so the next pushed value becomes
   507  	// the result.
   508  	if len(w.vals) == 0 {
   509  		w.Result = nil
   510  	}
   511  
   512  	return result
   513  }
   514  
   515  func (w *walker) valPush(v reflect.Value) {
   516  	w.vals = append(w.vals, v)
   517  
   518  	// If we haven't set the result yet, then this is the result since
   519  	// it is the first (outermost) value we're seeing.
   520  	if w.Result == nil && v.IsValid() {
   521  		w.Result = v.Interface()
   522  	}
   523  }
   524  
   525  func (w *walker) replacePointerMaybe() {
   526  	// Determine the last pointer value. If it is NOT a pointer, then
   527  	// we need to push that onto the stack.
   528  	if !w.pointerPeek() {
   529  		w.valPush(reflect.Indirect(w.valPop()))
   530  		return
   531  	}
   532  
   533  	v := w.valPop()
   534  
   535  	// If the expected type is a pointer to an interface of any depth,
   536  	// such as *interface{}, **interface{}, etc., then we need to convert
   537  	// the value "v" from *CONCRETE to *interface{} so types match for
   538  	// Set.
   539  	//
   540  	// Example if v is type *Foo where Foo is a struct, v would become
   541  	// *interface{} instead. This only happens if we have an interface expectation
   542  	// at this depth.
   543  	//
   544  	// For more info, see GH-16
   545  	if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)]; ok && iType.Kind() == reflect.Interface {
   546  		y := reflect.New(iType)           // Create *interface{}
   547  		y.Elem().Set(reflect.Indirect(v)) // Assign "Foo" to interface{} (dereferenced)
   548  		v = y                             // v is now typed *interface{} (where *v = Foo)
   549  	}
   550  
   551  	for i := 1; i < w.ps[w.depth]; i++ {
   552  		if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok {
   553  			iface := reflect.New(iType).Elem()
   554  			iface.Set(v)
   555  			v = iface
   556  		}
   557  
   558  		p := reflect.New(v.Type())
   559  		p.Elem().Set(v)
   560  		v = p
   561  	}
   562  
   563  	w.valPush(v)
   564  }
   565  
   566  // if this value is a Locker, lock it and add it to the locks slice
   567  func (w *walker) lock(v reflect.Value) {
   568  	if !w.useLocks {
   569  		return
   570  	}
   571  
   572  	if !v.IsValid() || !v.CanInterface() {
   573  		return
   574  	}
   575  
   576  	type rlocker interface {
   577  		RLocker() sync.Locker
   578  	}
   579  
   580  	var locker sync.Locker
   581  
   582  	// We can't call Interface() on a value directly, since that requires
   583  	// a copy. This is OK, since the pointer to a value which is a sync.Locker
   584  	// is also a sync.Locker.
   585  	if v.Kind() == reflect.Ptr {
   586  		switch l := v.Interface().(type) {
   587  		case rlocker:
   588  			// don't lock a mutex directly
   589  			if _, ok := l.(*sync.RWMutex); !ok {
   590  				locker = l.RLocker()
   591  			}
   592  		case sync.Locker:
   593  			locker = l
   594  		}
   595  	} else if v.CanAddr() {
   596  		switch l := v.Addr().Interface().(type) {
   597  		case rlocker:
   598  			// don't lock a mutex directly
   599  			if _, ok := l.(*sync.RWMutex); !ok {
   600  				locker = l.RLocker()
   601  			}
   602  		case sync.Locker:
   603  			locker = l
   604  		}
   605  	}
   606  
   607  	// still no callable locker
   608  	if locker == nil {
   609  		return
   610  	}
   611  
   612  	// don't lock a mutex directly
   613  	switch locker.(type) {
   614  	case *sync.Mutex, *sync.RWMutex:
   615  		return
   616  	}
   617  
   618  	locker.Lock()
   619  	w.locks[w.depth] = locker
   620  }
   621  
   622  // wrapPtr is a helper that takes v and always make it *v. copystructure
   623  // stores things internally as pointers until the last moment before unwrapping
   624  func wrapPtr(v reflect.Value) reflect.Value {
   625  	if !v.IsValid() {
   626  		return v
   627  	}
   628  	vPtr := reflect.New(v.Type())
   629  	vPtr.Elem().Set(v)
   630  	return vPtr
   631  }
   632  

View as plain text