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