mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	Fixes # https://github.com/kubernetes/kubernetes/issues/70802 Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
		
			
				
	
	
		
			164 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2016 Qiang Xue. All rights reserved.
 | |
| // Use of this source code is governed by a MIT-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package validation
 | |
| 
 | |
| import (
 | |
| 	"database/sql/driver"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	bytesType  = reflect.TypeOf([]byte(nil))
 | |
| 	valuerType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
 | |
| )
 | |
| 
 | |
| // EnsureString ensures the given value is a string.
 | |
| // If the value is a byte slice, it will be typecast into a string.
 | |
| // An error is returned otherwise.
 | |
| func EnsureString(value interface{}) (string, error) {
 | |
| 	v := reflect.ValueOf(value)
 | |
| 	if v.Kind() == reflect.String {
 | |
| 		return v.String(), nil
 | |
| 	}
 | |
| 	if v.Type() == bytesType {
 | |
| 		return string(v.Interface().([]byte)), nil
 | |
| 	}
 | |
| 	return "", errors.New("must be either a string or byte slice")
 | |
| }
 | |
| 
 | |
| // StringOrBytes typecasts a value into a string or byte slice.
 | |
| // Boolean flags are returned to indicate if the typecasting succeeds or not.
 | |
| func StringOrBytes(value interface{}) (isString bool, str string, isBytes bool, bs []byte) {
 | |
| 	v := reflect.ValueOf(value)
 | |
| 	if v.Kind() == reflect.String {
 | |
| 		str = v.String()
 | |
| 		isString = true
 | |
| 	} else if v.Kind() == reflect.Slice && v.Type() == bytesType {
 | |
| 		bs = v.Interface().([]byte)
 | |
| 		isBytes = true
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // LengthOfValue returns the length of a value that is a string, slice, map, or array.
 | |
| // An error is returned for all other types.
 | |
| func LengthOfValue(value interface{}) (int, error) {
 | |
| 	v := reflect.ValueOf(value)
 | |
| 	switch v.Kind() {
 | |
| 	case reflect.String, reflect.Slice, reflect.Map, reflect.Array:
 | |
| 		return v.Len(), nil
 | |
| 	}
 | |
| 	return 0, fmt.Errorf("cannot get the length of %v", v.Kind())
 | |
| }
 | |
| 
 | |
| // ToInt converts the given value to an int64.
 | |
| // An error is returned for all incompatible types.
 | |
| func ToInt(value interface{}) (int64, error) {
 | |
| 	v := reflect.ValueOf(value)
 | |
| 	switch v.Kind() {
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		return v.Int(), nil
 | |
| 	}
 | |
| 	return 0, fmt.Errorf("cannot convert %v to int64", v.Kind())
 | |
| }
 | |
| 
 | |
| // ToUint converts the given value to an uint64.
 | |
| // An error is returned for all incompatible types.
 | |
| func ToUint(value interface{}) (uint64, error) {
 | |
| 	v := reflect.ValueOf(value)
 | |
| 	switch v.Kind() {
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		return v.Uint(), nil
 | |
| 	}
 | |
| 	return 0, fmt.Errorf("cannot convert %v to uint64", v.Kind())
 | |
| }
 | |
| 
 | |
| // ToFloat converts the given value to a float64.
 | |
| // An error is returned for all incompatible types.
 | |
| func ToFloat(value interface{}) (float64, error) {
 | |
| 	v := reflect.ValueOf(value)
 | |
| 	switch v.Kind() {
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return v.Float(), nil
 | |
| 	}
 | |
| 	return 0, fmt.Errorf("cannot convert %v to float64", v.Kind())
 | |
| }
 | |
| 
 | |
| // IsEmpty checks if a value is empty or not.
 | |
| // A value is considered empty if
 | |
| // - integer, float: zero
 | |
| // - bool: false
 | |
| // - string, array: len() == 0
 | |
| // - slice, map: nil or len() == 0
 | |
| // - interface, pointer: nil or the referenced value is empty
 | |
| func IsEmpty(value interface{}) bool {
 | |
| 	v := reflect.ValueOf(value)
 | |
| 	switch v.Kind() {
 | |
| 	case reflect.String, reflect.Array, reflect.Map, reflect.Slice:
 | |
| 		return v.Len() == 0
 | |
| 	case reflect.Bool:
 | |
| 		return !v.Bool()
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		return v.Int() == 0
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		return v.Uint() == 0
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return v.Float() == 0
 | |
| 	case reflect.Invalid:
 | |
| 		return true
 | |
| 	case reflect.Interface, reflect.Ptr:
 | |
| 		if v.IsNil() {
 | |
| 			return true
 | |
| 		}
 | |
| 		return IsEmpty(v.Elem().Interface())
 | |
| 	case reflect.Struct:
 | |
| 		v, ok := value.(time.Time)
 | |
| 		if ok && v.IsZero() {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // Indirect returns the value that the given interface or pointer references to.
 | |
| // If the value implements driver.Valuer, it will deal with the value returned by
 | |
| // the Value() method instead. A boolean value is also returned to indicate if
 | |
| // the value is nil or not (only applicable to interface, pointer, map, and slice).
 | |
| // If the value is neither an interface nor a pointer, it will be returned back.
 | |
| func Indirect(value interface{}) (interface{}, bool) {
 | |
| 	rv := reflect.ValueOf(value)
 | |
| 	kind := rv.Kind()
 | |
| 	switch kind {
 | |
| 	case reflect.Invalid:
 | |
| 		return nil, true
 | |
| 	case reflect.Ptr, reflect.Interface:
 | |
| 		if rv.IsNil() {
 | |
| 			return nil, true
 | |
| 		}
 | |
| 		return Indirect(rv.Elem().Interface())
 | |
| 	case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
 | |
| 		if rv.IsNil() {
 | |
| 			return nil, true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if rv.Type().Implements(valuerType) {
 | |
| 		return indirectValuer(value.(driver.Valuer))
 | |
| 	}
 | |
| 
 | |
| 	return value, false
 | |
| }
 | |
| 
 | |
| func indirectValuer(valuer driver.Valuer) (interface{}, bool) {
 | |
| 	if value, err := valuer.Value(); value != nil && err == nil {
 | |
| 		return Indirect(value)
 | |
| 	}
 | |
| 	return nil, true
 | |
| }
 |