github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/eval/vals/equal.go (about) 1 package vals 2 3 import ( 4 "math/big" 5 "reflect" 6 ) 7 8 // Equaler wraps the Equal method. 9 type Equaler interface { 10 // Equal compares the receiver to another value. Two equal values must have 11 // the same hash code. 12 Equal(other interface{}) bool 13 } 14 15 // Equal returns whether two values are equal. It is implemented for the builtin 16 // types bool and string, the File, List, Map types, StructMap types, and types 17 // satisfying the Equaler interface. For other types, it uses reflect.DeepEqual 18 // to compare the two values. 19 func Equal(x, y interface{}) bool { 20 switch x := x.(type) { 21 case nil: 22 return x == y 23 case bool: 24 return x == y 25 case int: 26 return x == y 27 case float64: 28 return x == y 29 case *big.Int: 30 if y, ok := y.(*big.Int); ok { 31 return x.Cmp(y) == 0 32 } 33 return false 34 case *big.Rat: 35 if y, ok := y.(*big.Rat); ok { 36 return x.Cmp(y) == 0 37 } 38 return false 39 case string: 40 return x == y 41 case Equaler: 42 return x.Equal(y) 43 case File: 44 if yy, ok := y.(File); ok { 45 return x.Fd() == yy.Fd() 46 } 47 return false 48 case List: 49 if yy, ok := y.(List); ok { 50 return equalList(x, yy) 51 } 52 return false 53 case Map: 54 if yy, ok := y.(Map); ok { 55 return equalMap(x, yy) 56 } 57 return false 58 case StructMap: 59 if yy, ok := y.(StructMap); ok { 60 return equalStructMap(x, yy) 61 } 62 return false 63 default: 64 return reflect.DeepEqual(x, y) 65 } 66 } 67 68 func equalList(x, y List) bool { 69 if x.Len() != y.Len() { 70 return false 71 } 72 ix := x.Iterator() 73 iy := y.Iterator() 74 for ix.HasElem() && iy.HasElem() { 75 if !Equal(ix.Elem(), iy.Elem()) { 76 return false 77 } 78 ix.Next() 79 iy.Next() 80 } 81 return true 82 } 83 84 func equalMap(x, y Map) bool { 85 if x.Len() != y.Len() { 86 return false 87 } 88 for it := x.Iterator(); it.HasElem(); it.Next() { 89 k, vx := it.Elem() 90 vy, ok := y.Index(k) 91 if !ok || !Equal(vx, vy) { 92 return false 93 } 94 } 95 return true 96 } 97 98 func equalStructMap(x, y StructMap) bool { 99 t := reflect.TypeOf(x) 100 if t != reflect.TypeOf(y) { 101 return false 102 } 103 104 xValue := reflect.ValueOf(x) 105 yValue := reflect.ValueOf(y) 106 it := iterateStructMap(t) 107 for it.Next() { 108 _, xField := it.Get(xValue) 109 _, yField := it.Get(yValue) 110 if !Equal(xField, yField) { 111 return false 112 } 113 } 114 return true 115 }