github.com/niubaoshu/goutils@v0.0.0-20180828035119-e8e576f66c2b/deepequal.go (about)

     1  package goutils
     2  
     3  import (
     4  	"reflect"
     5  	"sync"
     6  	"sync/atomic"
     7  	"time"
     8  	"unsafe"
     9  )
    10  
    11  // Copyright 2009 The Go Authors. All rights reserved.
    12  // Use of this source code is governed by a BSD-style
    13  // license that can be found in the LICENSE file.
    14  
    15  // Deep equality test via reflection
    16  
    17  // During deepValueEqual, must keep track of checks that are
    18  // in progress. The comparison algorithm assumes that all
    19  // checks in progress are true when it reencounters them.
    20  // Visited comparisons are stored in a map indexed by visit.
    21  type visit struct {
    22  	a1  unsafe.Pointer
    23  	a2  unsafe.Pointer
    24  	typ reflect.Type
    25  }
    26  
    27  type (
    28  	Comparer struct {
    29  		mu      sync.RWMutex
    30  		visited map[visit]bool
    31  		funcs   atomic.Value
    32  	}
    33  	comparers map[reflect.Type]func(v1, v2 interface{}) bool
    34  )
    35  
    36  func (c *Comparer) Add(rt reflect.Type, fn func(interface{}, interface{}) bool) {
    37  	c.mu.Lock()
    38  	fs := c.funcs.Load().(comparers)
    39  	nfs := make(comparers)
    40  	for k, v := range fs {
    41  		nfs[k] = v
    42  	}
    43  	nfs[rt] = fn
    44  	c.funcs.Store(nfs)
    45  	c.mu.Unlock()
    46  }
    47  
    48  func NewComparer() *Comparer {
    49  	c := &Comparer{
    50  		visited: make(map[visit]bool),
    51  	}
    52  	c.funcs.Store(
    53  		comparers(map[reflect.Type]func(interface{}, interface{}) bool{
    54  			reflect.TypeOf((*time.Time)(nil)).Elem(): func(v1 interface{}, v2 interface{}) bool {
    55  				return v1.(time.Time).Equal(v2.(time.Time))
    56  			},
    57  		}),
    58  	)
    59  	return c
    60  }
    61  
    62  // Tests for deep equality using reflected types. The map argument tracks
    63  // comparisons that have already been seen, which allows short circuiting on
    64  // recursive types.
    65  func (c *Comparer) deepValueEqual(v1, v2 reflect.Value, depth int) bool {
    66  	if !v1.IsValid() || !v2.IsValid() {
    67  		return v1.IsValid() == v2.IsValid()
    68  	}
    69  	if v1.Type() != v2.Type() {
    70  		return false
    71  	}
    72  
    73  	if fn, ok := c.funcs.Load().(comparers)[v1.Type()]; ok {
    74  		return fn(valueInterface(v1, false), valueInterface(v2, false))
    75  	}
    76  
    77  	// if depth > 10 { panic("deepValueEqual") }	// for debugging
    78  
    79  	// We want to avoid putting more in the visited map than we need to.
    80  	// For any possible reference cycle that might be encountered,
    81  	// hard(t) needs to return true for at least one of the types in the cycle.
    82  	hard := func(k reflect.Kind) bool {
    83  		switch k {
    84  		case reflect.Map, reflect.Slice, reflect.Ptr, reflect.Interface:
    85  			return true
    86  		}
    87  		return false
    88  	}
    89  
    90  	if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
    91  		addr1 := unsafe.Pointer(v1.UnsafeAddr())
    92  		addr2 := unsafe.Pointer(v2.UnsafeAddr())
    93  		if uintptr(addr1) > uintptr(addr2) {
    94  			// Canonicalize order to reduce number of entries in visited.
    95  			// Assumes non-moving garbage collector.
    96  			addr1, addr2 = addr2, addr1
    97  		}
    98  
    99  		// Short circuit if references are already seen.
   100  		typ := v1.Type()
   101  		v := visit{addr1, addr2, typ}
   102  		if c.visited[v] {
   103  			return true
   104  		}
   105  
   106  		// Remember for later.
   107  		c.visited[v] = true
   108  	}
   109  
   110  	switch v1.Kind() {
   111  	case reflect.Array:
   112  		for i := 0; i < v1.Len(); i++ {
   113  			if !c.deepValueEqual(v1.Index(i), v2.Index(i), depth+1) {
   114  				return false
   115  			}
   116  		}
   117  		return true
   118  	case reflect.Slice:
   119  		if v1.IsNil() != v2.IsNil() {
   120  			return false
   121  		}
   122  		if v1.Len() != v2.Len() {
   123  			return false
   124  		}
   125  		if v1.Pointer() == v2.Pointer() {
   126  			return true
   127  		}
   128  		for i := 0; i < v1.Len(); i++ {
   129  			if !c.deepValueEqual(v1.Index(i), v2.Index(i), depth+1) {
   130  				return false
   131  			}
   132  		}
   133  		return true
   134  	case reflect.Interface:
   135  		if v1.IsNil() || v2.IsNil() {
   136  			return v1.IsNil() == v2.IsNil()
   137  		}
   138  		return c.deepValueEqual(v1.Elem(), v2.Elem(), depth+1)
   139  	case reflect.Ptr:
   140  		if v1.Pointer() == v2.Pointer() {
   141  			return true
   142  		}
   143  		return c.deepValueEqual(v1.Elem(), v2.Elem(), depth+1)
   144  	case reflect.Struct:
   145  		for i, n := 0, v1.NumField(); i < n; i++ {
   146  			if !c.deepValueEqual(v1.Field(i), v2.Field(i), depth+1) {
   147  				return false
   148  			}
   149  		}
   150  		return true
   151  	case reflect.Map:
   152  		if v1.IsNil() != v2.IsNil() {
   153  			return false
   154  		}
   155  		if v1.Len() != v2.Len() {
   156  			return false
   157  		}
   158  		if v1.Pointer() == v2.Pointer() {
   159  			return true
   160  		}
   161  		if v1.Type().Key().Kind() == reflect.Ptr {
   162  			dupv2 := reflect.ValueOf(DeepClone(valueInterface(v2, false)))
   163  			for _, k1 := range v1.MapKeys() {
   164  				if !k1.IsValid() {
   165  					return false
   166  				}
   167  				lookup := false
   168  				for _, dk2 := range dupv2.MapKeys() {
   169  					if dk2.IsValid() && c.deepValueEqual(k1, dk2, depth+1) {
   170  						val1 := v1.MapIndex(k1)
   171  						val2 := dupv2.MapIndex(dk2)
   172  						if val1.IsValid() && val2.IsValid() && c.deepValueEqual(val1, val2, depth+1) {
   173  							dupv2.SetMapIndex(dk2, reflect.Value{})
   174  							lookup = true
   175  							break
   176  						}
   177  					}
   178  				}
   179  				if !lookup {
   180  					return false
   181  				}
   182  			}
   183  			return true
   184  		}
   185  		for _, k1 := range v1.MapKeys() {
   186  			val1 := v1.MapIndex(k1)
   187  			val2 := v2.MapIndex(k1)
   188  			if !val1.IsValid() || !val2.IsValid() || !c.deepValueEqual(val1, val2, depth+1) {
   189  				return false
   190  			}
   191  		}
   192  		return true
   193  	case reflect.Func:
   194  		if v1.IsNil() && v2.IsNil() {
   195  			return true
   196  		}
   197  		// Can't do better than this:
   198  		return false
   199  	default:
   200  		// Normal equality suffices
   201  		return valueInterface(v1, false) == valueInterface(v2, false)
   202  	}
   203  }
   204  
   205  //go:linkname valueInterface reflect.valueInterface
   206  func valueInterface(v reflect.Value, safe bool) interface{}
   207  
   208  // DeepEqual reports whether x and y are ``deeply equal,'' defined as follows.
   209  // Two values of identical type are deeply equal if one of the following cases applies.
   210  // Values of distinct types are never deeply equal.
   211  //
   212  // Array values are deeply equal when their corresponding elements are deeply equal.
   213  //
   214  // Struct values are deeply equal if their corresponding fields,
   215  // both exported and unexported, are deeply equal.
   216  //
   217  // Func values are deeply equal if both are nil; otherwise they are not deeply equal.
   218  //
   219  // Interface values are deeply equal if they hold deeply equal concrete values.
   220  //
   221  // Map values are deeply equal when all of the following are true:
   222  // they are both nil or both non-nil, they have the same length,
   223  // and either they are the same map object or their corresponding keys
   224  // (matched using Go equality) map to deeply equal values.
   225  //
   226  // Pointer values are deeply equal if they are equal using Go's == operator
   227  // or if they point to deeply equal values.
   228  //
   229  // Slice values are deeply equal when all of the following are true:
   230  // they are both nil or both non-nil, they have the same length,
   231  // and either they point to the same initial entry of the same underlying array
   232  // (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal.
   233  // Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil))
   234  // are not deeply equal.
   235  //
   236  // Other values - numbers, bools, strings, and channels - are deeply equal
   237  // if they are equal using Go's == operator.
   238  //
   239  // In general DeepEqual is a recursive relaxation of Go's == operator.
   240  // However, this idea is impossible to implement without some inconsistency.
   241  // Specifically, it is possible for a value to be unequal to itself,
   242  // either because it is of func type (uncomparable in general)
   243  // or because it is a floating-point NaN value (not equal to itself in floating-point comparison),
   244  // or because it is an array, struct, or interface containing
   245  // such a value.
   246  // On the other hand, pointer values are always equal to themselves,
   247  // even if they point at or contain such problematic values,
   248  // because they compare equal using Go's == operator, and that
   249  // is a sufficient condition to be deeply equal, regardless of content.
   250  // DeepEqual has been defined so that the same short-cut applies
   251  // to slices and maps: if x and y are the same slice or the same map,
   252  // they are deeply equal regardless of content.
   253  func (c *Comparer) DeepEqual(x, y interface{}) bool {
   254  	if x == nil || y == nil {
   255  		return x == y
   256  	}
   257  	v1 := reflect.ValueOf(x)
   258  	v2 := reflect.ValueOf(y)
   259  	if v1.Type() != v2.Type() {
   260  		return false
   261  	}
   262  	return c.deepValueEqual(v1, v2, 0)
   263  }