mirror of
https://github.com/danog/liquid.git
synced 2024-12-02 12:27:45 +01:00
112 lines
2.3 KiB
Go
112 lines
2.3 KiB
Go
|
package generics
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
)
|
||
|
|
||
|
// Equal returns a bool indicating whether a == b after conversion.
|
||
|
func Equal(a, b interface{}) bool {
|
||
|
return genericCompare(reflect.ValueOf(a), reflect.ValueOf(b)) == 0
|
||
|
}
|
||
|
|
||
|
// Less returns a bool indicating whether a < b.
|
||
|
func Less(a, b interface{}) bool {
|
||
|
return genericCompare(reflect.ValueOf(a), reflect.ValueOf(b)) < 0
|
||
|
}
|
||
|
|
||
|
func genericSameTypeCompare(av, bv interface{}) int {
|
||
|
a, b := reflect.ValueOf(av), reflect.ValueOf(bv)
|
||
|
if a.Kind() != b.Kind() {
|
||
|
panic(fmt.Errorf("genericSameTypeCompare called on different types: %v and %v", a, b))
|
||
|
}
|
||
|
if a == b {
|
||
|
return 0
|
||
|
}
|
||
|
switch a.Kind() {
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
if a.Int() < b.Int() {
|
||
|
return -1
|
||
|
}
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
if a.Float() < b.Float() {
|
||
|
return -1
|
||
|
}
|
||
|
case reflect.String:
|
||
|
if a.String() < b.String() {
|
||
|
return -1
|
||
|
}
|
||
|
default:
|
||
|
panic(genericErrorf("unimplemented generic same-type comparison for %v and %v", a, b))
|
||
|
}
|
||
|
return 1
|
||
|
}
|
||
|
|
||
|
func genericCompare(a, b reflect.Value) int {
|
||
|
if a.Interface() == b.Interface() {
|
||
|
return 0
|
||
|
}
|
||
|
ak, bk := a.Kind(), b.Kind()
|
||
|
// _ = ak.Convert
|
||
|
switch a.Kind() {
|
||
|
case reflect.Bool:
|
||
|
if b.Kind() == reflect.Bool {
|
||
|
switch {
|
||
|
case a.Bool() && b.Bool():
|
||
|
return 0
|
||
|
case a.Bool():
|
||
|
return 1
|
||
|
case b.Bool():
|
||
|
return -1
|
||
|
default:
|
||
|
return 0
|
||
|
}
|
||
|
}
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
if hasIntKind(b) {
|
||
|
if a.Int() < b.Int() {
|
||
|
return -1
|
||
|
}
|
||
|
if a.Int() > b.Int() {
|
||
|
return 1
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
if hasFloatKind(b) {
|
||
|
return genericCompare(reflect.ValueOf(float64(a.Int())), b)
|
||
|
}
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
if hasIntKind(b) {
|
||
|
b = reflect.ValueOf(float64(b.Int()))
|
||
|
}
|
||
|
if hasFloatKind(b) {
|
||
|
if a.Float() < b.Float() {
|
||
|
return -1
|
||
|
}
|
||
|
if a.Float() > b.Float() {
|
||
|
return 1
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
}
|
||
|
panic(genericErrorf("unimplemented: comparison of %v<%s> with %v<%s>", a, ak, b, bk))
|
||
|
}
|
||
|
|
||
|
func hasIntKind(n reflect.Value) bool {
|
||
|
switch n.Kind() {
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return true
|
||
|
default:
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func hasFloatKind(n reflect.Value) bool {
|
||
|
switch n.Kind() {
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return true
|
||
|
default:
|
||
|
return false
|
||
|
}
|
||
|
}
|