-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscanner.go
105 lines (86 loc) · 1.83 KB
/
scanner.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
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
package txmng
import (
"fmt"
"reflect"
)
type Scanner interface {
Scan(args ...interface{}) error
}
type values struct {
vals []interface{}
}
func Values(args ...interface{}) Scanner {
return values{vals: args}
}
func (v values) Scan(args ...interface{}) error {
l := len(v.vals)
if l != len(args) {
return fmt.Errorf("vals has length=%d, but args has %d", l, len(args))
}
for i := 0; i < l; i++ {
tArg := reflect.TypeOf(args[i])
if tArg == nil { // Scan(.., nil, ...)
continue
}
if tArg.Kind() != reflect.Ptr {
return fmt.Errorf("arg %d is not a pointer", i)
}
tArgVal := tArg.Elem()
tVal := reflect.TypeOf(v.vals[i])
if tVal == nil { // Values(.., nil, ...)
continue
}
if tArgVal != tVal {
return fmt.Errorf("types are different %s, %s at position %d", tArgVal.String(), tVal.String(), i)
}
if !v.isValidArgKind(tArgVal.Kind()) {
return fmt.Errorf("invalid arg kind %s at position %d", tArgVal.Kind().String(), i)
}
argVal := reflect.ValueOf(args[i]).Elem()
val := reflect.ValueOf(v.vals[i])
if !argVal.CanSet() {
return fmt.Errorf(
"can't set the value %s, %s at position %d",
argVal.Kind().String(),
argVal.String(),
i,
)
}
argVal.Set(val)
}
return nil
}
func (v values) isValidArgKind(arg reflect.Kind) bool {
switch arg {
case reflect.Bool,
reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64,
reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr,
reflect.Float32,
reflect.Float64,
reflect.Complex64,
reflect.Complex128,
reflect.Array,
reflect.Map,
reflect.Ptr,
reflect.Slice,
reflect.String,
reflect.Struct:
return true
// Unacceptable
case reflect.Chan,
reflect.Func,
reflect.Interface,
reflect.UnsafePointer,
reflect.Invalid:
}
return false
}