-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtype_compat.go
71 lines (59 loc) · 1.67 KB
/
type_compat.go
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
package sqld
import (
"reflect"
"time"
)
// AreTypesCompatible checks if valueType is suitable for fieldType.
// Returns true if they are compatible, false otherwise.
func AreTypesCompatible(fieldType, valueType reflect.Type) bool {
// nil check or interface check
if valueType == nil || fieldType == nil {
return false
}
// If the field type is an interface{} with no methods, it's basically "any"
if fieldType.Kind() == reflect.Interface && fieldType.NumMethod() == 0 {
return true
}
// Unwrap pointers
for fieldType.Kind() == reflect.Pointer {
fieldType = fieldType.Elem()
}
for valueType.Kind() == reflect.Pointer {
valueType = valueType.Elem()
}
// Exact match
if fieldType == valueType {
return true
}
// Check numeric
if IsNumericType(fieldType) && IsNumericType(valueType) {
return true
}
// Check strings
if fieldType.Kind() == reflect.String && valueType.Kind() == reflect.String {
return true
}
// Check time.Time
if IsTimeType(fieldType) && IsTimeType(valueType) {
return true
}
// Check bool
if fieldType.Kind() == reflect.Bool && valueType.Kind() == reflect.Bool {
return true
}
return false
}
// IsNumericType returns true if the reflect.Type is one of the integer or float kinds.
func IsNumericType(t reflect.Type) bool {
switch t.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
return true
}
return false
}
// IsTimeType returns true if the reflect.Type is time.Time or a known date/time type.
func IsTimeType(t reflect.Type) bool {
return t == reflect.TypeOf(time.Time{})
}