barometer: update DMA's vendoring packages
[barometer.git] / src / dma / vendor / github.com / go-redis / redis / command.go
1 package redis
2
3 import (
4         "fmt"
5         "net"
6         "strconv"
7         "strings"
8         "time"
9
10         "github.com/go-redis/redis/internal"
11         "github.com/go-redis/redis/internal/proto"
12 )
13
14 type Cmder interface {
15         Name() string
16         Args() []interface{}
17         stringArg(int) string
18
19         readReply(rd *proto.Reader) error
20         setErr(error)
21
22         readTimeout() *time.Duration
23
24         Err() error
25 }
26
27 func setCmdsErr(cmds []Cmder, e error) {
28         for _, cmd := range cmds {
29                 if cmd.Err() == nil {
30                         cmd.setErr(e)
31                 }
32         }
33 }
34
35 func cmdsFirstErr(cmds []Cmder) error {
36         for _, cmd := range cmds {
37                 if err := cmd.Err(); err != nil {
38                         return err
39                 }
40         }
41         return nil
42 }
43
44 func writeCmd(wr *proto.Writer, cmds ...Cmder) error {
45         for _, cmd := range cmds {
46                 err := wr.WriteArgs(cmd.Args())
47                 if err != nil {
48                         return err
49                 }
50         }
51         return nil
52 }
53
54 func cmdString(cmd Cmder, val interface{}) string {
55         var ss []string
56         for _, arg := range cmd.Args() {
57                 ss = append(ss, fmt.Sprint(arg))
58         }
59         s := strings.Join(ss, " ")
60         if err := cmd.Err(); err != nil {
61                 return s + ": " + err.Error()
62         }
63         if val != nil {
64                 switch vv := val.(type) {
65                 case []byte:
66                         return s + ": " + string(vv)
67                 default:
68                         return s + ": " + fmt.Sprint(val)
69                 }
70         }
71         return s
72
73 }
74
75 func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
76         switch cmd.Name() {
77         case "eval", "evalsha":
78                 if cmd.stringArg(2) != "0" {
79                         return 3
80                 }
81
82                 return 0
83         case "publish":
84                 return 1
85         }
86         if info == nil {
87                 return 0
88         }
89         return int(info.FirstKeyPos)
90 }
91
92 //------------------------------------------------------------------------------
93
94 type baseCmd struct {
95         _args []interface{}
96         err   error
97
98         _readTimeout *time.Duration
99 }
100
101 var _ Cmder = (*Cmd)(nil)
102
103 func (cmd *baseCmd) Err() error {
104         return cmd.err
105 }
106
107 func (cmd *baseCmd) Args() []interface{} {
108         return cmd._args
109 }
110
111 func (cmd *baseCmd) stringArg(pos int) string {
112         if pos < 0 || pos >= len(cmd._args) {
113                 return ""
114         }
115         s, _ := cmd._args[pos].(string)
116         return s
117 }
118
119 func (cmd *baseCmd) Name() string {
120         if len(cmd._args) > 0 {
121                 // Cmd name must be lower cased.
122                 s := internal.ToLower(cmd.stringArg(0))
123                 cmd._args[0] = s
124                 return s
125         }
126         return ""
127 }
128
129 func (cmd *baseCmd) readTimeout() *time.Duration {
130         return cmd._readTimeout
131 }
132
133 func (cmd *baseCmd) setReadTimeout(d time.Duration) {
134         cmd._readTimeout = &d
135 }
136
137 func (cmd *baseCmd) setErr(e error) {
138         cmd.err = e
139 }
140
141 //------------------------------------------------------------------------------
142
143 type Cmd struct {
144         baseCmd
145
146         val interface{}
147 }
148
149 func NewCmd(args ...interface{}) *Cmd {
150         return &Cmd{
151                 baseCmd: baseCmd{_args: args},
152         }
153 }
154
155 func (cmd *Cmd) Val() interface{} {
156         return cmd.val
157 }
158
159 func (cmd *Cmd) Result() (interface{}, error) {
160         return cmd.val, cmd.err
161 }
162
163 func (cmd *Cmd) String() (string, error) {
164         if cmd.err != nil {
165                 return "", cmd.err
166         }
167         switch val := cmd.val.(type) {
168         case string:
169                 return val, nil
170         default:
171                 err := fmt.Errorf("redis: unexpected type=%T for String", val)
172                 return "", err
173         }
174 }
175
176 func (cmd *Cmd) Int() (int, error) {
177         if cmd.err != nil {
178                 return 0, cmd.err
179         }
180         switch val := cmd.val.(type) {
181         case int64:
182                 return int(val), nil
183         case string:
184                 return strconv.Atoi(val)
185         default:
186                 err := fmt.Errorf("redis: unexpected type=%T for Int", val)
187                 return 0, err
188         }
189 }
190
191 func (cmd *Cmd) Int64() (int64, error) {
192         if cmd.err != nil {
193                 return 0, cmd.err
194         }
195         switch val := cmd.val.(type) {
196         case int64:
197                 return val, nil
198         case string:
199                 return strconv.ParseInt(val, 10, 64)
200         default:
201                 err := fmt.Errorf("redis: unexpected type=%T for Int64", val)
202                 return 0, err
203         }
204 }
205
206 func (cmd *Cmd) Uint64() (uint64, error) {
207         if cmd.err != nil {
208                 return 0, cmd.err
209         }
210         switch val := cmd.val.(type) {
211         case int64:
212                 return uint64(val), nil
213         case string:
214                 return strconv.ParseUint(val, 10, 64)
215         default:
216                 err := fmt.Errorf("redis: unexpected type=%T for Uint64", val)
217                 return 0, err
218         }
219 }
220
221 func (cmd *Cmd) Float64() (float64, error) {
222         if cmd.err != nil {
223                 return 0, cmd.err
224         }
225         switch val := cmd.val.(type) {
226         case int64:
227                 return float64(val), nil
228         case string:
229                 return strconv.ParseFloat(val, 64)
230         default:
231                 err := fmt.Errorf("redis: unexpected type=%T for Float64", val)
232                 return 0, err
233         }
234 }
235
236 func (cmd *Cmd) Bool() (bool, error) {
237         if cmd.err != nil {
238                 return false, cmd.err
239         }
240         switch val := cmd.val.(type) {
241         case int64:
242                 return val != 0, nil
243         case string:
244                 return strconv.ParseBool(val)
245         default:
246                 err := fmt.Errorf("redis: unexpected type=%T for Bool", val)
247                 return false, err
248         }
249 }
250
251 func (cmd *Cmd) readReply(rd *proto.Reader) error {
252         cmd.val, cmd.err = rd.ReadReply(sliceParser)
253         return cmd.err
254 }
255
256 // Implements proto.MultiBulkParse
257 func sliceParser(rd *proto.Reader, n int64) (interface{}, error) {
258         vals := make([]interface{}, 0, n)
259         for i := int64(0); i < n; i++ {
260                 v, err := rd.ReadReply(sliceParser)
261                 if err != nil {
262                         if err == Nil {
263                                 vals = append(vals, nil)
264                                 continue
265                         }
266                         if err, ok := err.(proto.RedisError); ok {
267                                 vals = append(vals, err)
268                                 continue
269                         }
270                         return nil, err
271                 }
272
273                 switch v := v.(type) {
274                 case string:
275                         vals = append(vals, v)
276                 default:
277                         vals = append(vals, v)
278                 }
279         }
280         return vals, nil
281 }
282
283 //------------------------------------------------------------------------------
284
285 type SliceCmd struct {
286         baseCmd
287
288         val []interface{}
289 }
290
291 var _ Cmder = (*SliceCmd)(nil)
292
293 func NewSliceCmd(args ...interface{}) *SliceCmd {
294         return &SliceCmd{
295                 baseCmd: baseCmd{_args: args},
296         }
297 }
298
299 func (cmd *SliceCmd) Val() []interface{} {
300         return cmd.val
301 }
302
303 func (cmd *SliceCmd) Result() ([]interface{}, error) {
304         return cmd.val, cmd.err
305 }
306
307 func (cmd *SliceCmd) String() string {
308         return cmdString(cmd, cmd.val)
309 }
310
311 func (cmd *SliceCmd) readReply(rd *proto.Reader) error {
312         var v interface{}
313         v, cmd.err = rd.ReadArrayReply(sliceParser)
314         if cmd.err != nil {
315                 return cmd.err
316         }
317         cmd.val = v.([]interface{})
318         return nil
319 }
320
321 //------------------------------------------------------------------------------
322
323 type StatusCmd struct {
324         baseCmd
325
326         val string
327 }
328
329 var _ Cmder = (*StatusCmd)(nil)
330
331 func NewStatusCmd(args ...interface{}) *StatusCmd {
332         return &StatusCmd{
333                 baseCmd: baseCmd{_args: args},
334         }
335 }
336
337 func (cmd *StatusCmd) Val() string {
338         return cmd.val
339 }
340
341 func (cmd *StatusCmd) Result() (string, error) {
342         return cmd.val, cmd.err
343 }
344
345 func (cmd *StatusCmd) String() string {
346         return cmdString(cmd, cmd.val)
347 }
348
349 func (cmd *StatusCmd) readReply(rd *proto.Reader) error {
350         cmd.val, cmd.err = rd.ReadString()
351         return cmd.err
352 }
353
354 //------------------------------------------------------------------------------
355
356 type IntCmd struct {
357         baseCmd
358
359         val int64
360 }
361
362 var _ Cmder = (*IntCmd)(nil)
363
364 func NewIntCmd(args ...interface{}) *IntCmd {
365         return &IntCmd{
366                 baseCmd: baseCmd{_args: args},
367         }
368 }
369
370 func (cmd *IntCmd) Val() int64 {
371         return cmd.val
372 }
373
374 func (cmd *IntCmd) Result() (int64, error) {
375         return cmd.val, cmd.err
376 }
377
378 func (cmd *IntCmd) String() string {
379         return cmdString(cmd, cmd.val)
380 }
381
382 func (cmd *IntCmd) readReply(rd *proto.Reader) error {
383         cmd.val, cmd.err = rd.ReadIntReply()
384         return cmd.err
385 }
386
387 //------------------------------------------------------------------------------
388
389 type DurationCmd struct {
390         baseCmd
391
392         val       time.Duration
393         precision time.Duration
394 }
395
396 var _ Cmder = (*DurationCmd)(nil)
397
398 func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd {
399         return &DurationCmd{
400                 baseCmd:   baseCmd{_args: args},
401                 precision: precision,
402         }
403 }
404
405 func (cmd *DurationCmd) Val() time.Duration {
406         return cmd.val
407 }
408
409 func (cmd *DurationCmd) Result() (time.Duration, error) {
410         return cmd.val, cmd.err
411 }
412
413 func (cmd *DurationCmd) String() string {
414         return cmdString(cmd, cmd.val)
415 }
416
417 func (cmd *DurationCmd) readReply(rd *proto.Reader) error {
418         var n int64
419         n, cmd.err = rd.ReadIntReply()
420         if cmd.err != nil {
421                 return cmd.err
422         }
423         cmd.val = time.Duration(n) * cmd.precision
424         return nil
425 }
426
427 //------------------------------------------------------------------------------
428
429 type TimeCmd struct {
430         baseCmd
431
432         val time.Time
433 }
434
435 var _ Cmder = (*TimeCmd)(nil)
436
437 func NewTimeCmd(args ...interface{}) *TimeCmd {
438         return &TimeCmd{
439                 baseCmd: baseCmd{_args: args},
440         }
441 }
442
443 func (cmd *TimeCmd) Val() time.Time {
444         return cmd.val
445 }
446
447 func (cmd *TimeCmd) Result() (time.Time, error) {
448         return cmd.val, cmd.err
449 }
450
451 func (cmd *TimeCmd) String() string {
452         return cmdString(cmd, cmd.val)
453 }
454
455 func (cmd *TimeCmd) readReply(rd *proto.Reader) error {
456         var v interface{}
457         v, cmd.err = rd.ReadArrayReply(timeParser)
458         if cmd.err != nil {
459                 return cmd.err
460         }
461         cmd.val = v.(time.Time)
462         return nil
463 }
464
465 // Implements proto.MultiBulkParse
466 func timeParser(rd *proto.Reader, n int64) (interface{}, error) {
467         if n != 2 {
468                 return nil, fmt.Errorf("got %d elements, expected 2", n)
469         }
470
471         sec, err := rd.ReadInt()
472         if err != nil {
473                 return nil, err
474         }
475
476         microsec, err := rd.ReadInt()
477         if err != nil {
478                 return nil, err
479         }
480
481         return time.Unix(sec, microsec*1000), nil
482 }
483
484 //------------------------------------------------------------------------------
485
486 type BoolCmd struct {
487         baseCmd
488
489         val bool
490 }
491
492 var _ Cmder = (*BoolCmd)(nil)
493
494 func NewBoolCmd(args ...interface{}) *BoolCmd {
495         return &BoolCmd{
496                 baseCmd: baseCmd{_args: args},
497         }
498 }
499
500 func (cmd *BoolCmd) Val() bool {
501         return cmd.val
502 }
503
504 func (cmd *BoolCmd) Result() (bool, error) {
505         return cmd.val, cmd.err
506 }
507
508 func (cmd *BoolCmd) String() string {
509         return cmdString(cmd, cmd.val)
510 }
511
512 func (cmd *BoolCmd) readReply(rd *proto.Reader) error {
513         var v interface{}
514         v, cmd.err = rd.ReadReply(nil)
515         // `SET key value NX` returns nil when key already exists. But
516         // `SETNX key value` returns bool (0/1). So convert nil to bool.
517         // TODO: is this okay?
518         if cmd.err == Nil {
519                 cmd.val = false
520                 cmd.err = nil
521                 return nil
522         }
523         if cmd.err != nil {
524                 return cmd.err
525         }
526         switch v := v.(type) {
527         case int64:
528                 cmd.val = v == 1
529                 return nil
530         case string:
531                 cmd.val = v == "OK"
532                 return nil
533         default:
534                 cmd.err = fmt.Errorf("got %T, wanted int64 or string", v)
535                 return cmd.err
536         }
537 }
538
539 //------------------------------------------------------------------------------
540
541 type StringCmd struct {
542         baseCmd
543
544         val string
545 }
546
547 var _ Cmder = (*StringCmd)(nil)
548
549 func NewStringCmd(args ...interface{}) *StringCmd {
550         return &StringCmd{
551                 baseCmd: baseCmd{_args: args},
552         }
553 }
554
555 func (cmd *StringCmd) Val() string {
556         return cmd.val
557 }
558
559 func (cmd *StringCmd) Result() (string, error) {
560         return cmd.Val(), cmd.err
561 }
562
563 func (cmd *StringCmd) Bytes() ([]byte, error) {
564         return []byte(cmd.val), cmd.err
565 }
566
567 func (cmd *StringCmd) Int() (int, error) {
568         if cmd.err != nil {
569                 return 0, cmd.err
570         }
571         return strconv.Atoi(cmd.Val())
572 }
573
574 func (cmd *StringCmd) Int64() (int64, error) {
575         if cmd.err != nil {
576                 return 0, cmd.err
577         }
578         return strconv.ParseInt(cmd.Val(), 10, 64)
579 }
580
581 func (cmd *StringCmd) Uint64() (uint64, error) {
582         if cmd.err != nil {
583                 return 0, cmd.err
584         }
585         return strconv.ParseUint(cmd.Val(), 10, 64)
586 }
587
588 func (cmd *StringCmd) Float64() (float64, error) {
589         if cmd.err != nil {
590                 return 0, cmd.err
591         }
592         return strconv.ParseFloat(cmd.Val(), 64)
593 }
594
595 func (cmd *StringCmd) Scan(val interface{}) error {
596         if cmd.err != nil {
597                 return cmd.err
598         }
599         return proto.Scan([]byte(cmd.val), val)
600 }
601
602 func (cmd *StringCmd) String() string {
603         return cmdString(cmd, cmd.val)
604 }
605
606 func (cmd *StringCmd) readReply(rd *proto.Reader) error {
607         cmd.val, cmd.err = rd.ReadString()
608         return cmd.err
609 }
610
611 //------------------------------------------------------------------------------
612
613 type FloatCmd struct {
614         baseCmd
615
616         val float64
617 }
618
619 var _ Cmder = (*FloatCmd)(nil)
620
621 func NewFloatCmd(args ...interface{}) *FloatCmd {
622         return &FloatCmd{
623                 baseCmd: baseCmd{_args: args},
624         }
625 }
626
627 func (cmd *FloatCmd) Val() float64 {
628         return cmd.val
629 }
630
631 func (cmd *FloatCmd) Result() (float64, error) {
632         return cmd.Val(), cmd.Err()
633 }
634
635 func (cmd *FloatCmd) String() string {
636         return cmdString(cmd, cmd.val)
637 }
638
639 func (cmd *FloatCmd) readReply(rd *proto.Reader) error {
640         cmd.val, cmd.err = rd.ReadFloatReply()
641         return cmd.err
642 }
643
644 //------------------------------------------------------------------------------
645
646 type StringSliceCmd struct {
647         baseCmd
648
649         val []string
650 }
651
652 var _ Cmder = (*StringSliceCmd)(nil)
653
654 func NewStringSliceCmd(args ...interface{}) *StringSliceCmd {
655         return &StringSliceCmd{
656                 baseCmd: baseCmd{_args: args},
657         }
658 }
659
660 func (cmd *StringSliceCmd) Val() []string {
661         return cmd.val
662 }
663
664 func (cmd *StringSliceCmd) Result() ([]string, error) {
665         return cmd.Val(), cmd.Err()
666 }
667
668 func (cmd *StringSliceCmd) String() string {
669         return cmdString(cmd, cmd.val)
670 }
671
672 func (cmd *StringSliceCmd) ScanSlice(container interface{}) error {
673         return proto.ScanSlice(cmd.Val(), container)
674 }
675
676 func (cmd *StringSliceCmd) readReply(rd *proto.Reader) error {
677         var v interface{}
678         v, cmd.err = rd.ReadArrayReply(stringSliceParser)
679         if cmd.err != nil {
680                 return cmd.err
681         }
682         cmd.val = v.([]string)
683         return nil
684 }
685
686 // Implements proto.MultiBulkParse
687 func stringSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
688         ss := make([]string, 0, n)
689         for i := int64(0); i < n; i++ {
690                 s, err := rd.ReadString()
691                 if err == Nil {
692                         ss = append(ss, "")
693                 } else if err != nil {
694                         return nil, err
695                 } else {
696                         ss = append(ss, s)
697                 }
698         }
699         return ss, nil
700 }
701
702 //------------------------------------------------------------------------------
703
704 type BoolSliceCmd struct {
705         baseCmd
706
707         val []bool
708 }
709
710 var _ Cmder = (*BoolSliceCmd)(nil)
711
712 func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd {
713         return &BoolSliceCmd{
714                 baseCmd: baseCmd{_args: args},
715         }
716 }
717
718 func (cmd *BoolSliceCmd) Val() []bool {
719         return cmd.val
720 }
721
722 func (cmd *BoolSliceCmd) Result() ([]bool, error) {
723         return cmd.val, cmd.err
724 }
725
726 func (cmd *BoolSliceCmd) String() string {
727         return cmdString(cmd, cmd.val)
728 }
729
730 func (cmd *BoolSliceCmd) readReply(rd *proto.Reader) error {
731         var v interface{}
732         v, cmd.err = rd.ReadArrayReply(boolSliceParser)
733         if cmd.err != nil {
734                 return cmd.err
735         }
736         cmd.val = v.([]bool)
737         return nil
738 }
739
740 // Implements proto.MultiBulkParse
741 func boolSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
742         bools := make([]bool, 0, n)
743         for i := int64(0); i < n; i++ {
744                 n, err := rd.ReadIntReply()
745                 if err != nil {
746                         return nil, err
747                 }
748                 bools = append(bools, n == 1)
749         }
750         return bools, nil
751 }
752
753 //------------------------------------------------------------------------------
754
755 type StringStringMapCmd struct {
756         baseCmd
757
758         val map[string]string
759 }
760
761 var _ Cmder = (*StringStringMapCmd)(nil)
762
763 func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd {
764         return &StringStringMapCmd{
765                 baseCmd: baseCmd{_args: args},
766         }
767 }
768
769 func (cmd *StringStringMapCmd) Val() map[string]string {
770         return cmd.val
771 }
772
773 func (cmd *StringStringMapCmd) Result() (map[string]string, error) {
774         return cmd.val, cmd.err
775 }
776
777 func (cmd *StringStringMapCmd) String() string {
778         return cmdString(cmd, cmd.val)
779 }
780
781 func (cmd *StringStringMapCmd) readReply(rd *proto.Reader) error {
782         var v interface{}
783         v, cmd.err = rd.ReadArrayReply(stringStringMapParser)
784         if cmd.err != nil {
785                 return cmd.err
786         }
787         cmd.val = v.(map[string]string)
788         return nil
789 }
790
791 // Implements proto.MultiBulkParse
792 func stringStringMapParser(rd *proto.Reader, n int64) (interface{}, error) {
793         m := make(map[string]string, n/2)
794         for i := int64(0); i < n; i += 2 {
795                 key, err := rd.ReadString()
796                 if err != nil {
797                         return nil, err
798                 }
799
800                 value, err := rd.ReadString()
801                 if err != nil {
802                         return nil, err
803                 }
804
805                 m[key] = value
806         }
807         return m, nil
808 }
809
810 //------------------------------------------------------------------------------
811
812 type StringIntMapCmd struct {
813         baseCmd
814
815         val map[string]int64
816 }
817
818 var _ Cmder = (*StringIntMapCmd)(nil)
819
820 func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd {
821         return &StringIntMapCmd{
822                 baseCmd: baseCmd{_args: args},
823         }
824 }
825
826 func (cmd *StringIntMapCmd) Val() map[string]int64 {
827         return cmd.val
828 }
829
830 func (cmd *StringIntMapCmd) Result() (map[string]int64, error) {
831         return cmd.val, cmd.err
832 }
833
834 func (cmd *StringIntMapCmd) String() string {
835         return cmdString(cmd, cmd.val)
836 }
837
838 func (cmd *StringIntMapCmd) readReply(rd *proto.Reader) error {
839         var v interface{}
840         v, cmd.err = rd.ReadArrayReply(stringIntMapParser)
841         if cmd.err != nil {
842                 return cmd.err
843         }
844         cmd.val = v.(map[string]int64)
845         return nil
846 }
847
848 // Implements proto.MultiBulkParse
849 func stringIntMapParser(rd *proto.Reader, n int64) (interface{}, error) {
850         m := make(map[string]int64, n/2)
851         for i := int64(0); i < n; i += 2 {
852                 key, err := rd.ReadString()
853                 if err != nil {
854                         return nil, err
855                 }
856
857                 n, err := rd.ReadIntReply()
858                 if err != nil {
859                         return nil, err
860                 }
861
862                 m[key] = n
863         }
864         return m, nil
865 }
866
867 //------------------------------------------------------------------------------
868
869 type StringStructMapCmd struct {
870         baseCmd
871
872         val map[string]struct{}
873 }
874
875 var _ Cmder = (*StringStructMapCmd)(nil)
876
877 func NewStringStructMapCmd(args ...interface{}) *StringStructMapCmd {
878         return &StringStructMapCmd{
879                 baseCmd: baseCmd{_args: args},
880         }
881 }
882
883 func (cmd *StringStructMapCmd) Val() map[string]struct{} {
884         return cmd.val
885 }
886
887 func (cmd *StringStructMapCmd) Result() (map[string]struct{}, error) {
888         return cmd.val, cmd.err
889 }
890
891 func (cmd *StringStructMapCmd) String() string {
892         return cmdString(cmd, cmd.val)
893 }
894
895 func (cmd *StringStructMapCmd) readReply(rd *proto.Reader) error {
896         var v interface{}
897         v, cmd.err = rd.ReadArrayReply(stringStructMapParser)
898         if cmd.err != nil {
899                 return cmd.err
900         }
901         cmd.val = v.(map[string]struct{})
902         return nil
903 }
904
905 // Implements proto.MultiBulkParse
906 func stringStructMapParser(rd *proto.Reader, n int64) (interface{}, error) {
907         m := make(map[string]struct{}, n)
908         for i := int64(0); i < n; i++ {
909                 key, err := rd.ReadString()
910                 if err != nil {
911                         return nil, err
912                 }
913
914                 m[key] = struct{}{}
915         }
916         return m, nil
917 }
918
919 //------------------------------------------------------------------------------
920
921 type XMessage struct {
922         ID     string
923         Values map[string]interface{}
924 }
925
926 type XMessageSliceCmd struct {
927         baseCmd
928
929         val []XMessage
930 }
931
932 var _ Cmder = (*XMessageSliceCmd)(nil)
933
934 func NewXMessageSliceCmd(args ...interface{}) *XMessageSliceCmd {
935         return &XMessageSliceCmd{
936                 baseCmd: baseCmd{_args: args},
937         }
938 }
939
940 func (cmd *XMessageSliceCmd) Val() []XMessage {
941         return cmd.val
942 }
943
944 func (cmd *XMessageSliceCmd) Result() ([]XMessage, error) {
945         return cmd.val, cmd.err
946 }
947
948 func (cmd *XMessageSliceCmd) String() string {
949         return cmdString(cmd, cmd.val)
950 }
951
952 func (cmd *XMessageSliceCmd) readReply(rd *proto.Reader) error {
953         var v interface{}
954         v, cmd.err = rd.ReadArrayReply(xMessageSliceParser)
955         if cmd.err != nil {
956                 return cmd.err
957         }
958         cmd.val = v.([]XMessage)
959         return nil
960 }
961
962 // Implements proto.MultiBulkParse
963 func xMessageSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
964         msgs := make([]XMessage, 0, n)
965         for i := int64(0); i < n; i++ {
966                 _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
967                         id, err := rd.ReadString()
968                         if err != nil {
969                                 return nil, err
970                         }
971
972                         v, err := rd.ReadArrayReply(stringInterfaceMapParser)
973                         if err != nil {
974                                 return nil, err
975                         }
976
977                         msgs = append(msgs, XMessage{
978                                 ID:     id,
979                                 Values: v.(map[string]interface{}),
980                         })
981                         return nil, nil
982                 })
983                 if err != nil {
984                         return nil, err
985                 }
986         }
987         return msgs, nil
988 }
989
990 // Implements proto.MultiBulkParse
991 func stringInterfaceMapParser(rd *proto.Reader, n int64) (interface{}, error) {
992         m := make(map[string]interface{}, n/2)
993         for i := int64(0); i < n; i += 2 {
994                 key, err := rd.ReadString()
995                 if err != nil {
996                         return nil, err
997                 }
998
999                 value, err := rd.ReadString()
1000                 if err != nil {
1001                         return nil, err
1002                 }
1003
1004                 m[key] = value
1005         }
1006         return m, nil
1007 }
1008
1009 //------------------------------------------------------------------------------
1010
1011 type XStream struct {
1012         Stream   string
1013         Messages []XMessage
1014 }
1015
1016 type XStreamSliceCmd struct {
1017         baseCmd
1018
1019         val []XStream
1020 }
1021
1022 var _ Cmder = (*XStreamSliceCmd)(nil)
1023
1024 func NewXStreamSliceCmd(args ...interface{}) *XStreamSliceCmd {
1025         return &XStreamSliceCmd{
1026                 baseCmd: baseCmd{_args: args},
1027         }
1028 }
1029
1030 func (cmd *XStreamSliceCmd) Val() []XStream {
1031         return cmd.val
1032 }
1033
1034 func (cmd *XStreamSliceCmd) Result() ([]XStream, error) {
1035         return cmd.val, cmd.err
1036 }
1037
1038 func (cmd *XStreamSliceCmd) String() string {
1039         return cmdString(cmd, cmd.val)
1040 }
1041
1042 func (cmd *XStreamSliceCmd) readReply(rd *proto.Reader) error {
1043         var v interface{}
1044         v, cmd.err = rd.ReadArrayReply(xStreamSliceParser)
1045         if cmd.err != nil {
1046                 return cmd.err
1047         }
1048         cmd.val = v.([]XStream)
1049         return nil
1050 }
1051
1052 // Implements proto.MultiBulkParse
1053 func xStreamSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
1054         ret := make([]XStream, 0, n)
1055         for i := int64(0); i < n; i++ {
1056                 _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
1057                         if n != 2 {
1058                                 return nil, fmt.Errorf("got %d, wanted 2", n)
1059                         }
1060
1061                         stream, err := rd.ReadString()
1062                         if err != nil {
1063                                 return nil, err
1064                         }
1065
1066                         v, err := rd.ReadArrayReply(xMessageSliceParser)
1067                         if err != nil {
1068                                 return nil, err
1069                         }
1070
1071                         ret = append(ret, XStream{
1072                                 Stream:   stream,
1073                                 Messages: v.([]XMessage),
1074                         })
1075                         return nil, nil
1076                 })
1077                 if err != nil {
1078                         return nil, err
1079                 }
1080         }
1081         return ret, nil
1082 }
1083
1084 //------------------------------------------------------------------------------
1085
1086 type XPending struct {
1087         Count     int64
1088         Lower     string
1089         Higher    string
1090         Consumers map[string]int64
1091 }
1092
1093 type XPendingCmd struct {
1094         baseCmd
1095         val *XPending
1096 }
1097
1098 var _ Cmder = (*XPendingCmd)(nil)
1099
1100 func NewXPendingCmd(args ...interface{}) *XPendingCmd {
1101         return &XPendingCmd{
1102                 baseCmd: baseCmd{_args: args},
1103         }
1104 }
1105
1106 func (cmd *XPendingCmd) Val() *XPending {
1107         return cmd.val
1108 }
1109
1110 func (cmd *XPendingCmd) Result() (*XPending, error) {
1111         return cmd.val, cmd.err
1112 }
1113
1114 func (cmd *XPendingCmd) String() string {
1115         return cmdString(cmd, cmd.val)
1116 }
1117
1118 func (cmd *XPendingCmd) readReply(rd *proto.Reader) error {
1119         var info interface{}
1120         info, cmd.err = rd.ReadArrayReply(xPendingParser)
1121         if cmd.err != nil {
1122                 return cmd.err
1123         }
1124         cmd.val = info.(*XPending)
1125         return nil
1126 }
1127
1128 func xPendingParser(rd *proto.Reader, n int64) (interface{}, error) {
1129         if n != 4 {
1130                 return nil, fmt.Errorf("got %d, wanted 4", n)
1131         }
1132
1133         count, err := rd.ReadIntReply()
1134         if err != nil {
1135                 return nil, err
1136         }
1137
1138         lower, err := rd.ReadString()
1139         if err != nil && err != Nil {
1140                 return nil, err
1141         }
1142
1143         higher, err := rd.ReadString()
1144         if err != nil && err != Nil {
1145                 return nil, err
1146         }
1147
1148         pending := &XPending{
1149                 Count:  count,
1150                 Lower:  lower,
1151                 Higher: higher,
1152         }
1153         _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
1154                 for i := int64(0); i < n; i++ {
1155                         _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
1156                                 if n != 2 {
1157                                         return nil, fmt.Errorf("got %d, wanted 2", n)
1158                                 }
1159
1160                                 consumerName, err := rd.ReadString()
1161                                 if err != nil {
1162                                         return nil, err
1163                                 }
1164
1165                                 consumerPending, err := rd.ReadInt()
1166                                 if err != nil {
1167                                         return nil, err
1168                                 }
1169
1170                                 if pending.Consumers == nil {
1171                                         pending.Consumers = make(map[string]int64)
1172                                 }
1173                                 pending.Consumers[consumerName] = consumerPending
1174
1175                                 return nil, nil
1176                         })
1177                         if err != nil {
1178                                 return nil, err
1179                         }
1180                 }
1181                 return nil, nil
1182         })
1183         if err != nil && err != Nil {
1184                 return nil, err
1185         }
1186
1187         return pending, nil
1188 }
1189
1190 //------------------------------------------------------------------------------
1191
1192 type XPendingExt struct {
1193         Id         string
1194         Consumer   string
1195         Idle       time.Duration
1196         RetryCount int64
1197 }
1198
1199 type XPendingExtCmd struct {
1200         baseCmd
1201         val []XPendingExt
1202 }
1203
1204 var _ Cmder = (*XPendingExtCmd)(nil)
1205
1206 func NewXPendingExtCmd(args ...interface{}) *XPendingExtCmd {
1207         return &XPendingExtCmd{
1208                 baseCmd: baseCmd{_args: args},
1209         }
1210 }
1211
1212 func (cmd *XPendingExtCmd) Val() []XPendingExt {
1213         return cmd.val
1214 }
1215
1216 func (cmd *XPendingExtCmd) Result() ([]XPendingExt, error) {
1217         return cmd.val, cmd.err
1218 }
1219
1220 func (cmd *XPendingExtCmd) String() string {
1221         return cmdString(cmd, cmd.val)
1222 }
1223
1224 func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error {
1225         var info interface{}
1226         info, cmd.err = rd.ReadArrayReply(xPendingExtSliceParser)
1227         if cmd.err != nil {
1228                 return cmd.err
1229         }
1230         cmd.val = info.([]XPendingExt)
1231         return nil
1232 }
1233
1234 func xPendingExtSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
1235         ret := make([]XPendingExt, 0, n)
1236         for i := int64(0); i < n; i++ {
1237                 _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
1238                         if n != 4 {
1239                                 return nil, fmt.Errorf("got %d, wanted 4", n)
1240                         }
1241
1242                         id, err := rd.ReadString()
1243                         if err != nil {
1244                                 return nil, err
1245                         }
1246
1247                         consumer, err := rd.ReadString()
1248                         if err != nil && err != Nil {
1249                                 return nil, err
1250                         }
1251
1252                         idle, err := rd.ReadIntReply()
1253                         if err != nil && err != Nil {
1254                                 return nil, err
1255                         }
1256
1257                         retryCount, err := rd.ReadIntReply()
1258                         if err != nil && err != Nil {
1259                                 return nil, err
1260                         }
1261
1262                         ret = append(ret, XPendingExt{
1263                                 Id:         id,
1264                                 Consumer:   consumer,
1265                                 Idle:       time.Duration(idle) * time.Millisecond,
1266                                 RetryCount: retryCount,
1267                         })
1268                         return nil, nil
1269                 })
1270                 if err != nil {
1271                         return nil, err
1272                 }
1273         }
1274         return ret, nil
1275 }
1276
1277 //------------------------------------------------------------------------------
1278
1279 //------------------------------------------------------------------------------
1280
1281 type ZSliceCmd struct {
1282         baseCmd
1283
1284         val []Z
1285 }
1286
1287 var _ Cmder = (*ZSliceCmd)(nil)
1288
1289 func NewZSliceCmd(args ...interface{}) *ZSliceCmd {
1290         return &ZSliceCmd{
1291                 baseCmd: baseCmd{_args: args},
1292         }
1293 }
1294
1295 func (cmd *ZSliceCmd) Val() []Z {
1296         return cmd.val
1297 }
1298
1299 func (cmd *ZSliceCmd) Result() ([]Z, error) {
1300         return cmd.val, cmd.err
1301 }
1302
1303 func (cmd *ZSliceCmd) String() string {
1304         return cmdString(cmd, cmd.val)
1305 }
1306
1307 func (cmd *ZSliceCmd) readReply(rd *proto.Reader) error {
1308         var v interface{}
1309         v, cmd.err = rd.ReadArrayReply(zSliceParser)
1310         if cmd.err != nil {
1311                 return cmd.err
1312         }
1313         cmd.val = v.([]Z)
1314         return nil
1315 }
1316
1317 // Implements proto.MultiBulkParse
1318 func zSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
1319         zz := make([]Z, n/2)
1320         for i := int64(0); i < n; i += 2 {
1321                 var err error
1322
1323                 z := &zz[i/2]
1324
1325                 z.Member, err = rd.ReadString()
1326                 if err != nil {
1327                         return nil, err
1328                 }
1329
1330                 z.Score, err = rd.ReadFloatReply()
1331                 if err != nil {
1332                         return nil, err
1333                 }
1334         }
1335         return zz, nil
1336 }
1337
1338 //------------------------------------------------------------------------------
1339
1340 type ZWithKeyCmd struct {
1341         baseCmd
1342
1343         val ZWithKey
1344 }
1345
1346 var _ Cmder = (*ZWithKeyCmd)(nil)
1347
1348 func NewZWithKeyCmd(args ...interface{}) *ZWithKeyCmd {
1349         return &ZWithKeyCmd{
1350                 baseCmd: baseCmd{_args: args},
1351         }
1352 }
1353
1354 func (cmd *ZWithKeyCmd) Val() ZWithKey {
1355         return cmd.val
1356 }
1357
1358 func (cmd *ZWithKeyCmd) Result() (ZWithKey, error) {
1359         return cmd.Val(), cmd.Err()
1360 }
1361
1362 func (cmd *ZWithKeyCmd) String() string {
1363         return cmdString(cmd, cmd.val)
1364 }
1365
1366 func (cmd *ZWithKeyCmd) readReply(rd *proto.Reader) error {
1367         var v interface{}
1368         v, cmd.err = rd.ReadArrayReply(zWithKeyParser)
1369         if cmd.err != nil {
1370                 return cmd.err
1371         }
1372         cmd.val = v.(ZWithKey)
1373         return nil
1374 }
1375
1376 // Implements proto.MultiBulkParse
1377 func zWithKeyParser(rd *proto.Reader, n int64) (interface{}, error) {
1378         if n != 3 {
1379                 return nil, fmt.Errorf("got %d elements, expected 3", n)
1380         }
1381
1382         var z ZWithKey
1383         var err error
1384
1385         z.Key, err = rd.ReadString()
1386         if err != nil {
1387                 return nil, err
1388         }
1389         z.Member, err = rd.ReadString()
1390         if err != nil {
1391                 return nil, err
1392         }
1393         z.Score, err = rd.ReadFloatReply()
1394         if err != nil {
1395                 return nil, err
1396         }
1397         return z, nil
1398 }
1399
1400 //------------------------------------------------------------------------------
1401
1402 type ScanCmd struct {
1403         baseCmd
1404
1405         page   []string
1406         cursor uint64
1407
1408         process func(cmd Cmder) error
1409 }
1410
1411 var _ Cmder = (*ScanCmd)(nil)
1412
1413 func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
1414         return &ScanCmd{
1415                 baseCmd: baseCmd{_args: args},
1416                 process: process,
1417         }
1418 }
1419
1420 func (cmd *ScanCmd) Val() (keys []string, cursor uint64) {
1421         return cmd.page, cmd.cursor
1422 }
1423
1424 func (cmd *ScanCmd) Result() (keys []string, cursor uint64, err error) {
1425         return cmd.page, cmd.cursor, cmd.err
1426 }
1427
1428 func (cmd *ScanCmd) String() string {
1429         return cmdString(cmd, cmd.page)
1430 }
1431
1432 func (cmd *ScanCmd) readReply(rd *proto.Reader) error {
1433         cmd.page, cmd.cursor, cmd.err = rd.ReadScanReply()
1434         return cmd.err
1435 }
1436
1437 // Iterator creates a new ScanIterator.
1438 func (cmd *ScanCmd) Iterator() *ScanIterator {
1439         return &ScanIterator{
1440                 cmd: cmd,
1441         }
1442 }
1443
1444 //------------------------------------------------------------------------------
1445
1446 type ClusterNode struct {
1447         Id   string
1448         Addr string
1449 }
1450
1451 type ClusterSlot struct {
1452         Start int
1453         End   int
1454         Nodes []ClusterNode
1455 }
1456
1457 type ClusterSlotsCmd struct {
1458         baseCmd
1459
1460         val []ClusterSlot
1461 }
1462
1463 var _ Cmder = (*ClusterSlotsCmd)(nil)
1464
1465 func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd {
1466         return &ClusterSlotsCmd{
1467                 baseCmd: baseCmd{_args: args},
1468         }
1469 }
1470
1471 func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
1472         return cmd.val
1473 }
1474
1475 func (cmd *ClusterSlotsCmd) Result() ([]ClusterSlot, error) {
1476         return cmd.Val(), cmd.Err()
1477 }
1478
1479 func (cmd *ClusterSlotsCmd) String() string {
1480         return cmdString(cmd, cmd.val)
1481 }
1482
1483 func (cmd *ClusterSlotsCmd) readReply(rd *proto.Reader) error {
1484         var v interface{}
1485         v, cmd.err = rd.ReadArrayReply(clusterSlotsParser)
1486         if cmd.err != nil {
1487                 return cmd.err
1488         }
1489         cmd.val = v.([]ClusterSlot)
1490         return nil
1491 }
1492
1493 // Implements proto.MultiBulkParse
1494 func clusterSlotsParser(rd *proto.Reader, n int64) (interface{}, error) {
1495         slots := make([]ClusterSlot, n)
1496         for i := 0; i < len(slots); i++ {
1497                 n, err := rd.ReadArrayLen()
1498                 if err != nil {
1499                         return nil, err
1500                 }
1501                 if n < 2 {
1502                         err := fmt.Errorf("redis: got %d elements in cluster info, expected at least 2", n)
1503                         return nil, err
1504                 }
1505
1506                 start, err := rd.ReadIntReply()
1507                 if err != nil {
1508                         return nil, err
1509                 }
1510
1511                 end, err := rd.ReadIntReply()
1512                 if err != nil {
1513                         return nil, err
1514                 }
1515
1516                 nodes := make([]ClusterNode, n-2)
1517                 for j := 0; j < len(nodes); j++ {
1518                         n, err := rd.ReadArrayLen()
1519                         if err != nil {
1520                                 return nil, err
1521                         }
1522                         if n != 2 && n != 3 {
1523                                 err := fmt.Errorf("got %d elements in cluster info address, expected 2 or 3", n)
1524                                 return nil, err
1525                         }
1526
1527                         ip, err := rd.ReadString()
1528                         if err != nil {
1529                                 return nil, err
1530                         }
1531
1532                         port, err := rd.ReadString()
1533                         if err != nil {
1534                                 return nil, err
1535                         }
1536
1537                         nodes[j].Addr = net.JoinHostPort(ip, port)
1538
1539                         if n == 3 {
1540                                 id, err := rd.ReadString()
1541                                 if err != nil {
1542                                         return nil, err
1543                                 }
1544                                 nodes[j].Id = id
1545                         }
1546                 }
1547
1548                 slots[i] = ClusterSlot{
1549                         Start: int(start),
1550                         End:   int(end),
1551                         Nodes: nodes,
1552                 }
1553         }
1554         return slots, nil
1555 }
1556
1557 //------------------------------------------------------------------------------
1558
1559 // GeoLocation is used with GeoAdd to add geospatial location.
1560 type GeoLocation struct {
1561         Name                      string
1562         Longitude, Latitude, Dist float64
1563         GeoHash                   int64
1564 }
1565
1566 // GeoRadiusQuery is used with GeoRadius to query geospatial index.
1567 type GeoRadiusQuery struct {
1568         Radius float64
1569         // Can be m, km, ft, or mi. Default is km.
1570         Unit        string
1571         WithCoord   bool
1572         WithDist    bool
1573         WithGeoHash bool
1574         Count       int
1575         // Can be ASC or DESC. Default is no sort order.
1576         Sort      string
1577         Store     string
1578         StoreDist string
1579 }
1580
1581 type GeoLocationCmd struct {
1582         baseCmd
1583
1584         q         *GeoRadiusQuery
1585         locations []GeoLocation
1586 }
1587
1588 var _ Cmder = (*GeoLocationCmd)(nil)
1589
1590 func NewGeoLocationCmd(q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
1591         args = append(args, q.Radius)
1592         if q.Unit != "" {
1593                 args = append(args, q.Unit)
1594         } else {
1595                 args = append(args, "km")
1596         }
1597         if q.WithCoord {
1598                 args = append(args, "withcoord")
1599         }
1600         if q.WithDist {
1601                 args = append(args, "withdist")
1602         }
1603         if q.WithGeoHash {
1604                 args = append(args, "withhash")
1605         }
1606         if q.Count > 0 {
1607                 args = append(args, "count", q.Count)
1608         }
1609         if q.Sort != "" {
1610                 args = append(args, q.Sort)
1611         }
1612         if q.Store != "" {
1613                 args = append(args, "store")
1614                 args = append(args, q.Store)
1615         }
1616         if q.StoreDist != "" {
1617                 args = append(args, "storedist")
1618                 args = append(args, q.StoreDist)
1619         }
1620         return &GeoLocationCmd{
1621                 baseCmd: baseCmd{_args: args},
1622                 q:       q,
1623         }
1624 }
1625
1626 func (cmd *GeoLocationCmd) Val() []GeoLocation {
1627         return cmd.locations
1628 }
1629
1630 func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) {
1631         return cmd.locations, cmd.err
1632 }
1633
1634 func (cmd *GeoLocationCmd) String() string {
1635         return cmdString(cmd, cmd.locations)
1636 }
1637
1638 func (cmd *GeoLocationCmd) readReply(rd *proto.Reader) error {
1639         var v interface{}
1640         v, cmd.err = rd.ReadArrayReply(newGeoLocationSliceParser(cmd.q))
1641         if cmd.err != nil {
1642                 return cmd.err
1643         }
1644         cmd.locations = v.([]GeoLocation)
1645         return nil
1646 }
1647
1648 func newGeoLocationParser(q *GeoRadiusQuery) proto.MultiBulkParse {
1649         return func(rd *proto.Reader, n int64) (interface{}, error) {
1650                 var loc GeoLocation
1651                 var err error
1652
1653                 loc.Name, err = rd.ReadString()
1654                 if err != nil {
1655                         return nil, err
1656                 }
1657                 if q.WithDist {
1658                         loc.Dist, err = rd.ReadFloatReply()
1659                         if err != nil {
1660                                 return nil, err
1661                         }
1662                 }
1663                 if q.WithGeoHash {
1664                         loc.GeoHash, err = rd.ReadIntReply()
1665                         if err != nil {
1666                                 return nil, err
1667                         }
1668                 }
1669                 if q.WithCoord {
1670                         n, err := rd.ReadArrayLen()
1671                         if err != nil {
1672                                 return nil, err
1673                         }
1674                         if n != 2 {
1675                                 return nil, fmt.Errorf("got %d coordinates, expected 2", n)
1676                         }
1677
1678                         loc.Longitude, err = rd.ReadFloatReply()
1679                         if err != nil {
1680                                 return nil, err
1681                         }
1682                         loc.Latitude, err = rd.ReadFloatReply()
1683                         if err != nil {
1684                                 return nil, err
1685                         }
1686                 }
1687
1688                 return &loc, nil
1689         }
1690 }
1691
1692 func newGeoLocationSliceParser(q *GeoRadiusQuery) proto.MultiBulkParse {
1693         return func(rd *proto.Reader, n int64) (interface{}, error) {
1694                 locs := make([]GeoLocation, 0, n)
1695                 for i := int64(0); i < n; i++ {
1696                         v, err := rd.ReadReply(newGeoLocationParser(q))
1697                         if err != nil {
1698                                 return nil, err
1699                         }
1700                         switch vv := v.(type) {
1701                         case string:
1702                                 locs = append(locs, GeoLocation{
1703                                         Name: vv,
1704                                 })
1705                         case *GeoLocation:
1706                                 locs = append(locs, *vv)
1707                         default:
1708                                 return nil, fmt.Errorf("got %T, expected string or *GeoLocation", v)
1709                         }
1710                 }
1711                 return locs, nil
1712         }
1713 }
1714
1715 //------------------------------------------------------------------------------
1716
1717 type GeoPos struct {
1718         Longitude, Latitude float64
1719 }
1720
1721 type GeoPosCmd struct {
1722         baseCmd
1723
1724         positions []*GeoPos
1725 }
1726
1727 var _ Cmder = (*GeoPosCmd)(nil)
1728
1729 func NewGeoPosCmd(args ...interface{}) *GeoPosCmd {
1730         return &GeoPosCmd{
1731                 baseCmd: baseCmd{_args: args},
1732         }
1733 }
1734
1735 func (cmd *GeoPosCmd) Val() []*GeoPos {
1736         return cmd.positions
1737 }
1738
1739 func (cmd *GeoPosCmd) Result() ([]*GeoPos, error) {
1740         return cmd.Val(), cmd.Err()
1741 }
1742
1743 func (cmd *GeoPosCmd) String() string {
1744         return cmdString(cmd, cmd.positions)
1745 }
1746
1747 func (cmd *GeoPosCmd) readReply(rd *proto.Reader) error {
1748         var v interface{}
1749         v, cmd.err = rd.ReadArrayReply(geoPosSliceParser)
1750         if cmd.err != nil {
1751                 return cmd.err
1752         }
1753         cmd.positions = v.([]*GeoPos)
1754         return nil
1755 }
1756
1757 func geoPosSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
1758         positions := make([]*GeoPos, 0, n)
1759         for i := int64(0); i < n; i++ {
1760                 v, err := rd.ReadReply(geoPosParser)
1761                 if err != nil {
1762                         if err == Nil {
1763                                 positions = append(positions, nil)
1764                                 continue
1765                         }
1766                         return nil, err
1767                 }
1768                 switch v := v.(type) {
1769                 case *GeoPos:
1770                         positions = append(positions, v)
1771                 default:
1772                         return nil, fmt.Errorf("got %T, expected *GeoPos", v)
1773                 }
1774         }
1775         return positions, nil
1776 }
1777
1778 func geoPosParser(rd *proto.Reader, n int64) (interface{}, error) {
1779         var pos GeoPos
1780         var err error
1781
1782         pos.Longitude, err = rd.ReadFloatReply()
1783         if err != nil {
1784                 return nil, err
1785         }
1786
1787         pos.Latitude, err = rd.ReadFloatReply()
1788         if err != nil {
1789                 return nil, err
1790         }
1791
1792         return &pos, nil
1793 }
1794
1795 //------------------------------------------------------------------------------
1796
1797 type CommandInfo struct {
1798         Name        string
1799         Arity       int8
1800         Flags       []string
1801         FirstKeyPos int8
1802         LastKeyPos  int8
1803         StepCount   int8
1804         ReadOnly    bool
1805 }
1806
1807 type CommandsInfoCmd struct {
1808         baseCmd
1809
1810         val map[string]*CommandInfo
1811 }
1812
1813 var _ Cmder = (*CommandsInfoCmd)(nil)
1814
1815 func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd {
1816         return &CommandsInfoCmd{
1817                 baseCmd: baseCmd{_args: args},
1818         }
1819 }
1820
1821 func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
1822         return cmd.val
1823 }
1824
1825 func (cmd *CommandsInfoCmd) Result() (map[string]*CommandInfo, error) {
1826         return cmd.Val(), cmd.Err()
1827 }
1828
1829 func (cmd *CommandsInfoCmd) String() string {
1830         return cmdString(cmd, cmd.val)
1831 }
1832
1833 func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
1834         var v interface{}
1835         v, cmd.err = rd.ReadArrayReply(commandInfoSliceParser)
1836         if cmd.err != nil {
1837                 return cmd.err
1838         }
1839         cmd.val = v.(map[string]*CommandInfo)
1840         return nil
1841 }
1842
1843 // Implements proto.MultiBulkParse
1844 func commandInfoSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
1845         m := make(map[string]*CommandInfo, n)
1846         for i := int64(0); i < n; i++ {
1847                 v, err := rd.ReadReply(commandInfoParser)
1848                 if err != nil {
1849                         return nil, err
1850                 }
1851                 vv := v.(*CommandInfo)
1852                 m[vv.Name] = vv
1853
1854         }
1855         return m, nil
1856 }
1857
1858 func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) {
1859         var cmd CommandInfo
1860         var err error
1861
1862         if n != 6 {
1863                 return nil, fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 6", n)
1864         }
1865
1866         cmd.Name, err = rd.ReadString()
1867         if err != nil {
1868                 return nil, err
1869         }
1870
1871         arity, err := rd.ReadIntReply()
1872         if err != nil {
1873                 return nil, err
1874         }
1875         cmd.Arity = int8(arity)
1876
1877         flags, err := rd.ReadReply(stringSliceParser)
1878         if err != nil {
1879                 return nil, err
1880         }
1881         cmd.Flags = flags.([]string)
1882
1883         firstKeyPos, err := rd.ReadIntReply()
1884         if err != nil {
1885                 return nil, err
1886         }
1887         cmd.FirstKeyPos = int8(firstKeyPos)
1888
1889         lastKeyPos, err := rd.ReadIntReply()
1890         if err != nil {
1891                 return nil, err
1892         }
1893         cmd.LastKeyPos = int8(lastKeyPos)
1894
1895         stepCount, err := rd.ReadIntReply()
1896         if err != nil {
1897                 return nil, err
1898         }
1899         cmd.StepCount = int8(stepCount)
1900
1901         for _, flag := range cmd.Flags {
1902                 if flag == "readonly" {
1903                         cmd.ReadOnly = true
1904                         break
1905                 }
1906         }
1907
1908         return &cmd, nil
1909 }
1910
1911 //------------------------------------------------------------------------------
1912
1913 type cmdsInfoCache struct {
1914         fn func() (map[string]*CommandInfo, error)
1915
1916         once internal.Once
1917         cmds map[string]*CommandInfo
1918 }
1919
1920 func newCmdsInfoCache(fn func() (map[string]*CommandInfo, error)) *cmdsInfoCache {
1921         return &cmdsInfoCache{
1922                 fn: fn,
1923         }
1924 }
1925
1926 func (c *cmdsInfoCache) Get() (map[string]*CommandInfo, error) {
1927         err := c.once.Do(func() error {
1928                 cmds, err := c.fn()
1929                 if err != nil {
1930                         return err
1931                 }
1932                 c.cmds = cmds
1933                 return nil
1934         })
1935         return c.cmds, err
1936 }