1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package redis
16
17 import (
18 "errors"
19 "fmt"
20 "reflect"
21 "strconv"
22 "strings"
23 "sync"
24 )
25
26 func ensureLen(d reflect.Value, n int) {
27 if n > d.Cap() {
28 d.Set(reflect.MakeSlice(d.Type(), n, n))
29 } else {
30 d.SetLen(n)
31 }
32 }
33
34 func cannotConvert(d reflect.Value, s interface{}) error {
35 var sname string
36 switch s.(type) {
37 case string:
38 sname = "Redis simple string"
39 case Error:
40 sname = "Redis error"
41 case int64:
42 sname = "Redis integer"
43 case []byte:
44 sname = "Redis bulk string"
45 case []interface{}:
46 sname = "Redis array"
47 default:
48 sname = reflect.TypeOf(s).String()
49 }
50 return fmt.Errorf("cannot convert from %s to %s", sname, d.Type())
51 }
52
53 func convertAssignBulkString(d reflect.Value, s []byte) (err error) {
54 switch d.Type().Kind() {
55 case reflect.Float32, reflect.Float64:
56 var x float64
57 x, err = strconv.ParseFloat(string(s), d.Type().Bits())
58 d.SetFloat(x)
59 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
60 var x int64
61 x, err = strconv.ParseInt(string(s), 10, d.Type().Bits())
62 d.SetInt(x)
63 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
64 var x uint64
65 x, err = strconv.ParseUint(string(s), 10, d.Type().Bits())
66 d.SetUint(x)
67 case reflect.Bool:
68 var x bool
69 x, err = strconv.ParseBool(string(s))
70 d.SetBool(x)
71 case reflect.String:
72 d.SetString(string(s))
73 case reflect.Slice:
74 if d.Type().Elem().Kind() != reflect.Uint8 {
75 err = cannotConvert(d, s)
76 } else {
77 d.SetBytes(s)
78 }
79 default:
80 err = cannotConvert(d, s)
81 }
82 return
83 }
84
85 func convertAssignInt(d reflect.Value, s int64) (err error) {
86 switch d.Type().Kind() {
87 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
88 d.SetInt(s)
89 if d.Int() != s {
90 err = strconv.ErrRange
91 d.SetInt(0)
92 }
93 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
94 if s < 0 {
95 err = strconv.ErrRange
96 } else {
97 x := uint64(s)
98 d.SetUint(x)
99 if d.Uint() != x {
100 err = strconv.ErrRange
101 d.SetUint(0)
102 }
103 }
104 case reflect.Bool:
105 d.SetBool(s != 0)
106 default:
107 err = cannotConvert(d, s)
108 }
109 return
110 }
111
112 func convertAssignValue(d reflect.Value, s interface{}) (err error) {
113 if d.Kind() != reflect.Ptr {
114 if d.CanAddr() {
115 d2 := d.Addr()
116 if d2.CanInterface() {
117 if scanner, ok := d2.Interface().(Scanner); ok {
118 return scanner.RedisScan(s)
119 }
120 }
121 }
122 } else if d.CanInterface() {
123
124 if d.IsNil() {
125 d.Set(reflect.New(d.Type().Elem()))
126 }
127 if scanner, ok := d.Interface().(Scanner); ok {
128 return scanner.RedisScan(s)
129 }
130 }
131
132 switch s := s.(type) {
133 case []byte:
134 err = convertAssignBulkString(d, s)
135 case int64:
136 err = convertAssignInt(d, s)
137 default:
138 err = cannotConvert(d, s)
139 }
140 return err
141 }
142
143 func convertAssignArray(d reflect.Value, s []interface{}) error {
144 if d.Type().Kind() != reflect.Slice {
145 return cannotConvert(d, s)
146 }
147 ensureLen(d, len(s))
148 for i := 0; i < len(s); i++ {
149 if err := convertAssignValue(d.Index(i), s[i]); err != nil {
150 return err
151 }
152 }
153 return nil
154 }
155
156 func convertAssign(d interface{}, s interface{}) (err error) {
157 if scanner, ok := d.(Scanner); ok {
158 return scanner.RedisScan(s)
159 }
160
161
162
163 switch s := s.(type) {
164 case nil:
165
166 case []byte:
167 switch d := d.(type) {
168 case *string:
169 *d = string(s)
170 case *int:
171 *d, err = strconv.Atoi(string(s))
172 case *bool:
173 *d, err = strconv.ParseBool(string(s))
174 case *[]byte:
175 *d = s
176 case *interface{}:
177 *d = s
178 case nil:
179
180 default:
181 if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
182 err = cannotConvert(d, s)
183 } else {
184 err = convertAssignBulkString(d.Elem(), s)
185 }
186 }
187 case int64:
188 switch d := d.(type) {
189 case *int:
190 x := int(s)
191 if int64(x) != s {
192 err = strconv.ErrRange
193 x = 0
194 }
195 *d = x
196 case *bool:
197 *d = s != 0
198 case *interface{}:
199 *d = s
200 case nil:
201
202 default:
203 if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
204 err = cannotConvert(d, s)
205 } else {
206 err = convertAssignInt(d.Elem(), s)
207 }
208 }
209 case string:
210 switch d := d.(type) {
211 case *string:
212 *d = s
213 case *interface{}:
214 *d = s
215 case nil:
216
217 default:
218 err = cannotConvert(reflect.ValueOf(d), s)
219 }
220 case []interface{}:
221 switch d := d.(type) {
222 case *[]interface{}:
223 *d = s
224 case *interface{}:
225 *d = s
226 case nil:
227
228 default:
229 if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
230 err = cannotConvert(d, s)
231 } else {
232 err = convertAssignArray(d.Elem(), s)
233 }
234 }
235 case Error:
236 err = s
237 default:
238 err = cannotConvert(reflect.ValueOf(d), s)
239 }
240 return
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257 func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
258 if len(src) < len(dest) {
259 return nil, errors.New("redigo.Scan: array short")
260 }
261 var err error
262 for i, d := range dest {
263 err = convertAssign(d, src[i])
264 if err != nil {
265 err = fmt.Errorf("redigo.Scan: cannot assign to dest %d: %v", i, err)
266 break
267 }
268 }
269 return src[len(dest):], err
270 }
271
272 type fieldSpec struct {
273 name string
274 index []int
275 omitEmpty bool
276 }
277
278 type structSpec struct {
279 m map[string]*fieldSpec
280 l []*fieldSpec
281 }
282
283 func (ss *structSpec) fieldSpec(name []byte) *fieldSpec {
284 return ss.m[string(name)]
285 }
286
287 func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *structSpec) {
288 for i := 0; i < t.NumField(); i++ {
289 f := t.Field(i)
290 switch {
291 case f.PkgPath != "" && !f.Anonymous:
292
293 case f.Anonymous:
294
295
296 if f.Type.Kind() == reflect.Struct {
297 compileStructSpec(f.Type, depth, append(index, i), ss)
298 }
299 default:
300 fs := &fieldSpec{name: f.Name}
301 tag := f.Tag.Get("redis")
302 p := strings.Split(tag, ",")
303 if len(p) > 0 {
304 if p[0] == "-" {
305 continue
306 }
307 if len(p[0]) > 0 {
308 fs.name = p[0]
309 }
310 for _, s := range p[1:] {
311 switch s {
312 case "omitempty":
313 fs.omitEmpty = true
314 default:
315 panic(fmt.Errorf("redigo: unknown field tag %s for type %s", s, t.Name()))
316 }
317 }
318 }
319 d, found := depth[fs.name]
320 if !found {
321 d = 1 << 30
322 }
323 switch {
324 case len(index) == d:
325
326 delete(ss.m, fs.name)
327 j := 0
328 for i := 0; i < len(ss.l); i++ {
329 if fs.name != ss.l[i].name {
330 ss.l[j] = ss.l[i]
331 j += 1
332 }
333 }
334 ss.l = ss.l[:j]
335 case len(index) < d:
336 fs.index = make([]int, len(index)+1)
337 copy(fs.index, index)
338 fs.index[len(index)] = i
339 depth[fs.name] = len(index)
340 ss.m[fs.name] = fs
341 ss.l = append(ss.l, fs)
342 }
343 }
344 }
345 }
346
347 var (
348 structSpecMutex sync.RWMutex
349 structSpecCache = make(map[reflect.Type]*structSpec)
350 defaultFieldSpec = &fieldSpec{}
351 )
352
353 func structSpecForType(t reflect.Type) *structSpec {
354
355 structSpecMutex.RLock()
356 ss, found := structSpecCache[t]
357 structSpecMutex.RUnlock()
358 if found {
359 return ss
360 }
361
362 structSpecMutex.Lock()
363 defer structSpecMutex.Unlock()
364 ss, found = structSpecCache[t]
365 if found {
366 return ss
367 }
368
369 ss = &structSpec{m: make(map[string]*fieldSpec)}
370 compileStructSpec(t, make(map[string]int), nil, ss)
371 structSpecCache[t] = ss
372 return ss
373 }
374
375 var errScanStructValue = errors.New("redigo.ScanStruct: value must be non-nil pointer to a struct")
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 func ScanStruct(src []interface{}, dest interface{}) error {
394 d := reflect.ValueOf(dest)
395 if d.Kind() != reflect.Ptr || d.IsNil() {
396 return errScanStructValue
397 }
398 d = d.Elem()
399 if d.Kind() != reflect.Struct {
400 return errScanStructValue
401 }
402 ss := structSpecForType(d.Type())
403
404 if len(src)%2 != 0 {
405 return errors.New("redigo.ScanStruct: number of values not a multiple of 2")
406 }
407
408 for i := 0; i < len(src); i += 2 {
409 s := src[i+1]
410 if s == nil {
411 continue
412 }
413 name, ok := src[i].([]byte)
414 if !ok {
415 return fmt.Errorf("redigo.ScanStruct: key %d not a bulk string value", i)
416 }
417 fs := ss.fieldSpec(name)
418 if fs == nil {
419 continue
420 }
421 if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
422 return fmt.Errorf("redigo.ScanStruct: cannot assign field %s: %v", fs.name, err)
423 }
424 }
425 return nil
426 }
427
428 var (
429 errScanSliceValue = errors.New("redigo.ScanSlice: dest must be non-nil pointer to a struct")
430 )
431
432
433
434
435
436
437
438 func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error {
439 d := reflect.ValueOf(dest)
440 if d.Kind() != reflect.Ptr || d.IsNil() {
441 return errScanSliceValue
442 }
443 d = d.Elem()
444 if d.Kind() != reflect.Slice {
445 return errScanSliceValue
446 }
447
448 isPtr := false
449 t := d.Type().Elem()
450 if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
451 isPtr = true
452 t = t.Elem()
453 }
454
455 if t.Kind() != reflect.Struct {
456 ensureLen(d, len(src))
457 for i, s := range src {
458 if s == nil {
459 continue
460 }
461 if err := convertAssignValue(d.Index(i), s); err != nil {
462 return fmt.Errorf("redigo.ScanSlice: cannot assign element %d: %v", i, err)
463 }
464 }
465 return nil
466 }
467
468 ss := structSpecForType(t)
469 fss := ss.l
470 if len(fieldNames) > 0 {
471 fss = make([]*fieldSpec, len(fieldNames))
472 for i, name := range fieldNames {
473 fss[i] = ss.m[name]
474 if fss[i] == nil {
475 return fmt.Errorf("redigo.ScanSlice: ScanSlice bad field name %s", name)
476 }
477 }
478 }
479
480 if len(fss) == 0 {
481 return errors.New("redigo.ScanSlice: no struct fields")
482 }
483
484 n := len(src) / len(fss)
485 if n*len(fss) != len(src) {
486 return errors.New("redigo.ScanSlice: length not a multiple of struct field count")
487 }
488
489 ensureLen(d, n)
490 for i := 0; i < n; i++ {
491 d := d.Index(i)
492 if isPtr {
493 if d.IsNil() {
494 d.Set(reflect.New(t))
495 }
496 d = d.Elem()
497 }
498 for j, fs := range fss {
499 s := src[i*len(fss)+j]
500 if s == nil {
501 continue
502 }
503 if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
504 return fmt.Errorf("redigo.ScanSlice: cannot assign element %d to field %s: %v", i*len(fss)+j, fs.name, err)
505 }
506 }
507 }
508 return nil
509 }
510
511
512 type Args []interface{}
513
514
515 func (args Args) Add(value ...interface{}) Args {
516 return append(args, value...)
517 }
518
519
520
521
522
523
524
525
526
527
528
529
530
531 func (args Args) AddFlat(v interface{}) Args {
532 rv := reflect.ValueOf(v)
533 switch rv.Kind() {
534 case reflect.Struct:
535 args = flattenStruct(args, rv)
536 case reflect.Slice:
537 for i := 0; i < rv.Len(); i++ {
538 args = append(args, rv.Index(i).Interface())
539 }
540 case reflect.Map:
541 for _, k := range rv.MapKeys() {
542 args = append(args, k.Interface(), rv.MapIndex(k).Interface())
543 }
544 case reflect.Ptr:
545 if rv.Type().Elem().Kind() == reflect.Struct {
546 if !rv.IsNil() {
547 args = flattenStruct(args, rv.Elem())
548 }
549 } else {
550 args = append(args, v)
551 }
552 default:
553 args = append(args, v)
554 }
555 return args
556 }
557
558 func flattenStruct(args Args, v reflect.Value) Args {
559 ss := structSpecForType(v.Type())
560 for _, fs := range ss.l {
561 fv := v.FieldByIndex(fs.index)
562 if fs.omitEmpty {
563 var empty = false
564 switch fv.Kind() {
565 case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
566 empty = fv.Len() == 0
567 case reflect.Bool:
568 empty = !fv.Bool()
569 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
570 empty = fv.Int() == 0
571 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
572 empty = fv.Uint() == 0
573 case reflect.Float32, reflect.Float64:
574 empty = fv.Float() == 0
575 case reflect.Interface, reflect.Ptr:
576 empty = fv.IsNil()
577 }
578 if empty {
579 continue
580 }
581 }
582 args = append(args, fs.name, fv.Interface())
583 }
584 return args
585 }
586
View as plain text