2018-02-15 17:14:05 +08:00
|
|
|
package vals
|
2018-01-25 07:28:50 +08:00
|
|
|
|
2018-01-28 01:26:22 +08:00
|
|
|
import (
|
2021-06-22 11:59:00 +08:00
|
|
|
"math/big"
|
2018-01-28 01:26:22 +08:00
|
|
|
"reflect"
|
|
|
|
)
|
2018-01-25 07:57:58 +08:00
|
|
|
|
|
|
|
// Equaler wraps the Equal method.
|
|
|
|
type Equaler interface {
|
|
|
|
// Equal compares the receiver to another value. Two equal values must have
|
|
|
|
// the same hash code.
|
2022-03-20 23:50:25 +08:00
|
|
|
Equal(other any) bool
|
2018-01-25 07:57:58 +08:00
|
|
|
}
|
|
|
|
|
2018-01-27 23:51:37 +08:00
|
|
|
// Equal returns whether two values are equal. It is implemented for the builtin
|
2019-04-20 00:40:45 +08:00
|
|
|
// types bool and string, the File, List, Map types, StructMap types, and types
|
|
|
|
// satisfying the Equaler interface. For other types, it uses reflect.DeepEqual
|
|
|
|
// to compare the two values.
|
2022-03-20 23:50:25 +08:00
|
|
|
func Equal(x, y any) bool {
|
2018-01-25 09:40:15 +08:00
|
|
|
switch x := x.(type) {
|
2019-04-08 05:49:28 +08:00
|
|
|
case nil:
|
|
|
|
return x == y
|
2019-04-19 08:03:56 +08:00
|
|
|
case bool:
|
|
|
|
return x == y
|
2021-06-22 11:59:00 +08:00
|
|
|
case int:
|
|
|
|
return x == y
|
2019-04-10 06:46:04 +08:00
|
|
|
case float64:
|
|
|
|
return x == y
|
2021-06-22 11:59:00 +08:00
|
|
|
case *big.Int:
|
|
|
|
if y, ok := y.(*big.Int); ok {
|
|
|
|
return x.Cmp(y) == 0
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
case *big.Rat:
|
|
|
|
if y, ok := y.(*big.Rat); ok {
|
|
|
|
return x.Cmp(y) == 0
|
|
|
|
}
|
|
|
|
return false
|
2019-04-19 08:03:56 +08:00
|
|
|
case string:
|
|
|
|
return x == y
|
2020-06-28 08:47:31 +08:00
|
|
|
case Equaler:
|
|
|
|
return x.Equal(y)
|
2019-04-19 21:25:15 +08:00
|
|
|
case File:
|
|
|
|
if yy, ok := y.(File); ok {
|
|
|
|
return x.Fd() == yy.Fd()
|
|
|
|
}
|
|
|
|
return false
|
2019-04-19 19:24:45 +08:00
|
|
|
case List:
|
|
|
|
if yy, ok := y.(List); ok {
|
2018-01-29 22:36:43 +08:00
|
|
|
return equalList(x, yy)
|
2018-01-28 01:26:22 +08:00
|
|
|
}
|
2018-01-29 22:36:43 +08:00
|
|
|
return false
|
2019-04-19 19:24:45 +08:00
|
|
|
case Map:
|
|
|
|
if yy, ok := y.(Map); ok {
|
2018-01-29 22:36:43 +08:00
|
|
|
return equalMap(x, yy)
|
2018-01-28 01:26:22 +08:00
|
|
|
}
|
2018-01-29 22:36:43 +08:00
|
|
|
return false
|
2019-04-20 00:40:45 +08:00
|
|
|
case StructMap:
|
|
|
|
if yy, ok := y.(StructMap); ok {
|
|
|
|
return equalStructMap(x, yy)
|
|
|
|
}
|
|
|
|
return false
|
2019-04-19 08:03:56 +08:00
|
|
|
default:
|
|
|
|
return reflect.DeepEqual(x, y)
|
2018-01-25 07:57:58 +08:00
|
|
|
}
|
2018-01-25 07:28:50 +08:00
|
|
|
}
|
2018-01-28 01:26:22 +08:00
|
|
|
|
2019-04-19 19:24:45 +08:00
|
|
|
func equalList(x, y List) bool {
|
2018-01-29 22:36:43 +08:00
|
|
|
if x.Len() != y.Len() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
ix := x.Iterator()
|
|
|
|
iy := y.Iterator()
|
|
|
|
for ix.HasElem() && iy.HasElem() {
|
|
|
|
if !Equal(ix.Elem(), iy.Elem()) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
ix.Next()
|
|
|
|
iy.Next()
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-04-19 19:24:45 +08:00
|
|
|
func equalMap(x, y Map) bool {
|
2018-01-29 22:36:43 +08:00
|
|
|
if x.Len() != y.Len() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for it := x.Iterator(); it.HasElem(); it.Next() {
|
|
|
|
k, vx := it.Elem()
|
2018-03-02 07:15:51 +08:00
|
|
|
vy, ok := y.Index(k)
|
2018-01-29 22:36:43 +08:00
|
|
|
if !ok || !Equal(vx, vy) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2019-04-20 00:40:45 +08:00
|
|
|
|
|
|
|
func equalStructMap(x, y StructMap) bool {
|
2020-06-27 18:45:11 +08:00
|
|
|
t := reflect.TypeOf(x)
|
|
|
|
if t != reflect.TypeOf(y) {
|
2019-04-20 00:40:45 +08:00
|
|
|
return false
|
|
|
|
}
|
2020-06-27 18:45:11 +08:00
|
|
|
|
|
|
|
xValue := reflect.ValueOf(x)
|
|
|
|
yValue := reflect.ValueOf(y)
|
|
|
|
it := iterateStructMap(t)
|
|
|
|
for it.Next() {
|
|
|
|
_, xField := it.Get(xValue)
|
|
|
|
_, yField := it.Get(yValue)
|
|
|
|
if !Equal(xField, yField) {
|
2019-04-20 00:40:45 +08:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|