blob: 551373dcf325bf12941ee37f937bc35d606ff974 [file] [log] [blame]
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package generic
import "reflect"
// CanOrder returns whether the values a and b are orderable according
// to the Go language specification.
func CanOrder(a, b interface{}) bool {
ak, bk := reflect.ValueOf(a).Kind(), reflect.ValueOf(b).Kind()
if ak != bk {
return false
}
return CanOrderR(ak)
}
var orderable = map[reflect.Kind]bool{
reflect.Int: true,
reflect.Int8: true,
reflect.Int16: true,
reflect.Int32: true,
reflect.Int64: true,
reflect.Uint: true,
reflect.Uintptr: true,
reflect.Uint8: true,
reflect.Uint16: true,
reflect.Uint32: true,
reflect.Uint64: true,
reflect.Float32: true,
reflect.Float64: true,
reflect.String: true,
}
// CanOrderR returns whether two values of kind k are orderable
// according to the Go language specification.
func CanOrderR(k reflect.Kind) bool {
return orderable[k]
}
// Order returns the order of values a and b: -1 if a < b, 0 if a ==
// b, 1 if a > b. The results are undefined if either a or b is NaN.
//
// Order panics if a and b are not orderable according to the Go
// language specification.
func Order(a, b interface{}) int {
return OrderR(reflect.ValueOf(a), reflect.ValueOf(b))
}
// OrderR is equivalent to Order, but operates on reflect.Values.
func OrderR(a, b reflect.Value) int {
if a.Kind() != b.Kind() {
panic(&TypeError{a.Type(), b.Type(), "are not orderable because they are different kinds"})
}
switch a.Kind() {
case reflect.Float32, reflect.Float64:
a, b := a.Float(), b.Float()
if a < b {
return -1
} else if a > b {
return 1
}
return 0
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
a, b := a.Int(), b.Int()
if a < b {
return -1
} else if a > b {
return 1
}
return 0
case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
a, b := a.Uint(), b.Uint()
if a < b {
return -1
} else if a > b {
return 1
}
return 0
case reflect.String:
a, b := a.String(), b.String()
if a < b {
return -1
} else if a > b {
return 1
}
return 0
}
panic(&TypeError{a.Type(), nil, "is not orderable"})
}