...

Source file src/github.com/go-redis/redis/command.go

Documentation: github.com/go-redis/redis

     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) 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  // Implements proto.MultiBulkParse
   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  // Implements proto.MultiBulkParse
   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  	// `SET key value NX` returns nil when key already exists. But
   535  	// `SETNX key value` returns bool (0/1). So convert nil to bool.
   536  	// TODO: is this okay?
   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  // Implements proto.MultiBulkParse
   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  // Implements proto.MultiBulkParse
   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  // Implements proto.MultiBulkParse
   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  // Implements proto.MultiBulkParse
   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  // Implements proto.MultiBulkParse
   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  // Implements proto.MultiBulkParse
   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  // Implements proto.MultiBulkParse
  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  // Implements proto.MultiBulkParse
  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  // Implements proto.MultiBulkParse
  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  // Implements proto.MultiBulkParse
  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  // Iterator creates a new ScanIterator.
  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  // Implements proto.MultiBulkParse
  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  // GeoLocation is used with GeoAdd to add geospatial location.
  1596  type GeoLocation struct {
  1597  	Name                      string
  1598  	Longitude, Latitude, Dist float64
  1599  	GeoHash                   int64
  1600  }
  1601  
  1602  // GeoRadiusQuery is used with GeoRadius to query geospatial index.
  1603  type GeoRadiusQuery struct {
  1604  	Radius float64
  1605  	// Can be m, km, ft, or mi. Default is km.
  1606  	Unit        string
  1607  	WithCoord   bool
  1608  	WithDist    bool
  1609  	WithGeoHash bool
  1610  	Count       int
  1611  	// Can be ASC or DESC. Default is no sort order.
  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  // Implements proto.MultiBulkParse
  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