src: Add DMA localagent
[barometer.git] / src / dma / vendor / github.com / go-redis / redis / command.go
1 package redis
2
3 import (
4         "bytes"
5         "fmt"
6         "strconv"
7         "strings"
8         "time"
9
10         "github.com/go-redis/redis/internal"
11         "github.com/go-redis/redis/internal/pool"
12         "github.com/go-redis/redis/internal/proto"
13         "github.com/go-redis/redis/internal/util"
14 )
15
16 type Cmder interface {
17         Name() string
18         Args() []interface{}
19         stringArg(int) string
20
21         readReply(*pool.Conn) error
22         setErr(error)
23
24         readTimeout() *time.Duration
25
26         Err() error
27         fmt.Stringer
28 }
29
30 func setCmdsErr(cmds []Cmder, e error) {
31         for _, cmd := range cmds {
32                 if cmd.Err() == nil {
33                         cmd.setErr(e)
34                 }
35         }
36 }
37
38 func firstCmdsErr(cmds []Cmder) error {
39         for _, cmd := range cmds {
40                 if err := cmd.Err(); err != nil {
41                         return err
42                 }
43         }
44         return nil
45 }
46
47 func writeCmd(cn *pool.Conn, cmds ...Cmder) error {
48         cn.Wb.Reset()
49         for _, cmd := range cmds {
50                 if err := cn.Wb.Append(cmd.Args()); err != nil {
51                         return err
52                 }
53         }
54
55         _, err := cn.Write(cn.Wb.Bytes())
56         return err
57 }
58
59 func cmdString(cmd Cmder, val interface{}) string {
60         var ss []string
61         for _, arg := range cmd.Args() {
62                 ss = append(ss, fmt.Sprint(arg))
63         }
64         s := strings.Join(ss, " ")
65         if err := cmd.Err(); err != nil {
66                 return s + ": " + err.Error()
67         }
68         if val != nil {
69                 switch vv := val.(type) {
70                 case []byte:
71                         return s + ": " + string(vv)
72                 default:
73                         return s + ": " + fmt.Sprint(val)
74                 }
75         }
76         return s
77
78 }
79
80 func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
81         switch cmd.Name() {
82         case "eval", "evalsha":
83                 if cmd.stringArg(2) != "0" {
84                         return 3
85                 }
86
87                 return 0
88         case "publish":
89                 return 1
90         }
91         if info == nil {
92                 return 0
93         }
94         return int(info.FirstKeyPos)
95 }
96
97 //------------------------------------------------------------------------------
98
99 type baseCmd struct {
100         _args []interface{}
101         err   error
102
103         _readTimeout *time.Duration
104 }
105
106 var _ Cmder = (*Cmd)(nil)
107
108 func (cmd *baseCmd) Err() error {
109         return cmd.err
110 }
111
112 func (cmd *baseCmd) Args() []interface{} {
113         return cmd._args
114 }
115
116 func (cmd *baseCmd) stringArg(pos int) string {
117         if pos < 0 || pos >= len(cmd._args) {
118                 return ""
119         }
120         s, _ := cmd._args[pos].(string)
121         return s
122 }
123
124 func (cmd *baseCmd) Name() string {
125         if len(cmd._args) > 0 {
126                 // Cmd name must be lower cased.
127                 s := internal.ToLower(cmd.stringArg(0))
128                 cmd._args[0] = s
129                 return s
130         }
131         return ""
132 }
133
134 func (cmd *baseCmd) readTimeout() *time.Duration {
135         return cmd._readTimeout
136 }
137
138 func (cmd *baseCmd) setReadTimeout(d time.Duration) {
139         cmd._readTimeout = &d
140 }
141
142 func (cmd *baseCmd) setErr(e error) {
143         cmd.err = e
144 }
145
146 //------------------------------------------------------------------------------
147
148 type Cmd struct {
149         baseCmd
150
151         val interface{}
152 }
153
154 func NewCmd(args ...interface{}) *Cmd {
155         return &Cmd{
156                 baseCmd: baseCmd{_args: args},
157         }
158 }
159
160 func (cmd *Cmd) Val() interface{} {
161         return cmd.val
162 }
163
164 func (cmd *Cmd) Result() (interface{}, error) {
165         return cmd.val, cmd.err
166 }
167
168 func (cmd *Cmd) String() string {
169         return cmdString(cmd, cmd.val)
170 }
171
172 func (cmd *Cmd) readReply(cn *pool.Conn) error {
173         cmd.val, cmd.err = cn.Rd.ReadReply(sliceParser)
174         if cmd.err != nil {
175                 return cmd.err
176         }
177         if b, ok := cmd.val.([]byte); ok {
178                 // Bytes must be copied, because underlying memory is reused.
179                 cmd.val = string(b)
180         }
181         return nil
182 }
183
184 //------------------------------------------------------------------------------
185
186 type SliceCmd struct {
187         baseCmd
188
189         val []interface{}
190 }
191
192 var _ Cmder = (*SliceCmd)(nil)
193
194 func NewSliceCmd(args ...interface{}) *SliceCmd {
195         return &SliceCmd{
196                 baseCmd: baseCmd{_args: args},
197         }
198 }
199
200 func (cmd *SliceCmd) Val() []interface{} {
201         return cmd.val
202 }
203
204 func (cmd *SliceCmd) Result() ([]interface{}, error) {
205         return cmd.val, cmd.err
206 }
207
208 func (cmd *SliceCmd) String() string {
209         return cmdString(cmd, cmd.val)
210 }
211
212 func (cmd *SliceCmd) readReply(cn *pool.Conn) error {
213         var v interface{}
214         v, cmd.err = cn.Rd.ReadArrayReply(sliceParser)
215         if cmd.err != nil {
216                 return cmd.err
217         }
218         cmd.val = v.([]interface{})
219         return nil
220 }
221
222 //------------------------------------------------------------------------------
223
224 type StatusCmd struct {
225         baseCmd
226
227         val string
228 }
229
230 var _ Cmder = (*StatusCmd)(nil)
231
232 func NewStatusCmd(args ...interface{}) *StatusCmd {
233         return &StatusCmd{
234                 baseCmd: baseCmd{_args: args},
235         }
236 }
237
238 func (cmd *StatusCmd) Val() string {
239         return cmd.val
240 }
241
242 func (cmd *StatusCmd) Result() (string, error) {
243         return cmd.val, cmd.err
244 }
245
246 func (cmd *StatusCmd) String() string {
247         return cmdString(cmd, cmd.val)
248 }
249
250 func (cmd *StatusCmd) readReply(cn *pool.Conn) error {
251         cmd.val, cmd.err = cn.Rd.ReadStringReply()
252         return cmd.err
253 }
254
255 //------------------------------------------------------------------------------
256
257 type IntCmd struct {
258         baseCmd
259
260         val int64
261 }
262
263 var _ Cmder = (*IntCmd)(nil)
264
265 func NewIntCmd(args ...interface{}) *IntCmd {
266         return &IntCmd{
267                 baseCmd: baseCmd{_args: args},
268         }
269 }
270
271 func (cmd *IntCmd) Val() int64 {
272         return cmd.val
273 }
274
275 func (cmd *IntCmd) Result() (int64, error) {
276         return cmd.val, cmd.err
277 }
278
279 func (cmd *IntCmd) String() string {
280         return cmdString(cmd, cmd.val)
281 }
282
283 func (cmd *IntCmd) readReply(cn *pool.Conn) error {
284         cmd.val, cmd.err = cn.Rd.ReadIntReply()
285         return cmd.err
286 }
287
288 //------------------------------------------------------------------------------
289
290 type DurationCmd struct {
291         baseCmd
292
293         val       time.Duration
294         precision time.Duration
295 }
296
297 var _ Cmder = (*DurationCmd)(nil)
298
299 func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd {
300         return &DurationCmd{
301                 baseCmd:   baseCmd{_args: args},
302                 precision: precision,
303         }
304 }
305
306 func (cmd *DurationCmd) Val() time.Duration {
307         return cmd.val
308 }
309
310 func (cmd *DurationCmd) Result() (time.Duration, error) {
311         return cmd.val, cmd.err
312 }
313
314 func (cmd *DurationCmd) String() string {
315         return cmdString(cmd, cmd.val)
316 }
317
318 func (cmd *DurationCmd) readReply(cn *pool.Conn) error {
319         var n int64
320         n, cmd.err = cn.Rd.ReadIntReply()
321         if cmd.err != nil {
322                 return cmd.err
323         }
324         cmd.val = time.Duration(n) * cmd.precision
325         return nil
326 }
327
328 //------------------------------------------------------------------------------
329
330 type TimeCmd struct {
331         baseCmd
332
333         val time.Time
334 }
335
336 var _ Cmder = (*TimeCmd)(nil)
337
338 func NewTimeCmd(args ...interface{}) *TimeCmd {
339         return &TimeCmd{
340                 baseCmd: baseCmd{_args: args},
341         }
342 }
343
344 func (cmd *TimeCmd) Val() time.Time {
345         return cmd.val
346 }
347
348 func (cmd *TimeCmd) Result() (time.Time, error) {
349         return cmd.val, cmd.err
350 }
351
352 func (cmd *TimeCmd) String() string {
353         return cmdString(cmd, cmd.val)
354 }
355
356 func (cmd *TimeCmd) readReply(cn *pool.Conn) error {
357         var v interface{}
358         v, cmd.err = cn.Rd.ReadArrayReply(timeParser)
359         if cmd.err != nil {
360                 return cmd.err
361         }
362         cmd.val = v.(time.Time)
363         return nil
364 }
365
366 //------------------------------------------------------------------------------
367
368 type BoolCmd struct {
369         baseCmd
370
371         val bool
372 }
373
374 var _ Cmder = (*BoolCmd)(nil)
375
376 func NewBoolCmd(args ...interface{}) *BoolCmd {
377         return &BoolCmd{
378                 baseCmd: baseCmd{_args: args},
379         }
380 }
381
382 func (cmd *BoolCmd) Val() bool {
383         return cmd.val
384 }
385
386 func (cmd *BoolCmd) Result() (bool, error) {
387         return cmd.val, cmd.err
388 }
389
390 func (cmd *BoolCmd) String() string {
391         return cmdString(cmd, cmd.val)
392 }
393
394 var ok = []byte("OK")
395
396 func (cmd *BoolCmd) readReply(cn *pool.Conn) error {
397         var v interface{}
398         v, cmd.err = cn.Rd.ReadReply(nil)
399         // `SET key value NX` returns nil when key already exists. But
400         // `SETNX key value` returns bool (0/1). So convert nil to bool.
401         // TODO: is this okay?
402         if cmd.err == Nil {
403                 cmd.val = false
404                 cmd.err = nil
405                 return nil
406         }
407         if cmd.err != nil {
408                 return cmd.err
409         }
410         switch v := v.(type) {
411         case int64:
412                 cmd.val = v == 1
413                 return nil
414         case []byte:
415                 cmd.val = bytes.Equal(v, ok)
416                 return nil
417         default:
418                 cmd.err = fmt.Errorf("got %T, wanted int64 or string", v)
419                 return cmd.err
420         }
421 }
422
423 //------------------------------------------------------------------------------
424
425 type StringCmd struct {
426         baseCmd
427
428         val []byte
429 }
430
431 var _ Cmder = (*StringCmd)(nil)
432
433 func NewStringCmd(args ...interface{}) *StringCmd {
434         return &StringCmd{
435                 baseCmd: baseCmd{_args: args},
436         }
437 }
438
439 func (cmd *StringCmd) Val() string {
440         return util.BytesToString(cmd.val)
441 }
442
443 func (cmd *StringCmd) Result() (string, error) {
444         return cmd.Val(), cmd.err
445 }
446
447 func (cmd *StringCmd) Bytes() ([]byte, error) {
448         return cmd.val, cmd.err
449 }
450
451 func (cmd *StringCmd) Int64() (int64, error) {
452         if cmd.err != nil {
453                 return 0, cmd.err
454         }
455         return strconv.ParseInt(cmd.Val(), 10, 64)
456 }
457
458 func (cmd *StringCmd) Uint64() (uint64, error) {
459         if cmd.err != nil {
460                 return 0, cmd.err
461         }
462         return strconv.ParseUint(cmd.Val(), 10, 64)
463 }
464
465 func (cmd *StringCmd) Float64() (float64, error) {
466         if cmd.err != nil {
467                 return 0, cmd.err
468         }
469         return strconv.ParseFloat(cmd.Val(), 64)
470 }
471
472 func (cmd *StringCmd) Scan(val interface{}) error {
473         if cmd.err != nil {
474                 return cmd.err
475         }
476         return proto.Scan(cmd.val, val)
477 }
478
479 func (cmd *StringCmd) String() string {
480         return cmdString(cmd, cmd.val)
481 }
482
483 func (cmd *StringCmd) readReply(cn *pool.Conn) error {
484         cmd.val, cmd.err = cn.Rd.ReadBytesReply()
485         return cmd.err
486 }
487
488 //------------------------------------------------------------------------------
489
490 type FloatCmd struct {
491         baseCmd
492
493         val float64
494 }
495
496 var _ Cmder = (*FloatCmd)(nil)
497
498 func NewFloatCmd(args ...interface{}) *FloatCmd {
499         return &FloatCmd{
500                 baseCmd: baseCmd{_args: args},
501         }
502 }
503
504 func (cmd *FloatCmd) Val() float64 {
505         return cmd.val
506 }
507
508 func (cmd *FloatCmd) Result() (float64, error) {
509         return cmd.Val(), cmd.Err()
510 }
511
512 func (cmd *FloatCmd) String() string {
513         return cmdString(cmd, cmd.val)
514 }
515
516 func (cmd *FloatCmd) readReply(cn *pool.Conn) error {
517         cmd.val, cmd.err = cn.Rd.ReadFloatReply()
518         return cmd.err
519 }
520
521 //------------------------------------------------------------------------------
522
523 type StringSliceCmd struct {
524         baseCmd
525
526         val []string
527 }
528
529 var _ Cmder = (*StringSliceCmd)(nil)
530
531 func NewStringSliceCmd(args ...interface{}) *StringSliceCmd {
532         return &StringSliceCmd{
533                 baseCmd: baseCmd{_args: args},
534         }
535 }
536
537 func (cmd *StringSliceCmd) Val() []string {
538         return cmd.val
539 }
540
541 func (cmd *StringSliceCmd) Result() ([]string, error) {
542         return cmd.Val(), cmd.Err()
543 }
544
545 func (cmd *StringSliceCmd) String() string {
546         return cmdString(cmd, cmd.val)
547 }
548
549 func (cmd *StringSliceCmd) ScanSlice(container interface{}) error {
550         return proto.ScanSlice(cmd.Val(), container)
551 }
552
553 func (cmd *StringSliceCmd) readReply(cn *pool.Conn) error {
554         var v interface{}
555         v, cmd.err = cn.Rd.ReadArrayReply(stringSliceParser)
556         if cmd.err != nil {
557                 return cmd.err
558         }
559         cmd.val = v.([]string)
560         return nil
561 }
562
563 //------------------------------------------------------------------------------
564
565 type BoolSliceCmd struct {
566         baseCmd
567
568         val []bool
569 }
570
571 var _ Cmder = (*BoolSliceCmd)(nil)
572
573 func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd {
574         return &BoolSliceCmd{
575                 baseCmd: baseCmd{_args: args},
576         }
577 }
578
579 func (cmd *BoolSliceCmd) Val() []bool {
580         return cmd.val
581 }
582
583 func (cmd *BoolSliceCmd) Result() ([]bool, error) {
584         return cmd.val, cmd.err
585 }
586
587 func (cmd *BoolSliceCmd) String() string {
588         return cmdString(cmd, cmd.val)
589 }
590
591 func (cmd *BoolSliceCmd) readReply(cn *pool.Conn) error {
592         var v interface{}
593         v, cmd.err = cn.Rd.ReadArrayReply(boolSliceParser)
594         if cmd.err != nil {
595                 return cmd.err
596         }
597         cmd.val = v.([]bool)
598         return nil
599 }
600
601 //------------------------------------------------------------------------------
602
603 type StringStringMapCmd struct {
604         baseCmd
605
606         val map[string]string
607 }
608
609 var _ Cmder = (*StringStringMapCmd)(nil)
610
611 func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd {
612         return &StringStringMapCmd{
613                 baseCmd: baseCmd{_args: args},
614         }
615 }
616
617 func (cmd *StringStringMapCmd) Val() map[string]string {
618         return cmd.val
619 }
620
621 func (cmd *StringStringMapCmd) Result() (map[string]string, error) {
622         return cmd.val, cmd.err
623 }
624
625 func (cmd *StringStringMapCmd) String() string {
626         return cmdString(cmd, cmd.val)
627 }
628
629 func (cmd *StringStringMapCmd) readReply(cn *pool.Conn) error {
630         var v interface{}
631         v, cmd.err = cn.Rd.ReadArrayReply(stringStringMapParser)
632         if cmd.err != nil {
633                 return cmd.err
634         }
635         cmd.val = v.(map[string]string)
636         return nil
637 }
638
639 //------------------------------------------------------------------------------
640
641 type StringIntMapCmd struct {
642         baseCmd
643
644         val map[string]int64
645 }
646
647 var _ Cmder = (*StringIntMapCmd)(nil)
648
649 func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd {
650         return &StringIntMapCmd{
651                 baseCmd: baseCmd{_args: args},
652         }
653 }
654
655 func (cmd *StringIntMapCmd) Val() map[string]int64 {
656         return cmd.val
657 }
658
659 func (cmd *StringIntMapCmd) Result() (map[string]int64, error) {
660         return cmd.val, cmd.err
661 }
662
663 func (cmd *StringIntMapCmd) String() string {
664         return cmdString(cmd, cmd.val)
665 }
666
667 func (cmd *StringIntMapCmd) readReply(cn *pool.Conn) error {
668         var v interface{}
669         v, cmd.err = cn.Rd.ReadArrayReply(stringIntMapParser)
670         if cmd.err != nil {
671                 return cmd.err
672         }
673         cmd.val = v.(map[string]int64)
674         return nil
675 }
676
677 //------------------------------------------------------------------------------
678
679 type StringStructMapCmd struct {
680         baseCmd
681
682         val map[string]struct{}
683 }
684
685 var _ Cmder = (*StringStructMapCmd)(nil)
686
687 func NewStringStructMapCmd(args ...interface{}) *StringStructMapCmd {
688         return &StringStructMapCmd{
689                 baseCmd: baseCmd{_args: args},
690         }
691 }
692
693 func (cmd *StringStructMapCmd) Val() map[string]struct{} {
694         return cmd.val
695 }
696
697 func (cmd *StringStructMapCmd) Result() (map[string]struct{}, error) {
698         return cmd.val, cmd.err
699 }
700
701 func (cmd *StringStructMapCmd) String() string {
702         return cmdString(cmd, cmd.val)
703 }
704
705 func (cmd *StringStructMapCmd) readReply(cn *pool.Conn) error {
706         var v interface{}
707         v, cmd.err = cn.Rd.ReadArrayReply(stringStructMapParser)
708         if cmd.err != nil {
709                 return cmd.err
710         }
711         cmd.val = v.(map[string]struct{})
712         return nil
713 }
714
715 //------------------------------------------------------------------------------
716
717 type XStream struct {
718         Stream   string
719         Messages []*XMessage
720 }
721
722 type XMessage struct {
723         ID     string
724         Values map[string]interface{}
725 }
726
727 //------------------------------------------------------------------------------
728
729 type XStreamSliceCmd struct {
730         baseCmd
731
732         val []*XStream
733 }
734
735 var _ Cmder = (*XStreamSliceCmd)(nil)
736
737 func NewXStreamSliceCmd(args ...interface{}) *XStreamSliceCmd {
738         return &XStreamSliceCmd{
739                 baseCmd: baseCmd{_args: args},
740         }
741 }
742
743 func (cmd *XStreamSliceCmd) Val() []*XStream {
744         return cmd.val
745 }
746
747 func (cmd *XStreamSliceCmd) Result() ([]*XStream, error) {
748         return cmd.val, cmd.err
749 }
750
751 func (cmd *XStreamSliceCmd) String() string {
752         return cmdString(cmd, cmd.val)
753 }
754
755 func (cmd *XStreamSliceCmd) readReply(cn *pool.Conn) error {
756         var v interface{}
757         v, cmd.err = cn.Rd.ReadArrayReply(xStreamSliceParser)
758         if cmd.err != nil {
759                 return cmd.err
760         }
761         cmd.val = v.([]*XStream)
762         return nil
763 }
764
765 // Implements proto.MultiBulkParse
766 func xStreamSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
767         xx := make([]*XStream, n)
768         for i := int64(0); i < n; i++ {
769                 v, err := rd.ReadArrayReply(xStreamParser)
770                 if err != nil {
771                         return nil, err
772                 }
773                 xx[i] = v.(*XStream)
774         }
775         return xx, nil
776 }
777
778 // Implements proto.MultiBulkParse
779 func xStreamParser(rd *proto.Reader, n int64) (interface{}, error) {
780         if n != 2 {
781                 return nil, fmt.Errorf("got %d, wanted 2", n)
782         }
783
784         stream, err := rd.ReadStringReply()
785         if err != nil {
786                 return nil, err
787         }
788
789         v, err := rd.ReadArrayReply(xMessageSliceParser)
790         if err != nil {
791                 return nil, err
792         }
793
794         return &XStream{
795                 Stream:   stream,
796                 Messages: v.([]*XMessage),
797         }, nil
798 }
799
800 //------------------------------------------------------------------------------
801
802 type XMessageSliceCmd struct {
803         baseCmd
804
805         val []*XMessage
806 }
807
808 var _ Cmder = (*XMessageSliceCmd)(nil)
809
810 func NewXMessageSliceCmd(args ...interface{}) *XMessageSliceCmd {
811         return &XMessageSliceCmd{
812                 baseCmd: baseCmd{_args: args},
813         }
814 }
815
816 func (cmd *XMessageSliceCmd) Val() []*XMessage {
817         return cmd.val
818 }
819
820 func (cmd *XMessageSliceCmd) Result() ([]*XMessage, error) {
821         return cmd.val, cmd.err
822 }
823
824 func (cmd *XMessageSliceCmd) String() string {
825         return cmdString(cmd, cmd.val)
826 }
827
828 func (cmd *XMessageSliceCmd) readReply(cn *pool.Conn) error {
829         var v interface{}
830         v, cmd.err = cn.Rd.ReadArrayReply(xMessageSliceParser)
831         if cmd.err != nil {
832                 return cmd.err
833         }
834         cmd.val = v.([]*XMessage)
835         return nil
836 }
837
838 // Implements proto.MultiBulkParse
839 func xMessageSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
840         msgs := make([]*XMessage, n)
841         for i := int64(0); i < n; i++ {
842                 v, err := rd.ReadArrayReply(xMessageParser)
843                 if err != nil {
844                         return nil, err
845                 }
846                 msgs[i] = v.(*XMessage)
847         }
848         return msgs, nil
849 }
850
851 // Implements proto.MultiBulkParse
852 func xMessageParser(rd *proto.Reader, n int64) (interface{}, error) {
853         id, err := rd.ReadStringReply()
854         if err != nil {
855                 return nil, err
856         }
857
858         v, err := rd.ReadArrayReply(xKeyValueParser)
859         if err != nil {
860                 return nil, err
861         }
862
863         return &XMessage{
864                 ID:     id,
865                 Values: v.(map[string]interface{}),
866         }, nil
867 }
868
869 // Implements proto.MultiBulkParse
870 func xKeyValueParser(rd *proto.Reader, n int64) (interface{}, error) {
871         values := make(map[string]interface{}, n)
872         for i := int64(0); i < n; i += 2 {
873                 key, err := rd.ReadStringReply()
874                 if err != nil {
875                         return nil, err
876                 }
877
878                 value, err := rd.ReadStringReply()
879                 if err != nil {
880                         return nil, err
881                 }
882
883                 values[key] = value
884         }
885         return values, nil
886 }
887
888 //------------------------------------------------------------------------------
889
890 type ZSliceCmd struct {
891         baseCmd
892
893         val []Z
894 }
895
896 var _ Cmder = (*ZSliceCmd)(nil)
897
898 func NewZSliceCmd(args ...interface{}) *ZSliceCmd {
899         return &ZSliceCmd{
900                 baseCmd: baseCmd{_args: args},
901         }
902 }
903
904 func (cmd *ZSliceCmd) Val() []Z {
905         return cmd.val
906 }
907
908 func (cmd *ZSliceCmd) Result() ([]Z, error) {
909         return cmd.val, cmd.err
910 }
911
912 func (cmd *ZSliceCmd) String() string {
913         return cmdString(cmd, cmd.val)
914 }
915
916 func (cmd *ZSliceCmd) readReply(cn *pool.Conn) error {
917         var v interface{}
918         v, cmd.err = cn.Rd.ReadArrayReply(zSliceParser)
919         if cmd.err != nil {
920                 return cmd.err
921         }
922         cmd.val = v.([]Z)
923         return nil
924 }
925
926 //------------------------------------------------------------------------------
927
928 type ScanCmd struct {
929         baseCmd
930
931         page   []string
932         cursor uint64
933
934         process func(cmd Cmder) error
935 }
936
937 var _ Cmder = (*ScanCmd)(nil)
938
939 func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
940         return &ScanCmd{
941                 baseCmd: baseCmd{_args: args},
942                 process: process,
943         }
944 }
945
946 func (cmd *ScanCmd) Val() (keys []string, cursor uint64) {
947         return cmd.page, cmd.cursor
948 }
949
950 func (cmd *ScanCmd) Result() (keys []string, cursor uint64, err error) {
951         return cmd.page, cmd.cursor, cmd.err
952 }
953
954 func (cmd *ScanCmd) String() string {
955         return cmdString(cmd, cmd.page)
956 }
957
958 func (cmd *ScanCmd) readReply(cn *pool.Conn) error {
959         cmd.page, cmd.cursor, cmd.err = cn.Rd.ReadScanReply()
960         return cmd.err
961 }
962
963 // Iterator creates a new ScanIterator.
964 func (cmd *ScanCmd) Iterator() *ScanIterator {
965         return &ScanIterator{
966                 cmd: cmd,
967         }
968 }
969
970 //------------------------------------------------------------------------------
971
972 type ClusterNode struct {
973         Id   string
974         Addr string
975 }
976
977 type ClusterSlot struct {
978         Start int
979         End   int
980         Nodes []ClusterNode
981 }
982
983 type ClusterSlotsCmd struct {
984         baseCmd
985
986         val []ClusterSlot
987 }
988
989 var _ Cmder = (*ClusterSlotsCmd)(nil)
990
991 func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd {
992         return &ClusterSlotsCmd{
993                 baseCmd: baseCmd{_args: args},
994         }
995 }
996
997 func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
998         return cmd.val
999 }
1000
1001 func (cmd *ClusterSlotsCmd) Result() ([]ClusterSlot, error) {
1002         return cmd.Val(), cmd.Err()
1003 }
1004
1005 func (cmd *ClusterSlotsCmd) String() string {
1006         return cmdString(cmd, cmd.val)
1007 }
1008
1009 func (cmd *ClusterSlotsCmd) readReply(cn *pool.Conn) error {
1010         var v interface{}
1011         v, cmd.err = cn.Rd.ReadArrayReply(clusterSlotsParser)
1012         if cmd.err != nil {
1013                 return cmd.err
1014         }
1015         cmd.val = v.([]ClusterSlot)
1016         return nil
1017 }
1018
1019 //------------------------------------------------------------------------------
1020
1021 // GeoLocation is used with GeoAdd to add geospatial location.
1022 type GeoLocation struct {
1023         Name                      string
1024         Longitude, Latitude, Dist float64
1025         GeoHash                   int64
1026 }
1027
1028 // GeoRadiusQuery is used with GeoRadius to query geospatial index.
1029 type GeoRadiusQuery struct {
1030         Radius float64
1031         // Can be m, km, ft, or mi. Default is km.
1032         Unit        string
1033         WithCoord   bool
1034         WithDist    bool
1035         WithGeoHash bool
1036         Count       int
1037         // Can be ASC or DESC. Default is no sort order.
1038         Sort      string
1039         Store     string
1040         StoreDist string
1041 }
1042
1043 type GeoLocationCmd struct {
1044         baseCmd
1045
1046         q         *GeoRadiusQuery
1047         locations []GeoLocation
1048 }
1049
1050 var _ Cmder = (*GeoLocationCmd)(nil)
1051
1052 func NewGeoLocationCmd(q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
1053         args = append(args, q.Radius)
1054         if q.Unit != "" {
1055                 args = append(args, q.Unit)
1056         } else {
1057                 args = append(args, "km")
1058         }
1059         if q.WithCoord {
1060                 args = append(args, "withcoord")
1061         }
1062         if q.WithDist {
1063                 args = append(args, "withdist")
1064         }
1065         if q.WithGeoHash {
1066                 args = append(args, "withhash")
1067         }
1068         if q.Count > 0 {
1069                 args = append(args, "count", q.Count)
1070         }
1071         if q.Sort != "" {
1072                 args = append(args, q.Sort)
1073         }
1074         if q.Store != "" {
1075                 args = append(args, "store")
1076                 args = append(args, q.Store)
1077         }
1078         if q.StoreDist != "" {
1079                 args = append(args, "storedist")
1080                 args = append(args, q.StoreDist)
1081         }
1082         return &GeoLocationCmd{
1083                 baseCmd: baseCmd{_args: args},
1084                 q:       q,
1085         }
1086 }
1087
1088 func (cmd *GeoLocationCmd) Val() []GeoLocation {
1089         return cmd.locations
1090 }
1091
1092 func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) {
1093         return cmd.locations, cmd.err
1094 }
1095
1096 func (cmd *GeoLocationCmd) String() string {
1097         return cmdString(cmd, cmd.locations)
1098 }
1099
1100 func (cmd *GeoLocationCmd) readReply(cn *pool.Conn) error {
1101         var v interface{}
1102         v, cmd.err = cn.Rd.ReadArrayReply(newGeoLocationSliceParser(cmd.q))
1103         if cmd.err != nil {
1104                 return cmd.err
1105         }
1106         cmd.locations = v.([]GeoLocation)
1107         return nil
1108 }
1109
1110 //------------------------------------------------------------------------------
1111
1112 type GeoPos struct {
1113         Longitude, Latitude float64
1114 }
1115
1116 type GeoPosCmd struct {
1117         baseCmd
1118
1119         positions []*GeoPos
1120 }
1121
1122 var _ Cmder = (*GeoPosCmd)(nil)
1123
1124 func NewGeoPosCmd(args ...interface{}) *GeoPosCmd {
1125         return &GeoPosCmd{
1126                 baseCmd: baseCmd{_args: args},
1127         }
1128 }
1129
1130 func (cmd *GeoPosCmd) Val() []*GeoPos {
1131         return cmd.positions
1132 }
1133
1134 func (cmd *GeoPosCmd) Result() ([]*GeoPos, error) {
1135         return cmd.Val(), cmd.Err()
1136 }
1137
1138 func (cmd *GeoPosCmd) String() string {
1139         return cmdString(cmd, cmd.positions)
1140 }
1141
1142 func (cmd *GeoPosCmd) readReply(cn *pool.Conn) error {
1143         var v interface{}
1144         v, cmd.err = cn.Rd.ReadArrayReply(geoPosSliceParser)
1145         if cmd.err != nil {
1146                 return cmd.err
1147         }
1148         cmd.positions = v.([]*GeoPos)
1149         return nil
1150 }
1151
1152 //------------------------------------------------------------------------------
1153
1154 type CommandInfo struct {
1155         Name        string
1156         Arity       int8
1157         Flags       []string
1158         FirstKeyPos int8
1159         LastKeyPos  int8
1160         StepCount   int8
1161         ReadOnly    bool
1162 }
1163
1164 type CommandsInfoCmd struct {
1165         baseCmd
1166
1167         val map[string]*CommandInfo
1168 }
1169
1170 var _ Cmder = (*CommandsInfoCmd)(nil)
1171
1172 func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd {
1173         return &CommandsInfoCmd{
1174                 baseCmd: baseCmd{_args: args},
1175         }
1176 }
1177
1178 func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
1179         return cmd.val
1180 }
1181
1182 func (cmd *CommandsInfoCmd) Result() (map[string]*CommandInfo, error) {
1183         return cmd.Val(), cmd.Err()
1184 }
1185
1186 func (cmd *CommandsInfoCmd) String() string {
1187         return cmdString(cmd, cmd.val)
1188 }
1189
1190 func (cmd *CommandsInfoCmd) readReply(cn *pool.Conn) error {
1191         var v interface{}
1192         v, cmd.err = cn.Rd.ReadArrayReply(commandInfoSliceParser)
1193         if cmd.err != nil {
1194                 return cmd.err
1195         }
1196         cmd.val = v.(map[string]*CommandInfo)
1197         return nil
1198 }
1199
1200 //------------------------------------------------------------------------------
1201
1202 type cmdsInfoCache struct {
1203         fn func() (map[string]*CommandInfo, error)
1204
1205         once internal.Once
1206         cmds map[string]*CommandInfo
1207 }
1208
1209 func newCmdsInfoCache(fn func() (map[string]*CommandInfo, error)) *cmdsInfoCache {
1210         return &cmdsInfoCache{
1211                 fn: fn,
1212         }
1213 }
1214
1215 func (c *cmdsInfoCache) Get() (map[string]*CommandInfo, error) {
1216         err := c.once.Do(func() error {
1217                 cmds, err := c.fn()
1218                 if err != nil {
1219                         return err
1220                 }
1221                 c.cmds = cmds
1222                 return nil
1223         })
1224         return c.cmds, err
1225 }