util.go raw

   1  // Copyright 2016 Qiang Xue. All rights reserved.
   2  // Use of this source code is governed by a MIT-style
   3  // license that can be found in the LICENSE file.
   4  
   5  package validation
   6  
   7  import (
   8  	"database/sql/driver"
   9  	"errors"
  10  	"fmt"
  11  	"reflect"
  12  	"time"
  13  )
  14  
  15  var (
  16  	bytesType  = reflect.TypeOf([]byte(nil))
  17  	valuerType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
  18  )
  19  
  20  // EnsureString ensures the given value is a string.
  21  // If the value is a byte slice, it will be typecast into a string.
  22  // An error is returned otherwise.
  23  func EnsureString(value interface{}) (string, error) {
  24  	v := reflect.ValueOf(value)
  25  	if v.Kind() == reflect.String {
  26  		return v.String(), nil
  27  	}
  28  	if v.Type() == bytesType {
  29  		return string(v.Interface().([]byte)), nil
  30  	}
  31  	return "", errors.New("must be either a string or byte slice")
  32  }
  33  
  34  // StringOrBytes typecasts a value into a string or byte slice.
  35  // Boolean flags are returned to indicate if the typecasting succeeds or not.
  36  func StringOrBytes(value interface{}) (isString bool, str string, isBytes bool, bs []byte) {
  37  	v := reflect.ValueOf(value)
  38  	if v.Kind() == reflect.String {
  39  		str = v.String()
  40  		isString = true
  41  	} else if v.Kind() == reflect.Slice && v.Type() == bytesType {
  42  		bs = v.Interface().([]byte)
  43  		isBytes = true
  44  	}
  45  	return
  46  }
  47  
  48  // LengthOfValue returns the length of a value that is a string, slice, map, or array.
  49  // An error is returned for all other types.
  50  func LengthOfValue(value interface{}) (int, error) {
  51  	v := reflect.ValueOf(value)
  52  	switch v.Kind() {
  53  	case reflect.String, reflect.Slice, reflect.Map, reflect.Array:
  54  		return v.Len(), nil
  55  	}
  56  	return 0, fmt.Errorf("cannot get the length of %v", v.Kind())
  57  }
  58  
  59  // ToInt converts the given value to an int64.
  60  // An error is returned for all incompatible types.
  61  func ToInt(value interface{}) (int64, error) {
  62  	v := reflect.ValueOf(value)
  63  	switch v.Kind() {
  64  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  65  		return v.Int(), nil
  66  	}
  67  	return 0, fmt.Errorf("cannot convert %v to int64", v.Kind())
  68  }
  69  
  70  // ToUint converts the given value to an uint64.
  71  // An error is returned for all incompatible types.
  72  func ToUint(value interface{}) (uint64, error) {
  73  	v := reflect.ValueOf(value)
  74  	switch v.Kind() {
  75  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  76  		return v.Uint(), nil
  77  	}
  78  	return 0, fmt.Errorf("cannot convert %v to uint64", v.Kind())
  79  }
  80  
  81  // ToFloat converts the given value to a float64.
  82  // An error is returned for all incompatible types.
  83  func ToFloat(value interface{}) (float64, error) {
  84  	v := reflect.ValueOf(value)
  85  	switch v.Kind() {
  86  	case reflect.Float32, reflect.Float64:
  87  		return v.Float(), nil
  88  	}
  89  	return 0, fmt.Errorf("cannot convert %v to float64", v.Kind())
  90  }
  91  
  92  // IsEmpty checks if a value is empty or not.
  93  // A value is considered empty if
  94  // - integer, float: zero
  95  // - bool: false
  96  // - string, array: len() == 0
  97  // - slice, map: nil or len() == 0
  98  // - interface, pointer: nil or the referenced value is empty
  99  func IsEmpty(value interface{}) bool {
 100  	v := reflect.ValueOf(value)
 101  	switch v.Kind() {
 102  	case reflect.String, reflect.Array, reflect.Map, reflect.Slice:
 103  		return v.Len() == 0
 104  	case reflect.Bool:
 105  		return !v.Bool()
 106  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 107  		return v.Int() == 0
 108  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 109  		return v.Uint() == 0
 110  	case reflect.Float32, reflect.Float64:
 111  		return v.Float() == 0
 112  	case reflect.Invalid:
 113  		return true
 114  	case reflect.Interface, reflect.Ptr:
 115  		if v.IsNil() {
 116  			return true
 117  		}
 118  		return IsEmpty(v.Elem().Interface())
 119  	case reflect.Struct:
 120  		v, ok := value.(time.Time)
 121  		if ok && v.IsZero() {
 122  			return true
 123  		}
 124  	}
 125  
 126  	return false
 127  }
 128  
 129  // Indirect returns the value that the given interface or pointer references to.
 130  // If the value implements driver.Valuer, it will deal with the value returned by
 131  // the Value() method instead. A boolean value is also returned to indicate if
 132  // the value is nil or not (only applicable to interface, pointer, map, and slice).
 133  // If the value is neither an interface nor a pointer, it will be returned back.
 134  func Indirect(value interface{}) (interface{}, bool) {
 135  	rv := reflect.ValueOf(value)
 136  	kind := rv.Kind()
 137  	switch kind {
 138  	case reflect.Invalid:
 139  		return nil, true
 140  	case reflect.Ptr, reflect.Interface:
 141  		if rv.IsNil() {
 142  			return nil, true
 143  		}
 144  		return Indirect(rv.Elem().Interface())
 145  	case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
 146  		if rv.IsNil() {
 147  			return nil, true
 148  		}
 149  	}
 150  
 151  	if rv.Type().Implements(valuerType) {
 152  		return indirectValuer(value.(driver.Valuer))
 153  	}
 154  
 155  	return value, false
 156  }
 157  
 158  func indirectValuer(valuer driver.Valuer) (interface{}, bool) {
 159  	if value, err := valuer.Value(); value != nil && err == nil {
 160  		return Indirect(value)
 161  	}
 162  	return nil, true
 163  }
 164