1 package hscan
2
3 import (
4 "errors"
5 "fmt"
6 "reflect"
7 "strconv"
8 )
9
10
11 type decoderFunc func(reflect.Value, string) error
12
13
14
15 type Scanner interface {
16 ScanRedis(s string) error
17 }
18
19 var (
20
21 decoders = []decoderFunc{
22 reflect.Bool: decodeBool,
23 reflect.Int: decodeInt,
24 reflect.Int8: decodeInt8,
25 reflect.Int16: decodeInt16,
26 reflect.Int32: decodeInt32,
27 reflect.Int64: decodeInt64,
28 reflect.Uint: decodeUint,
29 reflect.Uint8: decodeUint8,
30 reflect.Uint16: decodeUint16,
31 reflect.Uint32: decodeUint32,
32 reflect.Uint64: decodeUint64,
33 reflect.Float32: decodeFloat32,
34 reflect.Float64: decodeFloat64,
35 reflect.Complex64: decodeUnsupported,
36 reflect.Complex128: decodeUnsupported,
37 reflect.Array: decodeUnsupported,
38 reflect.Chan: decodeUnsupported,
39 reflect.Func: decodeUnsupported,
40 reflect.Interface: decodeUnsupported,
41 reflect.Map: decodeUnsupported,
42 reflect.Ptr: decodeUnsupported,
43 reflect.Slice: decodeSlice,
44 reflect.String: decodeString,
45 reflect.Struct: decodeUnsupported,
46 reflect.UnsafePointer: decodeUnsupported,
47 }
48
49
50
51
52 globalStructMap = newStructMap()
53 )
54
55 func Struct(dst interface{}) (StructValue, error) {
56 v := reflect.ValueOf(dst)
57
58
59 if v.Kind() != reflect.Ptr || v.IsNil() {
60 return StructValue{}, fmt.Errorf("redis.Scan(non-pointer %T)", dst)
61 }
62
63 v = v.Elem()
64 if v.Kind() != reflect.Struct {
65 return StructValue{}, fmt.Errorf("redis.Scan(non-struct %T)", dst)
66 }
67
68 return StructValue{
69 spec: globalStructMap.get(v.Type()),
70 value: v,
71 }, nil
72 }
73
74
75
76 func Scan(dst interface{}, keys []interface{}, vals []interface{}) error {
77 if len(keys) != len(vals) {
78 return errors.New("args should have the same number of keys and vals")
79 }
80
81 strct, err := Struct(dst)
82 if err != nil {
83 return err
84 }
85
86
87 for i := 0; i < len(vals); i++ {
88 key, ok := keys[i].(string)
89 if !ok {
90 continue
91 }
92
93 val, ok := vals[i].(string)
94 if !ok {
95 continue
96 }
97
98 if err := strct.Scan(key, val); err != nil {
99 return err
100 }
101 }
102
103 return nil
104 }
105
106 func decodeBool(f reflect.Value, s string) error {
107 b, err := strconv.ParseBool(s)
108 if err != nil {
109 return err
110 }
111 f.SetBool(b)
112 return nil
113 }
114
115 func decodeInt8(f reflect.Value, s string) error {
116 return decodeNumber(f, s, 8)
117 }
118
119 func decodeInt16(f reflect.Value, s string) error {
120 return decodeNumber(f, s, 16)
121 }
122
123 func decodeInt32(f reflect.Value, s string) error {
124 return decodeNumber(f, s, 32)
125 }
126
127 func decodeInt64(f reflect.Value, s string) error {
128 return decodeNumber(f, s, 64)
129 }
130
131 func decodeInt(f reflect.Value, s string) error {
132 return decodeNumber(f, s, 0)
133 }
134
135 func decodeNumber(f reflect.Value, s string, bitSize int) error {
136 v, err := strconv.ParseInt(s, 10, bitSize)
137 if err != nil {
138 return err
139 }
140 f.SetInt(v)
141 return nil
142 }
143
144 func decodeUint8(f reflect.Value, s string) error {
145 return decodeUnsignedNumber(f, s, 8)
146 }
147
148 func decodeUint16(f reflect.Value, s string) error {
149 return decodeUnsignedNumber(f, s, 16)
150 }
151
152 func decodeUint32(f reflect.Value, s string) error {
153 return decodeUnsignedNumber(f, s, 32)
154 }
155
156 func decodeUint64(f reflect.Value, s string) error {
157 return decodeUnsignedNumber(f, s, 64)
158 }
159
160 func decodeUint(f reflect.Value, s string) error {
161 return decodeUnsignedNumber(f, s, 0)
162 }
163
164 func decodeUnsignedNumber(f reflect.Value, s string, bitSize int) error {
165 v, err := strconv.ParseUint(s, 10, bitSize)
166 if err != nil {
167 return err
168 }
169 f.SetUint(v)
170 return nil
171 }
172
173 func decodeFloat32(f reflect.Value, s string) error {
174 v, err := strconv.ParseFloat(s, 32)
175 if err != nil {
176 return err
177 }
178 f.SetFloat(v)
179 return nil
180 }
181
182
183 func decodeFloat64(f reflect.Value, s string) error {
184 v, err := strconv.ParseFloat(s, 64)
185 if err != nil {
186 return err
187 }
188 f.SetFloat(v)
189 return nil
190 }
191
192 func decodeString(f reflect.Value, s string) error {
193 f.SetString(s)
194 return nil
195 }
196
197 func decodeSlice(f reflect.Value, s string) error {
198
199 if f.Type().Elem().Kind() == reflect.Uint8 {
200 f.SetBytes([]byte(s))
201 }
202 return nil
203 }
204
205 func decodeUnsupported(v reflect.Value, s string) error {
206 return fmt.Errorf("redis.Scan(unsupported %s)", v.Type())
207 }
208
View as plain text