github.com/flower-corp/rosedb@v1.1.2-0.20230117132829-21dc4f7b319a/cmd/command.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/flower-corp/rosedb"
     7  	"github.com/flower-corp/rosedb/util"
     8  	"github.com/tidwall/redcon"
     9  	"path/filepath"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  )
    14  
    15  const (
    16  	resultOK       = "OK"
    17  	resultPong     = "PONG"
    18  	argsWithValues = "WITHVALUES"
    19  )
    20  
    21  var (
    22  	errSyntax            = errors.New("ERR syntax error ")
    23  	errValueIsInvalid    = errors.New("ERR value is not an integer or out of range")
    24  	errDBIndexOutOfRange = errors.New("ERR DB index is out of range")
    25  )
    26  
    27  func newWrongNumOfArgsError(cmd string) error {
    28  	return fmt.Errorf("ERR wrong number of arguments for '%s' command", cmd)
    29  }
    30  
    31  // +-------+--------+----------+------------+-----------+-------+---------+
    32  // |---------------------- server management commands --------------------|
    33  // +-------+--------+----------+------------+-----------+-------+---------+
    34  func info(cli *Client, args [][]byte) (interface{}, error) {
    35  	// todo
    36  	return "info", nil
    37  }
    38  
    39  // +-------+--------+----------+------------+-----------+-------+---------+
    40  // |-------------------- connection management commands ------------------|
    41  // +-------+--------+----------+------------+-----------+-------+---------+
    42  func selectDB(cli *Client, args [][]byte) (interface{}, error) {
    43  	cli.svr.mu.Lock()
    44  	defer cli.svr.mu.Unlock()
    45  
    46  	if len(args) != 1 {
    47  		return nil, newWrongNumOfArgsError("select")
    48  	}
    49  	n, err := strconv.Atoi(string(args[0]))
    50  	if err != nil {
    51  		return nil, errValueIsInvalid
    52  	}
    53  
    54  	if n < 0 || uint(n) >= cli.svr.opts.databases {
    55  		return nil, errDBIndexOutOfRange
    56  	}
    57  
    58  	db := cli.svr.dbs[n]
    59  	if db == nil {
    60  		path := filepath.Join(cli.svr.opts.dbPath, fmt.Sprintf(dbName, n))
    61  		opts := rosedb.DefaultOptions(path)
    62  		newdb, err := rosedb.Open(opts)
    63  		if err != nil {
    64  			return nil, err
    65  		}
    66  		db = newdb
    67  		cli.svr.dbs[n] = db
    68  	}
    69  	cli.db = db
    70  	return resultOK, nil
    71  }
    72  
    73  func ping(cli *Client, args [][]byte) (interface{}, error) {
    74  	if len(args) > 1 {
    75  		return nil, newWrongNumOfArgsError("ping")
    76  	}
    77  	var res = resultPong
    78  	if len(args) == 1 {
    79  		res = string(args[0])
    80  	}
    81  	return res, nil
    82  }
    83  
    84  // +-------+--------+----------+------------+-----------+-------+---------+
    85  // |-------------------------- generic commands --------------------------|
    86  // +-------+--------+----------+------------+-----------+-------+---------+
    87  func del(cli *Client, args [][]byte) (interface{}, error) {
    88  	if len(args) < 1 {
    89  		return nil, newWrongNumOfArgsError("del")
    90  	}
    91  	for _, key := range args {
    92  		if err := cli.db.Delete(key); err != nil {
    93  			return 0, err
    94  		}
    95  		// delete other ds. todo
    96  	}
    97  	return redcon.SimpleInt(1), nil
    98  }
    99  
   100  func keyType(cli *Client, args [][]byte) (interface{}, error) {
   101  	// todo
   102  	return "string", nil
   103  }
   104  
   105  // +-------+--------+----------+------------+-----------+-------+---------+
   106  // |-------------------------- String commands --------------------------|
   107  // +-------+--------+----------+------------+-----------+-------+---------+
   108  func set(cli *Client, args [][]byte) (interface{}, error) {
   109  	if len(args) < 2 {
   110  		return nil, newWrongNumOfArgsError("set")
   111  	}
   112  	key, value := args[0], args[1]
   113  
   114  	var setErr error
   115  	if len(args) > 2 {
   116  		ex := strings.ToLower(string(args[2]))
   117  		if ex != "ex" || len(args) != 4 {
   118  			return nil, errSyntax
   119  		}
   120  		second, err := strconv.Atoi(string(args[3]))
   121  		if err != nil {
   122  			return nil, errSyntax
   123  		}
   124  		setErr = cli.db.SetEX(key, value, time.Second*time.Duration(second))
   125  	} else {
   126  		setErr = cli.db.Set(key, value)
   127  	}
   128  	if setErr != nil {
   129  		return nil, setErr
   130  	}
   131  	return redcon.SimpleString(resultOK), nil
   132  }
   133  
   134  func setEX(cli *Client, args [][]byte) (interface{}, error) {
   135  	if len(args) != 3 {
   136  		return nil, newWrongNumOfArgsError("get")
   137  	}
   138  	key, seconds, value := args[0], args[1], args[2]
   139  	sec, err := strconv.Atoi(string(seconds))
   140  	if err != nil {
   141  		return nil, errValueIsInvalid
   142  	}
   143  	err = cli.db.SetEX(key, value, time.Second*time.Duration(sec))
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	return redcon.SimpleString(resultOK), nil
   148  }
   149  
   150  func setNX(cli *Client, args [][]byte) (interface{}, error) {
   151  	if len(args) != 2 {
   152  		return nil, newWrongNumOfArgsError("setnx")
   153  	}
   154  	key, value := args[0], args[1]
   155  	err := cli.db.SetNX(key, value)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	return redcon.SimpleString(resultOK), nil
   160  }
   161  
   162  func mSet(cli *Client, args [][]byte) (interface{}, error) {
   163  	if len(args) == 0 || len(args)%2 != 0 {
   164  		return nil, newWrongNumOfArgsError("mset")
   165  	}
   166  	err := cli.db.MSet(args...)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	return redcon.SimpleString(resultOK), nil
   171  }
   172  
   173  func mSetNX(cli *Client, args [][]byte) (interface{}, error) {
   174  	if len(args) == 0 || len(args)%2 != 0 {
   175  		return nil, newWrongNumOfArgsError("msetnx")
   176  	}
   177  	err := cli.db.MSetNX(args...)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	return redcon.SimpleString(resultOK), nil
   182  }
   183  
   184  func decr(cli *Client, args [][]byte) (interface{}, error) {
   185  	if len(args) != 1 {
   186  		return nil, newWrongNumOfArgsError("decr")
   187  	}
   188  	key := args[0]
   189  	return cli.db.Decr(key)
   190  }
   191  
   192  func decrBy(cli *Client, args [][]byte) (interface{}, error) {
   193  	if len(args) != 2 {
   194  		return nil, newWrongNumOfArgsError("decrby")
   195  	}
   196  	key, decrVal := args[0], args[1]
   197  	decrInt64Val, err := util.StrToInt64(string(decrVal))
   198  	if err != nil {
   199  		return nil, errValueIsInvalid
   200  	}
   201  	return cli.db.DecrBy(key, decrInt64Val)
   202  }
   203  
   204  func incr(cli *Client, args [][]byte) (interface{}, error) {
   205  	if len(args) != 1 {
   206  		return nil, newWrongNumOfArgsError("incr")
   207  	}
   208  	key := args[0]
   209  	return cli.db.Incr(key)
   210  }
   211  
   212  func incrBy(cli *Client, args [][]byte) (interface{}, error) {
   213  	if len(args) != 2 {
   214  		return nil, newWrongNumOfArgsError("incrby")
   215  	}
   216  	key, incrVal := args[0], args[1]
   217  	incrInt64Val, err := util.StrToInt64(string(incrVal))
   218  	if err != nil {
   219  		return nil, errValueIsInvalid
   220  	}
   221  	return cli.db.IncrBy(key, incrInt64Val)
   222  }
   223  
   224  func strLen(cli *Client, args [][]byte) (interface{}, error) {
   225  	if len(args) != 1 {
   226  		return nil, newWrongNumOfArgsError("strlen")
   227  	}
   228  	return cli.db.StrLen(args[0]), nil
   229  }
   230  
   231  func get(cli *Client, args [][]byte) (interface{}, error) {
   232  	if len(args) != 1 {
   233  		return nil, newWrongNumOfArgsError("get")
   234  	}
   235  	value, err := cli.db.Get(args[0])
   236  	if err != nil {
   237  		return nil, err
   238  	}
   239  	return value, nil
   240  }
   241  
   242  func mGet(cli *Client, args [][]byte) (interface{}, error) {
   243  	if len(args) < 1 {
   244  		return nil, newWrongNumOfArgsError("mget")
   245  	}
   246  	var keys [][]byte
   247  	for _, key := range args {
   248  		keys = append(keys, key)
   249  	}
   250  	values, err := cli.db.MGet(keys)
   251  	return values, err
   252  }
   253  
   254  func getRange(cli *Client, args [][]byte) (interface{}, error) {
   255  	if len(args) != 3 {
   256  		return nil, newWrongNumOfArgsError("getrange")
   257  	}
   258  	start, err := strconv.Atoi(string(args[1]))
   259  	if err != nil {
   260  		return nil, errValueIsInvalid
   261  	}
   262  
   263  	end, err := strconv.Atoi(string(args[2]))
   264  	if err != nil {
   265  		return nil, errValueIsInvalid
   266  	}
   267  
   268  	return cli.db.GetRange(args[0], start, end)
   269  }
   270  
   271  func appendStr(cli *Client, args [][]byte) (interface{}, error) {
   272  	if len(args) != 2 {
   273  		return nil, newWrongNumOfArgsError("append")
   274  	}
   275  	key, value := args[0], args[1]
   276  	err := cli.db.Append(key, value)
   277  	if err != nil {
   278  		return nil, err
   279  	}
   280  	return redcon.SimpleInt(cli.db.StrLen(key)), nil
   281  }
   282  
   283  func getDel(cli *Client, args [][]byte) (interface{}, error) {
   284  	if len(args) != 1 {
   285  		return nil, newWrongNumOfArgsError("getdel")
   286  	}
   287  	val, err := cli.db.GetDel(args[0])
   288  	return val, err
   289  }
   290  
   291  // +-------+--------+----------+------------+-----------+-------+---------+
   292  // |---------------------------- List commands ---------------------------|
   293  // +-------+--------+----------+------------+-----------+-------+---------+
   294  func lPush(cli *Client, args [][]byte) (interface{}, error) {
   295  	if len(args) < 2 {
   296  		return nil, newWrongNumOfArgsError("lpush")
   297  	}
   298  	key, value := args[0], args[1:]
   299  	err := cli.db.LPush(key, value...)
   300  	if err != nil {
   301  		return nil, err
   302  	}
   303  	return redcon.SimpleInt(cli.db.LLen(key)), nil
   304  }
   305  
   306  func lPushX(cli *Client, args [][]byte) (interface{}, error) {
   307  	if len(args) < 2 {
   308  		return nil, newWrongNumOfArgsError("lpush")
   309  	}
   310  	key, value := args[0], args[1:]
   311  	err := cli.db.LPushX(key, value...)
   312  	if err != nil {
   313  		return nil, err
   314  	}
   315  	return redcon.SimpleInt(cli.db.LLen(key)), nil
   316  }
   317  
   318  func rPush(cli *Client, args [][]byte) (interface{}, error) {
   319  	if len(args) < 2 {
   320  		return nil, newWrongNumOfArgsError("rpush")
   321  	}
   322  	key, value := args[0], args[1:]
   323  	err := cli.db.RPush(key, value...)
   324  	if err != nil {
   325  		return nil, err
   326  	}
   327  	return redcon.SimpleInt(cli.db.LLen(key)), nil
   328  }
   329  
   330  func rPushX(cli *Client, args [][]byte) (interface{}, error) {
   331  	if len(args) < 2 {
   332  		return nil, newWrongNumOfArgsError("rpush")
   333  	}
   334  	key, value := args[0], args[1:]
   335  	err := cli.db.RPushX(key, value...)
   336  	if err != nil {
   337  		return nil, err
   338  	}
   339  	return redcon.SimpleInt(cli.db.LLen(key)), nil
   340  }
   341  
   342  func lPop(cli *Client, args [][]byte) (interface{}, error) {
   343  	return popInternal(cli.db, args, true)
   344  }
   345  
   346  func rPop(cli *Client, args [][]byte) (interface{}, error) {
   347  	return popInternal(cli.db, args, false)
   348  }
   349  
   350  func lMove(cli *Client, args [][]byte) (interface{}, error) {
   351  	if len(args) != 4 {
   352  		return nil, newWrongNumOfArgsError("lmove")
   353  	}
   354  
   355  	srcKey, dstKey := args[0], args[1]
   356  	from, to := strings.ToLower(string(args[2])), strings.ToLower(string(args[3]))
   357  	var srcIsLeft, dstIsLeft bool
   358  
   359  	if from == "left" {
   360  		srcIsLeft = true
   361  	} else if from == "right" {
   362  		srcIsLeft = false
   363  	} else {
   364  		return nil, errSyntax
   365  	}
   366  
   367  	if to == "left" {
   368  		dstIsLeft = true
   369  	} else if to == "right" {
   370  		dstIsLeft = false
   371  	} else {
   372  		return nil, errSyntax
   373  	}
   374  
   375  	return cli.db.LMove(srcKey, dstKey, srcIsLeft, dstIsLeft)
   376  }
   377  
   378  func popInternal(db *rosedb.RoseDB, args [][]byte, isLeft bool) (interface{}, error) {
   379  	if len(args) < 1 {
   380  		return nil, newWrongNumOfArgsError("lpop")
   381  	}
   382  	key := args[0]
   383  	var count = 1
   384  	if len(args) == 2 {
   385  		c, err := strconv.Atoi(string(args[1]))
   386  		if err != nil {
   387  			return nil, errValueIsInvalid
   388  		}
   389  		count = c
   390  	}
   391  	total := db.LLen(key)
   392  	var values [][]byte
   393  	for i := 0; i < count && i < total; i++ {
   394  		var (
   395  			val []byte
   396  			err error
   397  		)
   398  		if isLeft {
   399  			val, err = db.LPop(key)
   400  		} else {
   401  			val, err = db.RPop(key)
   402  		}
   403  		if err != nil {
   404  			return nil, err
   405  		}
   406  		values = append(values, val)
   407  	}
   408  	return values, nil
   409  }
   410  
   411  func lLen(cli *Client, args [][]byte) (interface{}, error) {
   412  	if len(args) != 1 {
   413  		return nil, newWrongNumOfArgsError("llen")
   414  	}
   415  	key := args[0]
   416  	return redcon.SimpleInt(cli.db.LLen(key)), nil
   417  }
   418  
   419  func lIndex(cli *Client, args [][]byte) (interface{}, error) {
   420  	if len(args) != 2 {
   421  		return nil, newWrongNumOfArgsError("lindex")
   422  	}
   423  	key, index := args[0], args[1]
   424  	intIndex, err := strconv.Atoi(string(index))
   425  	if err != nil {
   426  		return nil, errValueIsInvalid
   427  	}
   428  	return cli.db.LIndex(key, intIndex)
   429  }
   430  
   431  func lSet(cli *Client, args [][]byte) (interface{}, error) {
   432  	if len(args) != 3 {
   433  		return nil, newWrongNumOfArgsError("lset")
   434  	}
   435  
   436  	key, index, value := args[0], args[1], args[2]
   437  	i, err := strconv.Atoi(string(index))
   438  	if err != nil {
   439  		return nil, errValueIsInvalid
   440  	}
   441  	err = cli.db.LSet(key, i, value)
   442  	if err != nil {
   443  		return nil, err
   444  	}
   445  	return redcon.SimpleString(resultOK), nil
   446  }
   447  
   448  func lRange(cli *Client, args [][]byte) (interface{}, error) {
   449  	if len(args) != 3 {
   450  		return nil, newWrongNumOfArgsError("lrange")
   451  	}
   452  
   453  	key, start, end := args[0], args[1], args[2]
   454  	s, err := strconv.Atoi(string(start))
   455  	if err != nil {
   456  		return nil, errValueIsInvalid
   457  	}
   458  
   459  	e, err := strconv.Atoi(string(end))
   460  	if err != nil {
   461  		return nil, errValueIsInvalid
   462  	}
   463  
   464  	return cli.db.LRange(key, s, e)
   465  }
   466  
   467  func lRem(cli *Client, args [][]byte) (interface{}, error) {
   468  	if len(args) != 3 {
   469  		return nil, newWrongNumOfArgsError("lrem")
   470  	}
   471  	key, element := args[0], args[2]
   472  	count, err := strconv.Atoi(string(args[1]))
   473  	if err != nil {
   474  		return nil, errValueIsInvalid
   475  	}
   476  	rem, err := cli.db.LRem(key, count, element)
   477  	return redcon.SimpleInt(rem), err
   478  }
   479  
   480  // +-------+--------+----------+------------+-----------+-------+---------+
   481  // |--------------------------- Hash commands ----------------------------|
   482  // +-------+--------+----------+------------+-----------+-------+---------+
   483  func hSet(cli *Client, args [][]byte) (interface{}, error) {
   484  	if len(args) < 2 || len(args)%2 == 0 {
   485  		return nil, newWrongNumOfArgsError("hset")
   486  	}
   487  	key := args[0]
   488  	var count int
   489  	for i := 1; i < len(args); i += 2 {
   490  		err := cli.db.HSet(key, args[i], args[i+1])
   491  		if err != nil {
   492  			return nil, err
   493  		}
   494  		count++
   495  	}
   496  	return redcon.SimpleInt(count), nil
   497  }
   498  
   499  func hSetNX(cli *Client, args [][]byte) (interface{}, error) {
   500  	if len(args) != 3 {
   501  		return nil, newWrongNumOfArgsError("hsetnx")
   502  	}
   503  
   504  	key, field, value := args[0], args[1], args[2]
   505  	ok, err := cli.db.HSetNX(key, field, value)
   506  	if err != nil {
   507  		return nil, err
   508  	}
   509  	if ok {
   510  		return redcon.SimpleInt(1), nil
   511  	}
   512  	return redcon.SimpleInt(0), nil
   513  }
   514  
   515  func hGet(cli *Client, args [][]byte) (interface{}, error) {
   516  	if len(args) != 2 {
   517  		return nil, newWrongNumOfArgsError("hget")
   518  	}
   519  	val, err := cli.db.HGet(args[0], args[1])
   520  	return val, err
   521  }
   522  
   523  func hmGet(cli *Client, args [][]byte) (interface{}, error) {
   524  	if len(args) < 2 {
   525  		return nil, newWrongNumOfArgsError("hmget")
   526  	}
   527  	return cli.db.HMGet(args[0], args[1:]...)
   528  }
   529  
   530  func hDel(cli *Client, args [][]byte) (interface{}, error) {
   531  	if len(args) < 2 {
   532  		return nil, newWrongNumOfArgsError("hdel")
   533  	}
   534  	count, err := cli.db.HDel(args[0], args[1:]...)
   535  	return redcon.SimpleInt(count), err
   536  }
   537  
   538  func hExists(cli *Client, args [][]byte) (interface{}, error) {
   539  	if len(args) != 2 {
   540  		return nil, newWrongNumOfArgsError("hexists")
   541  	}
   542  	ok, err := cli.db.HExists(args[0], args[1])
   543  	if err != nil {
   544  		return nil, err
   545  	}
   546  	if ok {
   547  		return redcon.SimpleInt(1), nil
   548  	}
   549  	return redcon.SimpleInt(0), nil
   550  }
   551  
   552  func hLen(cli *Client, args [][]byte) (interface{}, error) {
   553  	if len(args) != 1 {
   554  		return nil, newWrongNumOfArgsError("hlen")
   555  	}
   556  	return redcon.SimpleInt(cli.db.HLen(args[0])), nil
   557  }
   558  
   559  func hKeys(cli *Client, args [][]byte) (interface{}, error) {
   560  	if len(args) != 1 {
   561  		return nil, newWrongNumOfArgsError("hkeys")
   562  	}
   563  	return cli.db.HKeys(args[0])
   564  }
   565  
   566  func hVals(cli *Client, args [][]byte) (interface{}, error) {
   567  	if len(args) != 1 {
   568  		return nil, newWrongNumOfArgsError("hvals")
   569  	}
   570  	return cli.db.HVals(args[0])
   571  }
   572  
   573  func hGetAll(cli *Client, args [][]byte) (interface{}, error) {
   574  	if len(args) != 1 {
   575  		return nil, newWrongNumOfArgsError("hgetall")
   576  	}
   577  	return cli.db.HGetAll(args[0])
   578  }
   579  
   580  func hStrLen(cli *Client, args [][]byte) (interface{}, error) {
   581  	if len(args) != 2 {
   582  		return nil, newWrongNumOfArgsError("hstrlen")
   583  	}
   584  	return redcon.SimpleInt(cli.db.HStrLen(args[0], args[1])), nil
   585  }
   586  
   587  func hScan(cli *Client, args [][]byte) (interface{}, error) {
   588  	if len(args) != 4 {
   589  		return nil, newWrongNumOfArgsError("hscan")
   590  	}
   591  	pattern := string(args[2])
   592  	count, err := strconv.Atoi(string(args[3]))
   593  	if err != nil {
   594  		return nil, err
   595  	}
   596  	return cli.db.HScan(args[0], args[1], pattern, count)
   597  }
   598  
   599  func hIncrBy(cli *Client, args [][]byte) (interface{}, error) {
   600  	if len(args) != 3 {
   601  		return nil, newWrongNumOfArgsError("hincrby")
   602  	}
   603  	key, field, incrVal := args[0], args[1], args[2]
   604  	incrInt64Val, err := util.StrToInt64(string(incrVal))
   605  	if err != nil {
   606  		return nil, errValueIsInvalid
   607  	}
   608  	return cli.db.HIncrBy(key, field, incrInt64Val)
   609  }
   610  
   611  func hRandField(cli *Client, args [][]byte) (interface{}, error) {
   612  	if len(args) != 1 && len(args) != 2 && len(args) != 3 {
   613  		return nil, newWrongNumOfArgsError("hrandfield")
   614  	}
   615  	if len(args) == 1 {
   616  		keys, err := cli.db.HRandField(args[0], 1, false)
   617  		if err != nil {
   618  			return nil, err
   619  		}
   620  		if len(keys) == 1 {
   621  			return keys[0], nil
   622  		}
   623  		return keys, nil
   624  	}
   625  	count, err := strconv.Atoi(string(args[1]))
   626  	if err != nil {
   627  		return nil, errValueIsInvalid
   628  	}
   629  	withValues := false
   630  	if len(args) == 3 {
   631  		if !strings.EqualFold(string(args[2]), argsWithValues) {
   632  			return nil, errSyntax
   633  		}
   634  		withValues = true
   635  	}
   636  	return cli.db.HRandField(args[0], count, withValues)
   637  }
   638  
   639  // +-------+--------+----------+------------+-----------+-------+---------+
   640  // |---------------------------- Set commands ----------------------------|
   641  // +-------+--------+----------+------------+-----------+-------+---------+
   642  func sAdd(cli *Client, args [][]byte) (interface{}, error) {
   643  	if len(args) < 2 {
   644  		return nil, newWrongNumOfArgsError("sadd")
   645  	}
   646  	key := args[0]
   647  	var count int
   648  	for _, val := range args[1:] {
   649  		isMember := cli.db.SIsMember(key, val)
   650  		if !isMember {
   651  			err := cli.db.SAdd(key, val)
   652  			if err != nil {
   653  				return nil, err
   654  			}
   655  			count++
   656  		}
   657  	}
   658  	return redcon.SimpleInt(count), nil
   659  }
   660  
   661  func sRem(cli *Client, args [][]byte) (interface{}, error) {
   662  	if len(args) < 2 {
   663  		return nil, newWrongNumOfArgsError("srem")
   664  	}
   665  	key := args[0]
   666  	var count int
   667  	for _, val := range args[1:] {
   668  		isMember := cli.db.SIsMember(key, val)
   669  		if isMember {
   670  			err := cli.db.SRem(key, val)
   671  			if err != nil {
   672  				return nil, err
   673  			}
   674  			count++
   675  		}
   676  	}
   677  	return redcon.SimpleInt(count), nil
   678  }
   679  
   680  func sPop(cli *Client, args [][]byte) (interface{}, error) {
   681  	if len(args) != 2 {
   682  		return nil, newWrongNumOfArgsError("spop")
   683  	}
   684  	count, err := util.StrToUint(string(args[1]))
   685  	if err != nil {
   686  		return nil, errValueIsInvalid
   687  	}
   688  	return cli.db.SPop(args[0], uint(count))
   689  }
   690  
   691  func sIsMember(cli *Client, args [][]byte) (interface{}, error) {
   692  	if len(args) != 2 {
   693  		return nil, newWrongNumOfArgsError("sismember")
   694  	}
   695  	key, mem := args[0], args[1]
   696  	if ok := cli.db.SIsMember(key, mem); ok {
   697  		return redcon.SimpleInt(1), nil
   698  	} else {
   699  		return redcon.SimpleInt(0), nil
   700  	}
   701  }
   702  
   703  func sMisMember(cli *Client, args [][]byte) (interface{}, error) {
   704  	if len(args) < 2 {
   705  		return nil, newWrongNumOfArgsError("smismember")
   706  	}
   707  	res := make([]redcon.SimpleInt, 0)
   708  	key := args[0]
   709  	for _, mem := range args[1:] {
   710  		if ok := cli.db.SIsMember(key, mem); ok {
   711  			res = append(res, redcon.SimpleInt(1))
   712  		} else {
   713  			res = append(res, redcon.SimpleInt(0))
   714  		}
   715  	}
   716  	return res, nil
   717  }
   718  
   719  func sMembers(cli *Client, args [][]byte) (interface{}, error) {
   720  	if len(args) != 1 {
   721  		return nil, newWrongNumOfArgsError("smembers")
   722  	}
   723  	return cli.db.SMembers(args[0])
   724  }
   725  
   726  func sCard(cli *Client, args [][]byte) (interface{}, error) {
   727  	if len(args) != 1 {
   728  		return nil, newWrongNumOfArgsError("scard")
   729  	}
   730  	return redcon.SimpleInt(cli.db.SCard(args[0])), nil
   731  }
   732  
   733  func sDiff(cli *Client, args [][]byte) (interface{}, error) {
   734  	if len(args) == 0 {
   735  		return nil, newWrongNumOfArgsError("sdiff")
   736  	}
   737  	return cli.db.SDiff(args...)
   738  }
   739  
   740  func sDiffStore(cli *Client, args [][]byte) (interface{}, error) {
   741  	if len(args) < 2 {
   742  		return nil, newWrongNumOfArgsError("sdiffstore")
   743  	}
   744  	return cli.db.SDiffStore(args...)
   745  }
   746  
   747  func sUnion(cli *Client, args [][]byte) (interface{}, error) {
   748  	if len(args) == 0 {
   749  		return nil, newWrongNumOfArgsError("sunion")
   750  	}
   751  	return cli.db.SUnion(args...)
   752  }
   753  func sUnionStore(cli *Client, args [][]byte) (interface{}, error) {
   754  	if len(args) < 2 {
   755  		return nil, newWrongNumOfArgsError("sunionstore")
   756  	}
   757  	return cli.db.SUnionStore(args...)
   758  }
   759  func sInter(cli *Client, args [][]byte) (interface{}, error) {
   760  	if len(args) == 0 {
   761  		return nil, newWrongNumOfArgsError("sinter")
   762  	}
   763  	return cli.db.SInter(args...)
   764  }
   765  func sInterStore(cli *Client, args [][]byte) (interface{}, error) {
   766  	if len(args) < 2 {
   767  		return nil, newWrongNumOfArgsError("sinterstore")
   768  	}
   769  	return cli.db.SInterStore(args...)
   770  }
   771  
   772  // +-------+--------+----------+------------+-----------+-------+---------+
   773  // |------------------------- Sorted Set commands ------------------------|
   774  // +-------+--------+----------+------------+-----------+-------+---------+
   775  
   776  func zAdd(cli *Client, args [][]byte) (interface{}, error) {
   777  	if (len(args)-1)%2 != 0 {
   778  		return nil, newWrongNumOfArgsError("zadd")
   779  	}
   780  	key := args[0]
   781  	for i := 1; i < len(args); i += 2 {
   782  		score, err := util.StrToFloat64(string(args[i]))
   783  		if err != nil {
   784  			return nil, errValueIsInvalid
   785  		}
   786  		err = cli.db.ZAdd(key, score, args[i+1])
   787  		if err != nil {
   788  			return nil, err
   789  		}
   790  	}
   791  	return redcon.SimpleInt(len(args[1:]) / 2), nil
   792  }
   793  
   794  func zScore(cli *Client, args [][]byte) (interface{}, error) {
   795  	if len(args) != 2 {
   796  		return nil, newWrongNumOfArgsError("zscore")
   797  	}
   798  	_, score := cli.db.ZScore(args[0], args[1])
   799  	return score, nil
   800  }
   801  
   802  func zRem(cli *Client, args [][]byte) (interface{}, error) {
   803  	if len(args) < 2 {
   804  		return nil, newWrongNumOfArgsError("zrem")
   805  	}
   806  	key := args[0]
   807  	for _, member := range args[1:] {
   808  		err := cli.db.ZRem(key, member)
   809  		if err != nil {
   810  			return nil, err
   811  		}
   812  	}
   813  	return redcon.SimpleInt(len(args[1:]) / 2), nil
   814  }
   815  
   816  func zCard(cli *Client, args [][]byte) (interface{}, error) {
   817  	if len(args) != 1 {
   818  		return nil, newWrongNumOfArgsError("zcard")
   819  	}
   820  	return redcon.SimpleInt(cli.db.ZCard(args[0])), nil
   821  }
   822  
   823  func zRange(cli *Client, args [][]byte) (interface{}, error) {
   824  	if len(args) != 3 {
   825  		return nil, newWrongNumOfArgsError("zrange")
   826  	}
   827  	start, err := strconv.Atoi(string(args[1]))
   828  	if err != nil {
   829  		return nil, err
   830  	}
   831  	stop, err := strconv.Atoi(string(args[2]))
   832  	if err != nil {
   833  		return nil, err
   834  	}
   835  	return cli.db.ZRange(args[0], start, stop)
   836  }
   837  
   838  func zRevRange(cli *Client, args [][]byte) (interface{}, error) {
   839  	if len(args) != 3 {
   840  		return nil, newWrongNumOfArgsError("zrevrange")
   841  	}
   842  	start, err := strconv.Atoi(string(args[1]))
   843  	if err != nil {
   844  		return nil, err
   845  	}
   846  	stop, err := strconv.Atoi(string(args[2]))
   847  	if err != nil {
   848  		return nil, err
   849  	}
   850  	return cli.db.ZRevRange(args[0], start, stop)
   851  }
   852  
   853  func zRank(cli *Client, args [][]byte) (interface{}, error) {
   854  	if len(args) != 2 {
   855  		return nil, newWrongNumOfArgsError("zrank")
   856  	}
   857  	ok, rank := cli.db.ZRank(args[0], args[1])
   858  	if !ok {
   859  		return nil, nil
   860  	}
   861  	return rank, nil
   862  }
   863  
   864  func zRevRank(cli *Client, args [][]byte) (interface{}, error) {
   865  	if len(args) != 2 {
   866  		return nil, newWrongNumOfArgsError("zrevrank")
   867  	}
   868  	ok, rank := cli.db.ZRevRank(args[0], args[1])
   869  	if !ok {
   870  		return nil, nil
   871  	}
   872  	return rank, nil
   873  }