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