1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// 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
}
|