in pkg/cmd/get/sorter.go [175:295]
func isLess(i, j reflect.Value) (bool, error) {
switch i.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return i.Int() < j.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return i.Uint() < j.Uint(), nil
case reflect.Float32, reflect.Float64:
return i.Float() < j.Float(), nil
case reflect.String:
return sortorder.NaturalLess(i.String(), j.String()), nil
case reflect.Ptr:
return isLess(i.Elem(), j.Elem())
case reflect.Struct:
// sort metav1.Time
in := i.Interface()
if t, ok := in.(metav1.Time); ok {
time := j.Interface().(metav1.Time)
return t.Before(&time), nil
}
// sort resource.Quantity
if iQuantity, ok := in.(resource.Quantity); ok {
jQuantity := j.Interface().(resource.Quantity)
return iQuantity.Cmp(jQuantity) < 0, nil
}
// fallback to the fields comparison
for idx := 0; idx < i.NumField(); idx++ {
less, err := isLess(i.Field(idx), j.Field(idx))
if err != nil || !less {
return less, err
}
}
return true, nil
case reflect.Array, reflect.Slice:
// note: the length of i and j may be different
for idx := 0; idx < integer.IntMin(i.Len(), j.Len()); idx++ {
less, err := isLess(i.Index(idx), j.Index(idx))
if err != nil || !less {
return less, err
}
}
return true, nil
case reflect.Interface:
if i.IsNil() && j.IsNil() {
return false, nil
} else if i.IsNil() {
return true, nil
} else if j.IsNil() {
return false, nil
}
switch itype := i.Interface().(type) {
case uint8:
if jtype, ok := j.Interface().(uint8); ok {
return itype < jtype, nil
}
case uint16:
if jtype, ok := j.Interface().(uint16); ok {
return itype < jtype, nil
}
case uint32:
if jtype, ok := j.Interface().(uint32); ok {
return itype < jtype, nil
}
case uint64:
if jtype, ok := j.Interface().(uint64); ok {
return itype < jtype, nil
}
case int8:
if jtype, ok := j.Interface().(int8); ok {
return itype < jtype, nil
}
case int16:
if jtype, ok := j.Interface().(int16); ok {
return itype < jtype, nil
}
case int32:
if jtype, ok := j.Interface().(int32); ok {
return itype < jtype, nil
}
case int64:
if jtype, ok := j.Interface().(int64); ok {
return itype < jtype, nil
}
case uint:
if jtype, ok := j.Interface().(uint); ok {
return itype < jtype, nil
}
case int:
if jtype, ok := j.Interface().(int); ok {
return itype < jtype, nil
}
case float32:
if jtype, ok := j.Interface().(float32); ok {
return itype < jtype, nil
}
case float64:
if jtype, ok := j.Interface().(float64); ok {
return itype < jtype, nil
}
case string:
if jtype, ok := j.Interface().(string); ok {
// check if it's a Quantity
itypeQuantity, err := resource.ParseQuantity(itype)
if err != nil {
return sortorder.NaturalLess(itype, jtype), nil
}
jtypeQuantity, err := resource.ParseQuantity(jtype)
if err != nil {
return sortorder.NaturalLess(itype, jtype), nil
}
// Both strings are quantity
return itypeQuantity.Cmp(jtypeQuantity) < 0, nil
}
default:
return false, fmt.Errorf("unsortable type: %T", itype)
}
return false, fmt.Errorf("unsortable interface: %v", i.Kind())
default:
return false, fmt.Errorf("unsortable type: %v", i.Kind())
}
}