2017-06-27 16:28:39 +02:00
|
|
|
package generics
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
)
|
|
|
|
|
2017-06-28 15:36:39 +02:00
|
|
|
var (
|
|
|
|
int64Type = reflect.TypeOf(int64(0))
|
|
|
|
float64Type = reflect.TypeOf(float64(0))
|
|
|
|
)
|
|
|
|
|
2017-06-27 16:28:39 +02:00
|
|
|
// Equal returns a bool indicating whether a == b after conversion.
|
2017-07-02 05:52:23 +02:00
|
|
|
func Equal(a, b interface{}) bool { // nolint: gocyclo
|
2017-06-28 04:54:27 +02:00
|
|
|
if a == nil || b == nil {
|
|
|
|
return a == b
|
|
|
|
}
|
2017-06-28 15:36:39 +02:00
|
|
|
ra, rb := reflect.ValueOf(a), reflect.ValueOf(b)
|
|
|
|
switch joinKind(ra.Kind(), rb.Kind()) {
|
|
|
|
case reflect.Array, reflect.Slice:
|
|
|
|
if ra.Len() != rb.Len() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i := 0; i < ra.Len(); i++ {
|
|
|
|
if !Equal(ra.Index(i).Interface(), rb.Index(i).Interface()) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
case reflect.Bool:
|
|
|
|
return ra.Bool() == rb.Bool()
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
|
return ra.Convert(int64Type).Int() == rb.Convert(int64Type).Int()
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
return ra.Convert(float64Type).Float() == rb.Convert(float64Type).Float()
|
|
|
|
case reflect.String:
|
|
|
|
return ra.String() == rb.String()
|
|
|
|
default:
|
|
|
|
return a == b
|
|
|
|
}
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Less returns a bool indicating whether a < b.
|
|
|
|
func Less(a, b interface{}) bool {
|
2017-06-28 15:36:39 +02:00
|
|
|
if a == nil || b == nil {
|
2017-06-28 03:30:47 +02:00
|
|
|
return false
|
|
|
|
}
|
2017-06-28 15:36:39 +02:00
|
|
|
ra, rb := reflect.ValueOf(a), reflect.ValueOf(b)
|
|
|
|
switch joinKind(ra.Kind(), rb.Kind()) {
|
2017-06-28 03:30:47 +02:00
|
|
|
case reflect.Bool:
|
2017-06-28 15:36:39 +02:00
|
|
|
return !ra.Bool() && rb.Bool()
|
2017-06-27 16:28:39 +02:00
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
2017-06-28 15:36:39 +02:00
|
|
|
return ra.Convert(int64Type).Int() < rb.Convert(int64Type).Int()
|
2017-06-27 16:28:39 +02:00
|
|
|
case reflect.Float32, reflect.Float64:
|
2017-06-28 15:36:39 +02:00
|
|
|
return ra.Convert(float64Type).Float() < rb.Convert(float64Type).Float()
|
2017-06-27 16:28:39 +02:00
|
|
|
case reflect.String:
|
2017-06-28 15:36:39 +02:00
|
|
|
return ra.String() < rb.String()
|
2017-06-27 16:28:39 +02:00
|
|
|
default:
|
2017-06-28 15:36:39 +02:00
|
|
|
return false
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-02 05:52:23 +02:00
|
|
|
func joinKind(a, b reflect.Kind) reflect.Kind { // nolint: gocyclo
|
2017-06-28 15:36:39 +02:00
|
|
|
if a == b {
|
|
|
|
return a
|
2017-06-27 23:29:50 +02:00
|
|
|
}
|
2017-06-28 15:36:39 +02:00
|
|
|
switch a {
|
|
|
|
case reflect.Array, reflect.Slice:
|
|
|
|
if b == reflect.Array || b == reflect.Slice {
|
|
|
|
return reflect.Slice
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
2017-06-28 15:36:39 +02:00
|
|
|
if isIntKind(b) {
|
|
|
|
return reflect.Int64
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
2017-06-28 15:36:39 +02:00
|
|
|
if isFloatKind(b) {
|
|
|
|
return reflect.Float64
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
case reflect.Float32, reflect.Float64:
|
2017-06-28 15:36:39 +02:00
|
|
|
if isIntKind(b) || isFloatKind(b) {
|
|
|
|
return reflect.Float64
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
}
|
2017-06-28 15:36:39 +02:00
|
|
|
return reflect.Invalid
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
|
2017-06-28 15:36:39 +02:00
|
|
|
func isIntKind(k reflect.Kind) bool {
|
|
|
|
switch k {
|
2017-06-27 16:28:39 +02:00
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-28 15:36:39 +02:00
|
|
|
func isFloatKind(k reflect.Kind) bool {
|
|
|
|
switch k {
|
2017-06-27 16:28:39 +02:00
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|