github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/elvish/eval/vals/equal.go (about)

     1  package vals
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/u-root/u-root/cmds/core/elvish/hashmap"
     7  )
     8  
     9  // Equaler wraps the Equal method.
    10  type Equaler interface {
    11  	// Equal compares the receiver to another value. Two equal values must have
    12  	// the same hash code.
    13  	Equal(other interface{}) bool
    14  }
    15  
    16  // Equal returns whether two values are equal. It is implemented for the builtin
    17  // types bool and string, and types satisfying the listEqualable, mapEqualable
    18  // or Equaler interface. For other types, it uses reflect.DeepEqual to compare
    19  // the two values.
    20  func Equal(x, y interface{}) bool {
    21  	switch x := x.(type) {
    22  	case Equaler:
    23  		return x.Equal(y)
    24  	case bool:
    25  		return x == y
    26  	case string:
    27  		return x == y
    28  	case listEqualable:
    29  		if yy, ok := y.(listEqualable); ok {
    30  			return equalList(x, yy)
    31  		}
    32  		return false
    33  	case mapEqualable:
    34  		if yy, ok := y.(mapEqualable); ok {
    35  			return equalMap(x, yy)
    36  		}
    37  		return false
    38  	}
    39  	return reflect.DeepEqual(x, y)
    40  }
    41  
    42  type listEqualable interface {
    43  	Lener
    44  	listIterable
    45  }
    46  
    47  func equalList(x, y listEqualable) bool {
    48  	if x.Len() != y.Len() {
    49  		return false
    50  	}
    51  	ix := x.Iterator()
    52  	iy := y.Iterator()
    53  	for ix.HasElem() && iy.HasElem() {
    54  		if !Equal(ix.Elem(), iy.Elem()) {
    55  			return false
    56  		}
    57  		ix.Next()
    58  		iy.Next()
    59  	}
    60  	return true
    61  }
    62  
    63  type mapEqualable interface {
    64  	Lener
    65  	Index(interface{}) (interface{}, bool)
    66  	Iterator() hashmap.Iterator
    67  }
    68  
    69  var _ mapEqualable = hashmap.Map(nil)
    70  
    71  func equalMap(x, y mapEqualable) bool {
    72  	if x.Len() != y.Len() {
    73  		return false
    74  	}
    75  	for it := x.Iterator(); it.HasElem(); it.Next() {
    76  		k, vx := it.Elem()
    77  		vy, ok := y.Index(k)
    78  		if !ok || !Equal(vx, vy) {
    79  			return false
    80  		}
    81  	}
    82  	return true
    83  }