github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/third_party/forked/golang/reflect/deep_equal.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package reflect is a fork of go's standard library reflection package, which
     6  // allows for deep equal with equality functions defined.
     7  package reflect
     8  
     9  import (
    10  	"fmt"
    11  	"reflect"
    12  	"strings"
    13  )
    14  
    15  // Equalities is a map from type to a function comparing two values of
    16  // that type.
    17  type Equalities map[reflect.Type]reflect.Value
    18  
    19  // For convenience, panics on errors
    20  func EqualitiesOrDie(funcs ...interface{}) Equalities {
    21  	e := Equalities{}
    22  	if err := e.AddFuncs(funcs...); err != nil {
    23  		panic(err)
    24  	}
    25  	return e
    26  }
    27  
    28  // AddFuncs is a shortcut for multiple calls to AddFunc.
    29  func (e Equalities) AddFuncs(funcs ...interface{}) error {
    30  	for _, f := range funcs {
    31  		if err := e.AddFunc(f); err != nil {
    32  			return err
    33  		}
    34  	}
    35  	return nil
    36  }
    37  
    38  // AddFunc uses func as an equality function: it must take
    39  // two parameters of the same type, and return a boolean.
    40  func (e Equalities) AddFunc(eqFunc interface{}) error {
    41  	fv := reflect.ValueOf(eqFunc)
    42  	ft := fv.Type()
    43  	if ft.Kind() != reflect.Func {
    44  		return fmt.Errorf("expected func, got: %v", ft)
    45  	}
    46  	if ft.NumIn() != 2 {
    47  		return fmt.Errorf("expected two 'in' params, got: %v", ft)
    48  	}
    49  	if ft.NumOut() != 1 {
    50  		return fmt.Errorf("expected one 'out' param, got: %v", ft)
    51  	}
    52  	if ft.In(0) != ft.In(1) {
    53  		return fmt.Errorf("expected arg 1 and 2 to have same type, but got %v", ft)
    54  	}
    55  	var forReturnType bool
    56  	boolType := reflect.TypeOf(forReturnType)
    57  	if ft.Out(0) != boolType {
    58  		return fmt.Errorf("expected bool return, got: %v", ft)
    59  	}
    60  	e[ft.In(0)] = fv
    61  	return nil
    62  }
    63  
    64  // Below here is forked from go's reflect/deepequal.go
    65  
    66  // During deepValueEqual, must keep track of checks that are
    67  // in progress.  The comparison algorithm assumes that all
    68  // checks in progress are true when it reencounters them.
    69  // Visited comparisons are stored in a map indexed by visit.
    70  type visit struct {
    71  	a1  uintptr
    72  	a2  uintptr
    73  	typ reflect.Type
    74  }
    75  
    76  // unexportedTypePanic is thrown when you use this DeepEqual on something that has an
    77  // unexported type. It indicates a programmer error, so should not occur at runtime,
    78  // which is why it's not public and thus impossible to catch.
    79  type unexportedTypePanic []reflect.Type
    80  
    81  func (u unexportedTypePanic) Error() string { return u.String() }
    82  func (u unexportedTypePanic) String() string {
    83  	strs := make([]string, len(u))
    84  	for i, t := range u {
    85  		strs[i] = fmt.Sprintf("%v", t)
    86  	}
    87  	return "an unexported field was encountered, nested like this: " + strings.Join(strs, " -> ")
    88  }
    89  
    90  func makeUsefulPanic(v reflect.Value) {
    91  	if x := recover(); x != nil {
    92  		if u, ok := x.(unexportedTypePanic); ok {
    93  			u = append(unexportedTypePanic{v.Type()}, u...)
    94  			x = u
    95  		}
    96  		panic(x)
    97  	}
    98  }
    99  
   100  // Tests for deep equality using reflected types. The map argument tracks
   101  // comparisons that have already been seen, which allows short circuiting on
   102  // recursive types.
   103  // equateNilAndEmpty controls whether empty maps/slices are equivalent to nil
   104  func (e Equalities) deepValueEqual(v1, v2 reflect.Value, visited map[visit]bool, equateNilAndEmpty bool, depth int) bool {
   105  	defer makeUsefulPanic(v1)
   106  
   107  	if !v1.IsValid() || !v2.IsValid() {
   108  		return v1.IsValid() == v2.IsValid()
   109  	}
   110  	if v1.Type() != v2.Type() {
   111  		return false
   112  	}
   113  	if fv, ok := e[v1.Type()]; ok {
   114  		return fv.Call([]reflect.Value{v1, v2})[0].Bool()
   115  	}
   116  
   117  	hard := func(k reflect.Kind) bool {
   118  		switch k {
   119  		case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct:
   120  			return true
   121  		}
   122  		return false
   123  	}
   124  
   125  	if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
   126  		addr1 := v1.UnsafeAddr()
   127  		addr2 := v2.UnsafeAddr()
   128  		if addr1 > addr2 {
   129  			// Canonicalize order to reduce number of entries in visited.
   130  			addr1, addr2 = addr2, addr1
   131  		}
   132  
   133  		// Short circuit if references are identical ...
   134  		if addr1 == addr2 {
   135  			return true
   136  		}
   137  
   138  		// ... or already seen
   139  		typ := v1.Type()
   140  		v := visit{addr1, addr2, typ}
   141  		if visited[v] {
   142  			return true
   143  		}
   144  
   145  		// Remember for later.
   146  		visited[v] = true
   147  	}
   148  
   149  	switch v1.Kind() {
   150  	case reflect.Array:
   151  		// We don't need to check length here because length is part of
   152  		// an array's type, which has already been filtered for.
   153  		for i := 0; i < v1.Len(); i++ {
   154  			if !e.deepValueEqual(v1.Index(i), v2.Index(i), visited, equateNilAndEmpty, depth+1) {
   155  				return false
   156  			}
   157  		}
   158  		return true
   159  	case reflect.Slice:
   160  		if equateNilAndEmpty {
   161  			if (v1.IsNil() || v1.Len() == 0) != (v2.IsNil() || v2.Len() == 0) {
   162  				return false
   163  			}
   164  
   165  			if v1.IsNil() || v1.Len() == 0 {
   166  				return true
   167  			}
   168  		} else {
   169  			if v1.IsNil() != v2.IsNil() {
   170  				return false
   171  			}
   172  
   173  			// Optimize nil and empty cases
   174  			// Two lists that are BOTH nil are equal
   175  			// No need to check v2 is nil since v1.IsNil == v2.IsNil from above
   176  			if v1.IsNil() {
   177  				return true
   178  			}
   179  
   180  			// Two lists that are both empty and both non nil are equal
   181  			if v1.Len() == 0 || v2.Len() == 0 {
   182  				return true
   183  			}
   184  		}
   185  		if v1.Len() != v2.Len() {
   186  			return false
   187  		}
   188  		if v1.Pointer() == v2.Pointer() {
   189  			return true
   190  		}
   191  		for i := 0; i < v1.Len(); i++ {
   192  			if !e.deepValueEqual(v1.Index(i), v2.Index(i), visited, equateNilAndEmpty, depth+1) {
   193  				return false
   194  			}
   195  		}
   196  		return true
   197  	case reflect.Interface:
   198  		if v1.IsNil() || v2.IsNil() {
   199  			return v1.IsNil() == v2.IsNil()
   200  		}
   201  		return e.deepValueEqual(v1.Elem(), v2.Elem(), visited, equateNilAndEmpty, depth+1)
   202  	case reflect.Ptr:
   203  		return e.deepValueEqual(v1.Elem(), v2.Elem(), visited, equateNilAndEmpty, depth+1)
   204  	case reflect.Struct:
   205  		for i, n := 0, v1.NumField(); i < n; i++ {
   206  			if !e.deepValueEqual(v1.Field(i), v2.Field(i), visited, equateNilAndEmpty, depth+1) {
   207  				return false
   208  			}
   209  		}
   210  		return true
   211  	case reflect.Map:
   212  		if equateNilAndEmpty {
   213  			if (v1.IsNil() || v1.Len() == 0) != (v2.IsNil() || v2.Len() == 0) {
   214  				return false
   215  			}
   216  			if v1.IsNil() || v1.Len() == 0 {
   217  				return true
   218  			}
   219  		} else {
   220  			if v1.IsNil() != v2.IsNil() {
   221  				return false
   222  			}
   223  
   224  			// Optimize nil and empty cases
   225  			// Two maps that are BOTH nil are equal
   226  			// No need to check v2 is nil since v1.IsNil == v2.IsNil from above
   227  			if v1.IsNil() {
   228  				return true
   229  			}
   230  
   231  			// Two maps that are both empty and both non nil are equal
   232  			if v1.Len() == 0 || v2.Len() == 0 {
   233  				return true
   234  			}
   235  		}
   236  		if v1.Len() != v2.Len() {
   237  			return false
   238  		}
   239  		if v1.Pointer() == v2.Pointer() {
   240  			return true
   241  		}
   242  		for _, k := range v1.MapKeys() {
   243  			if !e.deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, equateNilAndEmpty, depth+1) {
   244  				return false
   245  			}
   246  		}
   247  		return true
   248  	case reflect.Func:
   249  		if v1.IsNil() && v2.IsNil() {
   250  			return true
   251  		}
   252  		// Can't do better than this:
   253  		return false
   254  	default:
   255  		// Normal equality suffices
   256  		if !v1.CanInterface() || !v2.CanInterface() {
   257  			panic(unexportedTypePanic{})
   258  		}
   259  		return v1.Interface() == v2.Interface()
   260  	}
   261  }
   262  
   263  // DeepEqual is like reflect.DeepEqual, but focused on semantic equality
   264  // instead of memory equality.
   265  //
   266  // It will use e's equality functions if it finds types that match.
   267  //
   268  // An empty slice *is* equal to a nil slice for our purposes; same for maps.
   269  //
   270  // Unexported field members cannot be compared and will cause an informative panic; you must add an Equality
   271  // function for these types.
   272  func (e Equalities) DeepEqual(a1, a2 interface{}) bool {
   273  	return e.deepEqual(a1, a2, true)
   274  }
   275  
   276  func (e Equalities) DeepEqualWithNilDifferentFromEmpty(a1, a2 interface{}) bool {
   277  	return e.deepEqual(a1, a2, false)
   278  }
   279  
   280  func (e Equalities) deepEqual(a1, a2 interface{}, equateNilAndEmpty bool) bool {
   281  	if a1 == nil || a2 == nil {
   282  		return a1 == a2
   283  	}
   284  	v1 := reflect.ValueOf(a1)
   285  	v2 := reflect.ValueOf(a2)
   286  	if v1.Type() != v2.Type() {
   287  		return false
   288  	}
   289  	return e.deepValueEqual(v1, v2, make(map[visit]bool), equateNilAndEmpty, 0)
   290  }
   291  
   292  func (e Equalities) deepValueDerive(v1, v2 reflect.Value, visited map[visit]bool, depth int) bool {
   293  	defer makeUsefulPanic(v1)
   294  
   295  	if !v1.IsValid() || !v2.IsValid() {
   296  		return v1.IsValid() == v2.IsValid()
   297  	}
   298  	if v1.Type() != v2.Type() {
   299  		return false
   300  	}
   301  	if fv, ok := e[v1.Type()]; ok {
   302  		return fv.Call([]reflect.Value{v1, v2})[0].Bool()
   303  	}
   304  
   305  	hard := func(k reflect.Kind) bool {
   306  		switch k {
   307  		case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct:
   308  			return true
   309  		}
   310  		return false
   311  	}
   312  
   313  	if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
   314  		addr1 := v1.UnsafeAddr()
   315  		addr2 := v2.UnsafeAddr()
   316  		if addr1 > addr2 {
   317  			// Canonicalize order to reduce number of entries in visited.
   318  			addr1, addr2 = addr2, addr1
   319  		}
   320  
   321  		// Short circuit if references are identical ...
   322  		if addr1 == addr2 {
   323  			return true
   324  		}
   325  
   326  		// ... or already seen
   327  		typ := v1.Type()
   328  		v := visit{addr1, addr2, typ}
   329  		if visited[v] {
   330  			return true
   331  		}
   332  
   333  		// Remember for later.
   334  		visited[v] = true
   335  	}
   336  
   337  	switch v1.Kind() {
   338  	case reflect.Array:
   339  		// We don't need to check length here because length is part of
   340  		// an array's type, which has already been filtered for.
   341  		for i := 0; i < v1.Len(); i++ {
   342  			if !e.deepValueDerive(v1.Index(i), v2.Index(i), visited, depth+1) {
   343  				return false
   344  			}
   345  		}
   346  		return true
   347  	case reflect.Slice:
   348  		if v1.IsNil() || v1.Len() == 0 {
   349  			return true
   350  		}
   351  		if v1.Len() > v2.Len() {
   352  			return false
   353  		}
   354  		if v1.Pointer() == v2.Pointer() {
   355  			return true
   356  		}
   357  		for i := 0; i < v1.Len(); i++ {
   358  			if !e.deepValueDerive(v1.Index(i), v2.Index(i), visited, depth+1) {
   359  				return false
   360  			}
   361  		}
   362  		return true
   363  	case reflect.String:
   364  		if v1.Len() == 0 {
   365  			return true
   366  		}
   367  		if v1.Len() > v2.Len() {
   368  			return false
   369  		}
   370  		return v1.String() == v2.String()
   371  	case reflect.Interface:
   372  		if v1.IsNil() {
   373  			return true
   374  		}
   375  		return e.deepValueDerive(v1.Elem(), v2.Elem(), visited, depth+1)
   376  	case reflect.Pointer:
   377  		if v1.IsNil() {
   378  			return true
   379  		}
   380  		return e.deepValueDerive(v1.Elem(), v2.Elem(), visited, depth+1)
   381  	case reflect.Struct:
   382  		for i, n := 0, v1.NumField(); i < n; i++ {
   383  			if !e.deepValueDerive(v1.Field(i), v2.Field(i), visited, depth+1) {
   384  				return false
   385  			}
   386  		}
   387  		return true
   388  	case reflect.Map:
   389  		if v1.IsNil() || v1.Len() == 0 {
   390  			return true
   391  		}
   392  		if v1.Len() > v2.Len() {
   393  			return false
   394  		}
   395  		if v1.Pointer() == v2.Pointer() {
   396  			return true
   397  		}
   398  		for _, k := range v1.MapKeys() {
   399  			if !e.deepValueDerive(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
   400  				return false
   401  			}
   402  		}
   403  		return true
   404  	case reflect.Func:
   405  		if v1.IsNil() && v2.IsNil() {
   406  			return true
   407  		}
   408  		// Can't do better than this:
   409  		return false
   410  	default:
   411  		// Normal equality suffices
   412  		if !v1.CanInterface() || !v2.CanInterface() {
   413  			panic(unexportedTypePanic{})
   414  		}
   415  		return v1.Interface() == v2.Interface()
   416  	}
   417  }
   418  
   419  // DeepDerivative is similar to DeepEqual except that unset fields in a1 are
   420  // ignored (not compared). This allows us to focus on the fields that matter to
   421  // the semantic comparison.
   422  //
   423  // The unset fields include a nil pointer and an empty string.
   424  func (e Equalities) DeepDerivative(a1, a2 interface{}) bool {
   425  	if a1 == nil {
   426  		return true
   427  	}
   428  	v1 := reflect.ValueOf(a1)
   429  	v2 := reflect.ValueOf(a2)
   430  	if v1.Type() != v2.Type() {
   431  		return false
   432  	}
   433  	return e.deepValueDerive(v1, v2, make(map[visit]bool), 0)
   434  }