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