package redis

import (
	
	
	
	
	
	
	
	

	
)

// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
// For example:
//
//	rdb.Set(ctx, key, value, redis.KeepTTL)
const KeepTTL = -1

func usePrecise( time.Duration) bool {
	return  < time.Second || %time.Second != 0
}

func formatMs( context.Context,  time.Duration) int64 {
	if  > 0 &&  < time.Millisecond {
		internal.Logger.Printf(
			,
			"specified duration is %s, but minimal supported value is %s - truncating to 1ms",
			, time.Millisecond,
		)
		return 1
	}
	return int64( / time.Millisecond)
}

func formatSec( context.Context,  time.Duration) int64 {
	if  > 0 &&  < time.Second {
		internal.Logger.Printf(
			,
			"specified duration is %s, but minimal supported value is %s - truncating to 1s",
			, time.Second,
		)
		return 1
	}
	return int64( / time.Second)
}

func appendArgs(,  []interface{}) []interface{} {
	if len() == 1 {
		return appendArg(, [0])
	}

	 = append(, ...)
	return 
}

func appendArg( []interface{},  interface{}) []interface{} {
	switch arg := .(type) {
	case []string:
		for ,  := range  {
			 = append(, )
		}
		return 
	case []interface{}:
		 = append(, ...)
		return 
	case map[string]interface{}:
		for ,  := range  {
			 = append(, , )
		}
		return 
	case map[string]string:
		for ,  := range  {
			 = append(, , )
		}
		return 
	case time.Time, time.Duration, encoding.BinaryMarshaler, net.IP:
		return append(, )
	default:
		// scan struct field
		 := reflect.ValueOf()
		if .Type().Kind() == reflect.Ptr {
			if .IsNil() {
				// error: arg is not a valid object
				return 
			}
			 = .Elem()
		}

		if .Type().Kind() == reflect.Struct {
			return appendStructField(, )
		}

		return append(, )
	}
}

// appendStructField appends the field and value held by the structure v to dst, and returns the appended dst.
func appendStructField( []interface{},  reflect.Value) []interface{} {
	 := .Type()
	for  := 0;  < .NumField(); ++ {
		 := .Field().Tag.Get("redis")
		if  == "" ||  == "-" {
			continue
		}
		 = strings.Split(, ",")[0]
		if  == "" {
			continue
		}

		 := .Field()
		if .CanInterface() {
			 = append(, , .Interface())
		}
	}

	return 
}

type Cmdable interface {
	Pipeline() Pipeliner
	Pipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error)

	TxPipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error)
	TxPipeline() Pipeliner

	Command(ctx context.Context) *CommandsInfoCmd
	CommandList(ctx context.Context, filter *FilterBy) *StringSliceCmd
	CommandGetKeys(ctx context.Context, commands ...interface{}) *StringSliceCmd
	CommandGetKeysAndFlags(ctx context.Context, commands ...interface{}) *KeyFlagsCmd
	ClientGetName(ctx context.Context) *StringCmd
	Echo(ctx context.Context, message interface{}) *StringCmd
	Ping(ctx context.Context) *StatusCmd
	Quit(ctx context.Context) *StatusCmd
	Del(ctx context.Context, keys ...string) *IntCmd
	Unlink(ctx context.Context, keys ...string) *IntCmd
	Dump(ctx context.Context, key string) *StringCmd
	Exists(ctx context.Context, keys ...string) *IntCmd
	Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
	ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
	ExpireTime(ctx context.Context, key string) *DurationCmd
	ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd
	ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd
	ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd
	ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd
	Keys(ctx context.Context, pattern string) *StringSliceCmd
	Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd
	Move(ctx context.Context, key string, db int) *BoolCmd
	ObjectRefCount(ctx context.Context, key string) *IntCmd
	ObjectEncoding(ctx context.Context, key string) *StringCmd
	ObjectIdleTime(ctx context.Context, key string) *DurationCmd
	Persist(ctx context.Context, key string) *BoolCmd
	PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
	PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
	PExpireTime(ctx context.Context, key string) *DurationCmd
	PTTL(ctx context.Context, key string) *DurationCmd
	RandomKey(ctx context.Context) *StringCmd
	Rename(ctx context.Context, key, newkey string) *StatusCmd
	RenameNX(ctx context.Context, key, newkey string) *BoolCmd
	Restore(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
	RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
	Sort(ctx context.Context, key string, sort *Sort) *StringSliceCmd
	SortRO(ctx context.Context, key string, sort *Sort) *StringSliceCmd
	SortStore(ctx context.Context, key, store string, sort *Sort) *IntCmd
	SortInterfaces(ctx context.Context, key string, sort *Sort) *SliceCmd
	Touch(ctx context.Context, keys ...string) *IntCmd
	TTL(ctx context.Context, key string) *DurationCmd
	Type(ctx context.Context, key string) *StatusCmd
	Append(ctx context.Context, key, value string) *IntCmd
	Decr(ctx context.Context, key string) *IntCmd
	DecrBy(ctx context.Context, key string, decrement int64) *IntCmd
	Get(ctx context.Context, key string) *StringCmd
	GetRange(ctx context.Context, key string, start, end int64) *StringCmd
	GetSet(ctx context.Context, key string, value interface{}) *StringCmd
	GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd
	GetDel(ctx context.Context, key string) *StringCmd
	Incr(ctx context.Context, key string) *IntCmd
	IncrBy(ctx context.Context, key string, value int64) *IntCmd
	IncrByFloat(ctx context.Context, key string, value float64) *FloatCmd
	MGet(ctx context.Context, keys ...string) *SliceCmd
	MSet(ctx context.Context, values ...interface{}) *StatusCmd
	MSetNX(ctx context.Context, values ...interface{}) *BoolCmd
	Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd
	SetArgs(ctx context.Context, key string, value interface{}, a SetArgs) *StatusCmd
	SetEx(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd
	SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd
	SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd
	SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd
	StrLen(ctx context.Context, key string) *IntCmd
	Copy(ctx context.Context, sourceKey string, destKey string, db int, replace bool) *IntCmd

	GetBit(ctx context.Context, key string, offset int64) *IntCmd
	SetBit(ctx context.Context, key string, offset int64, value int) *IntCmd
	BitCount(ctx context.Context, key string, bitCount *BitCount) *IntCmd
	BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd
	BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd
	BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd
	BitOpNot(ctx context.Context, destKey string, key string) *IntCmd
	BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd
	BitPosSpan(ctx context.Context, key string, bit int8, start, end int64, span string) *IntCmd
	BitField(ctx context.Context, key string, args ...interface{}) *IntSliceCmd

	Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd
	ScanType(ctx context.Context, cursor uint64, match string, count int64, keyType string) *ScanCmd
	SScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
	HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
	ZScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd

	HDel(ctx context.Context, key string, fields ...string) *IntCmd
	HExists(ctx context.Context, key, field string) *BoolCmd
	HGet(ctx context.Context, key, field string) *StringCmd
	HGetAll(ctx context.Context, key string) *MapStringStringCmd
	HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd
	HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd
	HKeys(ctx context.Context, key string) *StringSliceCmd
	HLen(ctx context.Context, key string) *IntCmd
	HMGet(ctx context.Context, key string, fields ...string) *SliceCmd
	HSet(ctx context.Context, key string, values ...interface{}) *IntCmd
	HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd
	HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd
	HVals(ctx context.Context, key string) *StringSliceCmd
	HRandField(ctx context.Context, key string, count int) *StringSliceCmd
	HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd

	BLPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd
	BLMPop(ctx context.Context, timeout time.Duration, direction string, count int64, keys ...string) *KeyValuesCmd
	BRPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd
	BRPopLPush(ctx context.Context, source, destination string, timeout time.Duration) *StringCmd
	LCS(ctx context.Context, q *LCSQuery) *LCSCmd
	LIndex(ctx context.Context, key string, index int64) *StringCmd
	LInsert(ctx context.Context, key, op string, pivot, value interface{}) *IntCmd
	LInsertBefore(ctx context.Context, key string, pivot, value interface{}) *IntCmd
	LInsertAfter(ctx context.Context, key string, pivot, value interface{}) *IntCmd
	LLen(ctx context.Context, key string) *IntCmd
	LMPop(ctx context.Context, direction string, count int64, keys ...string) *KeyValuesCmd
	LPop(ctx context.Context, key string) *StringCmd
	LPopCount(ctx context.Context, key string, count int) *StringSliceCmd
	LPos(ctx context.Context, key string, value string, args LPosArgs) *IntCmd
	LPosCount(ctx context.Context, key string, value string, count int64, args LPosArgs) *IntSliceCmd
	LPush(ctx context.Context, key string, values ...interface{}) *IntCmd
	LPushX(ctx context.Context, key string, values ...interface{}) *IntCmd
	LRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
	LRem(ctx context.Context, key string, count int64, value interface{}) *IntCmd
	LSet(ctx context.Context, key string, index int64, value interface{}) *StatusCmd
	LTrim(ctx context.Context, key string, start, stop int64) *StatusCmd
	RPop(ctx context.Context, key string) *StringCmd
	RPopCount(ctx context.Context, key string, count int) *StringSliceCmd
	RPopLPush(ctx context.Context, source, destination string) *StringCmd
	RPush(ctx context.Context, key string, values ...interface{}) *IntCmd
	RPushX(ctx context.Context, key string, values ...interface{}) *IntCmd
	LMove(ctx context.Context, source, destination, srcpos, destpos string) *StringCmd
	BLMove(ctx context.Context, source, destination, srcpos, destpos string, timeout time.Duration) *StringCmd

	SAdd(ctx context.Context, key string, members ...interface{}) *IntCmd
	SCard(ctx context.Context, key string) *IntCmd
	SDiff(ctx context.Context, keys ...string) *StringSliceCmd
	SDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd
	SInter(ctx context.Context, keys ...string) *StringSliceCmd
	SInterCard(ctx context.Context, limit int64, keys ...string) *IntCmd
	SInterStore(ctx context.Context, destination string, keys ...string) *IntCmd
	SIsMember(ctx context.Context, key string, member interface{}) *BoolCmd
	SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd
	SMembers(ctx context.Context, key string) *StringSliceCmd
	SMembersMap(ctx context.Context, key string) *StringStructMapCmd
	SMove(ctx context.Context, source, destination string, member interface{}) *BoolCmd
	SPop(ctx context.Context, key string) *StringCmd
	SPopN(ctx context.Context, key string, count int64) *StringSliceCmd
	SRandMember(ctx context.Context, key string) *StringCmd
	SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd
	SRem(ctx context.Context, key string, members ...interface{}) *IntCmd
	SUnion(ctx context.Context, keys ...string) *StringSliceCmd
	SUnionStore(ctx context.Context, destination string, keys ...string) *IntCmd

	XAdd(ctx context.Context, a *XAddArgs) *StringCmd
	XDel(ctx context.Context, stream string, ids ...string) *IntCmd
	XLen(ctx context.Context, stream string) *IntCmd
	XRange(ctx context.Context, stream, start, stop string) *XMessageSliceCmd
	XRangeN(ctx context.Context, stream, start, stop string, count int64) *XMessageSliceCmd
	XRevRange(ctx context.Context, stream string, start, stop string) *XMessageSliceCmd
	XRevRangeN(ctx context.Context, stream string, start, stop string, count int64) *XMessageSliceCmd
	XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd
	XReadStreams(ctx context.Context, streams ...string) *XStreamSliceCmd
	XGroupCreate(ctx context.Context, stream, group, start string) *StatusCmd
	XGroupCreateMkStream(ctx context.Context, stream, group, start string) *StatusCmd
	XGroupSetID(ctx context.Context, stream, group, start string) *StatusCmd
	XGroupDestroy(ctx context.Context, stream, group string) *IntCmd
	XGroupCreateConsumer(ctx context.Context, stream, group, consumer string) *IntCmd
	XGroupDelConsumer(ctx context.Context, stream, group, consumer string) *IntCmd
	XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd
	XAck(ctx context.Context, stream, group string, ids ...string) *IntCmd
	XPending(ctx context.Context, stream, group string) *XPendingCmd
	XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingExtCmd
	XClaim(ctx context.Context, a *XClaimArgs) *XMessageSliceCmd
	XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCmd
	XAutoClaim(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimCmd
	XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimJustIDCmd
	XTrimMaxLen(ctx context.Context, key string, maxLen int64) *IntCmd
	XTrimMaxLenApprox(ctx context.Context, key string, maxLen, limit int64) *IntCmd
	XTrimMinID(ctx context.Context, key string, minID string) *IntCmd
	XTrimMinIDApprox(ctx context.Context, key string, minID string, limit int64) *IntCmd
	XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd
	XInfoStream(ctx context.Context, key string) *XInfoStreamCmd
	XInfoStreamFull(ctx context.Context, key string, count int) *XInfoStreamFullCmd
	XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd

	BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
	BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
	BZMPop(ctx context.Context, timeout time.Duration, order string, count int64, keys ...string) *ZSliceWithKeyCmd

	ZAdd(ctx context.Context, key string, members ...Z) *IntCmd
	ZAddLT(ctx context.Context, key string, members ...Z) *IntCmd
	ZAddGT(ctx context.Context, key string, members ...Z) *IntCmd
	ZAddNX(ctx context.Context, key string, members ...Z) *IntCmd
	ZAddXX(ctx context.Context, key string, members ...Z) *IntCmd
	ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd
	ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd
	ZCard(ctx context.Context, key string) *IntCmd
	ZCount(ctx context.Context, key, min, max string) *IntCmd
	ZLexCount(ctx context.Context, key, min, max string) *IntCmd
	ZIncrBy(ctx context.Context, key string, increment float64, member string) *FloatCmd
	ZInter(ctx context.Context, store *ZStore) *StringSliceCmd
	ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd
	ZInterCard(ctx context.Context, limit int64, keys ...string) *IntCmd
	ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd
	ZMPop(ctx context.Context, order string, count int64, keys ...string) *ZSliceWithKeyCmd
	ZMScore(ctx context.Context, key string, members ...string) *FloatSliceCmd
	ZPopMax(ctx context.Context, key string, count ...int64) *ZSliceCmd
	ZPopMin(ctx context.Context, key string, count ...int64) *ZSliceCmd
	ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
	ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd
	ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
	ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
	ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd
	ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd
	ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd
	ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd
	ZRank(ctx context.Context, key, member string) *IntCmd
	ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd
	ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd
	ZRemRangeByScore(ctx context.Context, key, min, max string) *IntCmd
	ZRemRangeByLex(ctx context.Context, key, min, max string) *IntCmd
	ZRevRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
	ZRevRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd
	ZRevRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
	ZRevRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
	ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd
	ZRevRank(ctx context.Context, key, member string) *IntCmd
	ZScore(ctx context.Context, key, member string) *FloatCmd
	ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd
	ZRandMember(ctx context.Context, key string, count int) *StringSliceCmd
	ZRandMemberWithScores(ctx context.Context, key string, count int) *ZSliceCmd
	ZUnion(ctx context.Context, store ZStore) *StringSliceCmd
	ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd
	ZDiff(ctx context.Context, keys ...string) *StringSliceCmd
	ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd
	ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd

	PFAdd(ctx context.Context, key string, els ...interface{}) *IntCmd
	PFCount(ctx context.Context, keys ...string) *IntCmd
	PFMerge(ctx context.Context, dest string, keys ...string) *StatusCmd

	BgRewriteAOF(ctx context.Context) *StatusCmd
	BgSave(ctx context.Context) *StatusCmd
	ClientKill(ctx context.Context, ipPort string) *StatusCmd
	ClientKillByFilter(ctx context.Context, keys ...string) *IntCmd
	ClientList(ctx context.Context) *StringCmd
	ClientPause(ctx context.Context, dur time.Duration) *BoolCmd
	ClientUnpause(ctx context.Context) *BoolCmd
	ClientID(ctx context.Context) *IntCmd
	ClientUnblock(ctx context.Context, id int64) *IntCmd
	ClientUnblockWithError(ctx context.Context, id int64) *IntCmd
	ConfigGet(ctx context.Context, parameter string) *MapStringStringCmd
	ConfigResetStat(ctx context.Context) *StatusCmd
	ConfigSet(ctx context.Context, parameter, value string) *StatusCmd
	ConfigRewrite(ctx context.Context) *StatusCmd
	DBSize(ctx context.Context) *IntCmd
	FlushAll(ctx context.Context) *StatusCmd
	FlushAllAsync(ctx context.Context) *StatusCmd
	FlushDB(ctx context.Context) *StatusCmd
	FlushDBAsync(ctx context.Context) *StatusCmd
	Info(ctx context.Context, section ...string) *StringCmd
	LastSave(ctx context.Context) *IntCmd
	Save(ctx context.Context) *StatusCmd
	Shutdown(ctx context.Context) *StatusCmd
	ShutdownSave(ctx context.Context) *StatusCmd
	ShutdownNoSave(ctx context.Context) *StatusCmd
	SlaveOf(ctx context.Context, host, port string) *StatusCmd
	SlowLogGet(ctx context.Context, num int64) *SlowLogCmd
	Time(ctx context.Context) *TimeCmd
	DebugObject(ctx context.Context, key string) *StringCmd
	ReadOnly(ctx context.Context) *StatusCmd
	ReadWrite(ctx context.Context) *StatusCmd
	MemoryUsage(ctx context.Context, key string, samples ...int) *IntCmd

	Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
	EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
	EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
	EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
	ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
	ScriptFlush(ctx context.Context) *StatusCmd
	ScriptKill(ctx context.Context) *StatusCmd
	ScriptLoad(ctx context.Context, script string) *StringCmd

	FunctionLoad(ctx context.Context, code string) *StringCmd
	FunctionLoadReplace(ctx context.Context, code string) *StringCmd
	FunctionDelete(ctx context.Context, libName string) *StringCmd
	FunctionFlush(ctx context.Context) *StringCmd
	FunctionKill(ctx context.Context) *StringCmd
	FunctionFlushAsync(ctx context.Context) *StringCmd
	FunctionList(ctx context.Context, q FunctionListQuery) *FunctionListCmd
	FunctionDump(ctx context.Context) *StringCmd
	FunctionRestore(ctx context.Context, libDump string) *StringCmd
	FunctionStats(ctx context.Context) *FunctionStatsCmd
	FCall(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd
	FCallRo(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd

	Publish(ctx context.Context, channel string, message interface{}) *IntCmd
	SPublish(ctx context.Context, channel string, message interface{}) *IntCmd
	PubSubChannels(ctx context.Context, pattern string) *StringSliceCmd
	PubSubNumSub(ctx context.Context, channels ...string) *MapStringIntCmd
	PubSubNumPat(ctx context.Context) *IntCmd
	PubSubShardChannels(ctx context.Context, pattern string) *StringSliceCmd
	PubSubShardNumSub(ctx context.Context, channels ...string) *MapStringIntCmd

	ClusterSlots(ctx context.Context) *ClusterSlotsCmd
	ClusterShards(ctx context.Context) *ClusterShardsCmd
	ClusterLinks(ctx context.Context) *ClusterLinksCmd
	ClusterNodes(ctx context.Context) *StringCmd
	ClusterMeet(ctx context.Context, host, port string) *StatusCmd
	ClusterForget(ctx context.Context, nodeID string) *StatusCmd
	ClusterReplicate(ctx context.Context, nodeID string) *StatusCmd
	ClusterResetSoft(ctx context.Context) *StatusCmd
	ClusterResetHard(ctx context.Context) *StatusCmd
	ClusterInfo(ctx context.Context) *StringCmd
	ClusterKeySlot(ctx context.Context, key string) *IntCmd
	ClusterGetKeysInSlot(ctx context.Context, slot int, count int) *StringSliceCmd
	ClusterCountFailureReports(ctx context.Context, nodeID string) *IntCmd
	ClusterCountKeysInSlot(ctx context.Context, slot int) *IntCmd
	ClusterDelSlots(ctx context.Context, slots ...int) *StatusCmd
	ClusterDelSlotsRange(ctx context.Context, min, max int) *StatusCmd
	ClusterSaveConfig(ctx context.Context) *StatusCmd
	ClusterSlaves(ctx context.Context, nodeID string) *StringSliceCmd
	ClusterFailover(ctx context.Context) *StatusCmd
	ClusterAddSlots(ctx context.Context, slots ...int) *StatusCmd
	ClusterAddSlotsRange(ctx context.Context, min, max int) *StatusCmd

	GeoAdd(ctx context.Context, key string, geoLocation ...*GeoLocation) *IntCmd
	GeoPos(ctx context.Context, key string, members ...string) *GeoPosCmd
	GeoRadius(ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd
	GeoRadiusStore(ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery) *IntCmd
	GeoRadiusByMember(ctx context.Context, key, member string, query *GeoRadiusQuery) *GeoLocationCmd
	GeoRadiusByMemberStore(ctx context.Context, key, member string, query *GeoRadiusQuery) *IntCmd
	GeoSearch(ctx context.Context, key string, q *GeoSearchQuery) *StringSliceCmd
	GeoSearchLocation(ctx context.Context, key string, q *GeoSearchLocationQuery) *GeoSearchLocationCmd
	GeoSearchStore(ctx context.Context, key, store string, q *GeoSearchStoreQuery) *IntCmd
	GeoDist(ctx context.Context, key string, member1, member2, unit string) *FloatCmd
	GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd

	ACLDryRun(ctx context.Context, username string, command ...interface{}) *StringCmd
}

type StatefulCmdable interface {
	Cmdable
	Auth(ctx context.Context, password string) *StatusCmd
	AuthACL(ctx context.Context, username, password string) *StatusCmd
	Select(ctx context.Context, index int) *StatusCmd
	SwapDB(ctx context.Context, index1, index2 int) *StatusCmd
	ClientSetName(ctx context.Context, name string) *BoolCmd
	Hello(ctx context.Context, ver int, username, password, clientName string) *MapStringInterfaceCmd
}

var (
	_ Cmdable = (*Client)(nil)
	_ Cmdable = (*Tx)(nil)
	_ Cmdable = (*Ring)(nil)
	_ Cmdable = (*ClusterClient)(nil)
)

type cmdable func(ctx context.Context, cmd Cmder) error

type statefulCmdable func(ctx context.Context, cmd Cmder) error

//------------------------------------------------------------------------------

func ( statefulCmdable) ( context.Context,  string) *StatusCmd {
	 := NewStatusCmd(, "auth", )
	_ = (, )
	return 
}

// AuthACL Perform an AUTH command, using the given user and pass.
// Should be used to authenticate the current connection with one of the connections defined in the ACL list
// when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
func ( statefulCmdable) ( context.Context, ,  string) *StatusCmd {
	 := NewStatusCmd(, "auth", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int,  time.Duration) *IntCmd {
	 := NewIntCmd(, "wait", , int(/time.Millisecond))
	.setReadTimeout()
	_ = (, )
	return 
}

func ( statefulCmdable) ( context.Context,  int) *StatusCmd {
	 := NewStatusCmd(, "select", )
	_ = (, )
	return 
}

func ( statefulCmdable) ( context.Context, ,  int) *StatusCmd {
	 := NewStatusCmd(, "swapdb", , )
	_ = (, )
	return 
}

// ClientSetName assigns a name to the connection.
func ( statefulCmdable) ( context.Context,  string) *BoolCmd {
	 := NewBoolCmd(, "client", "setname", )
	_ = (, )
	return 
}

// Hello Set the resp protocol used.
func ( statefulCmdable) ( context.Context,
	 int, , ,  string) *MapStringInterfaceCmd {
	 := make([]interface{}, 0, 7)
	 = append(, "hello", )
	if  != "" {
		if  != "" {
			 = append(, "auth", , )
		} else {
			 = append(, "auth", "default", )
		}
	}
	if  != "" {
		 = append(, "setname", )
	}
	 := NewMapStringInterfaceCmd(, ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context) *CommandsInfoCmd {
	 := NewCommandsInfoCmd(, "command")
	_ = (, )
	return 
}

// FilterBy is used for the `CommandList` command parameter.
type FilterBy struct {
	Module  string
	ACLCat  string
	Pattern string
}

func ( cmdable) ( context.Context,  *FilterBy) *StringSliceCmd {
	 := make([]interface{}, 0, 5)
	 = append(, "command", "list")
	if  != nil {
		if .Module != "" {
			 = append(, "filterby", "module", .Module)
		} else if .ACLCat != "" {
			 = append(, "filterby", "aclcat", .ACLCat)
		} else if .Pattern != "" {
			 = append(, "filterby", "pattern", .Pattern)
		}
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...interface{}) *StringSliceCmd {
	 := make([]interface{}, 2+len())
	[0] = "command"
	[1] = "getkeys"
	copy([2:], )
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...interface{}) *KeyFlagsCmd {
	 := make([]interface{}, 2+len())
	[0] = "command"
	[1] = "getkeysandflags"
	copy([2:], )
	 := NewKeyFlagsCmd(, ...)
	_ = (, )
	return 
}

// ClientGetName returns the name of the connection.
func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "client", "getname")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  interface{}) *StringCmd {
	 := NewStringCmd(, "echo", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "ping")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	panic("not implemented")
}

func ( cmdable) ( context.Context,  ...string) *IntCmd {
	 := make([]interface{}, 1+len())
	[0] = "del"
	for ,  := range  {
		[1+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *IntCmd {
	 := make([]interface{}, 1+len())
	[0] = "unlink"
	for ,  := range  {
		[1+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "dump", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *IntCmd {
	 := make([]interface{}, 1+len())
	[0] = "exists"
	for ,  := range  {
		[1+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  time.Duration) *BoolCmd {
	return .expire(, , , "")
}

func ( cmdable) ( context.Context,  string,  time.Duration) *BoolCmd {
	return .expire(, , , "NX")
}

func ( cmdable) ( context.Context,  string,  time.Duration) *BoolCmd {
	return .expire(, , , "XX")
}

func ( cmdable) ( context.Context,  string,  time.Duration) *BoolCmd {
	return .expire(, , , "GT")
}

func ( cmdable) ( context.Context,  string,  time.Duration) *BoolCmd {
	return .expire(, , , "LT")
}

func ( cmdable) (
	 context.Context,  string,  time.Duration,  string,
) *BoolCmd {
	 := make([]interface{}, 3, 4)
	[0] = "expire"
	[1] = 
	[2] = formatSec(, )
	if  != "" {
		 = append(, )
	}

	 := NewBoolCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  time.Time) *BoolCmd {
	 := NewBoolCmd(, "expireat", , .Unix())
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *DurationCmd {
	 := NewDurationCmd(, time.Second, "expiretime", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringSliceCmd {
	 := NewStringSliceCmd(, "keys", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string,  int,  time.Duration) *StatusCmd {
	 := NewStatusCmd(
		,
		"migrate",
		,
		,
		,
		,
		formatMs(, ),
	)
	.setReadTimeout()
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int) *BoolCmd {
	 := NewBoolCmd(, "move", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "object", "refcount", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "object", "encoding", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *DurationCmd {
	 := NewDurationCmd(, time.Second, "object", "idletime", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *BoolCmd {
	 := NewBoolCmd(, "persist", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  time.Duration) *BoolCmd {
	 := NewBoolCmd(, "pexpire", , formatMs(, ))
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  time.Time) *BoolCmd {
	 := NewBoolCmd(
		,
		"pexpireat",
		,
		.UnixNano()/int64(time.Millisecond),
	)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *DurationCmd {
	 := NewDurationCmd(, time.Millisecond, "pexpiretime", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *DurationCmd {
	 := NewDurationCmd(, time.Millisecond, "pttl", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "randomkey")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *StatusCmd {
	 := NewStatusCmd(, "rename", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *BoolCmd {
	 := NewBoolCmd(, "renamenx", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  time.Duration,  string) *StatusCmd {
	 := NewStatusCmd(
		,
		"restore",
		,
		formatMs(, ),
		,
	)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  time.Duration,  string) *StatusCmd {
	 := NewStatusCmd(
		,
		"restore",
		,
		formatMs(, ),
		,
		"replace",
	)
	_ = (, )
	return 
}

type Sort struct {
	By            string
	Offset, Count int64
	Get           []string
	Order         string
	Alpha         bool
}

func ( *Sort) (,  string) []interface{} {
	 := []interface{}{, }

	if .By != "" {
		 = append(, "by", .By)
	}
	if .Offset != 0 || .Count != 0 {
		 = append(, "limit", .Offset, .Count)
	}
	for ,  := range .Get {
		 = append(, "get", )
	}
	if .Order != "" {
		 = append(, .Order)
	}
	if .Alpha {
		 = append(, "alpha")
	}
	return 
}

func ( cmdable) ( context.Context,  string,  *Sort) *StringSliceCmd {
	 := NewStringSliceCmd(, .args("sort_ro", )...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  *Sort) *StringSliceCmd {
	 := NewStringSliceCmd(, .args("sort", )...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  *Sort) *IntCmd {
	 := .args("sort", )
	if  != "" {
		 = append(, "store", )
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  *Sort) *SliceCmd {
	 := NewSliceCmd(, .args("sort", )...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *IntCmd {
	 := make([]interface{}, len()+1)
	[0] = "touch"
	for ,  := range  {
		[+1] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *DurationCmd {
	 := NewDurationCmd(, time.Second, "ttl", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StatusCmd {
	 := NewStatusCmd(, "type", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *IntCmd {
	 := NewIntCmd(, "append", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "decr", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int64) *IntCmd {
	 := NewIntCmd(, "decrby", , )
	_ = (, )
	return 
}

// Get Redis `GET key` command. It returns redis.Nil error when key does not exist.
func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "get", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  int64) *StringCmd {
	 := NewStringCmd(, "getrange", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  interface{}) *StringCmd {
	 := NewStringCmd(, "getset", , )
	_ = (, )
	return 
}

// GetEx An expiration of zero removes the TTL associated with the key (i.e. GETEX key persist).
// Requires Redis >= 6.2.0.
func ( cmdable) ( context.Context,  string,  time.Duration) *StringCmd {
	 := make([]interface{}, 0, 4)
	 = append(, "getex", )
	if  > 0 {
		if usePrecise() {
			 = append(, "px", formatMs(, ))
		} else {
			 = append(, "ex", formatSec(, ))
		}
	} else if  == 0 {
		 = append(, "persist")
	}

	 := NewStringCmd(, ...)
	_ = (, )
	return 
}

// GetDel redis-server version >= 6.2.0.
func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "getdel", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "incr", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int64) *IntCmd {
	 := NewIntCmd(, "incrby", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  float64) *FloatCmd {
	 := NewFloatCmd(, "incrbyfloat", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *SliceCmd {
	 := make([]interface{}, 1+len())
	[0] = "mget"
	for ,  := range  {
		[1+] = 
	}
	 := NewSliceCmd(, ...)
	_ = (, )
	return 
}

// MSet is like Set but accepts multiple values:
//   - MSet("key1", "value1", "key2", "value2")
//   - MSet([]string{"key1", "value1", "key2", "value2"})
//   - MSet(map[string]interface{}{"key1": "value1", "key2": "value2"})
//   - MSet(struct), For struct types, see HSet description.
func ( cmdable) ( context.Context,  ...interface{}) *StatusCmd {
	 := make([]interface{}, 1, 1+len())
	[0] = "mset"
	 = appendArgs(, )
	 := NewStatusCmd(, ...)
	_ = (, )
	return 
}

// MSetNX is like SetNX but accepts multiple values:
//   - MSetNX("key1", "value1", "key2", "value2")
//   - MSetNX([]string{"key1", "value1", "key2", "value2"})
//   - MSetNX(map[string]interface{}{"key1": "value1", "key2": "value2"})
//   - MSetNX(struct), For struct types, see HSet description.
func ( cmdable) ( context.Context,  ...interface{}) *BoolCmd {
	 := make([]interface{}, 1, 1+len())
	[0] = "msetnx"
	 = appendArgs(, )
	 := NewBoolCmd(, ...)
	_ = (, )
	return 
}

// Set Redis `SET key value [expiration]` command.
// Use expiration for `SETEx`-like behavior.
//
// Zero expiration means the key has no expiration time.
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
func ( cmdable) ( context.Context,  string,  interface{},  time.Duration) *StatusCmd {
	 := make([]interface{}, 3, 5)
	[0] = "set"
	[1] = 
	[2] = 
	if  > 0 {
		if usePrecise() {
			 = append(, "px", formatMs(, ))
		} else {
			 = append(, "ex", formatSec(, ))
		}
	} else if  == KeepTTL {
		 = append(, "keepttl")
	}

	 := NewStatusCmd(, ...)
	_ = (, )
	return 
}

// SetArgs provides arguments for the SetArgs function.
type SetArgs struct {
	// Mode can be `NX` or `XX` or empty.
	Mode string

	// Zero `TTL` or `Expiration` means that the key has no expiration time.
	TTL      time.Duration
	ExpireAt time.Time

	// When Get is true, the command returns the old value stored at key, or nil when key did not exist.
	Get bool

	// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
	// otherwise you will receive an error: (error) ERR syntax error.
	KeepTTL bool
}

// SetArgs supports all the options that the SET command supports.
// It is the alternative to the Set function when you want
// to have more control over the options.
func ( cmdable) ( context.Context,  string,  interface{},  SetArgs) *StatusCmd {
	 := []interface{}{"set", , }

	if .KeepTTL {
		 = append(, "keepttl")
	}

	if !.ExpireAt.IsZero() {
		 = append(, "exat", .ExpireAt.Unix())
	}
	if .TTL > 0 {
		if usePrecise(.TTL) {
			 = append(, "px", formatMs(, .TTL))
		} else {
			 = append(, "ex", formatSec(, .TTL))
		}
	}

	if .Mode != "" {
		 = append(, .Mode)
	}

	if .Get {
		 = append(, "get")
	}

	 := NewStatusCmd(, ...)
	_ = (, )
	return 
}

// SetEx Redis `SETEx key expiration value` command.
func ( cmdable) ( context.Context,  string,  interface{},  time.Duration) *StatusCmd {
	 := NewStatusCmd(, "setex", , formatSec(, ), )
	_ = (, )
	return 
}

// SetNX Redis `SET key value [expiration] NX` command.
//
// Zero expiration means the key has no expiration time.
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
func ( cmdable) ( context.Context,  string,  interface{},  time.Duration) *BoolCmd {
	var  *BoolCmd
	switch  {
	case 0:
		// Use old `SETNX` to support old Redis versions.
		 = NewBoolCmd(, "setnx", , )
	case KeepTTL:
		 = NewBoolCmd(, "set", , , "keepttl", "nx")
	default:
		if usePrecise() {
			 = NewBoolCmd(, "set", , , "px", formatMs(, ), "nx")
		} else {
			 = NewBoolCmd(, "set", , , "ex", formatSec(, ), "nx")
		}
	}

	_ = (, )
	return 
}

// SetXX Redis `SET key value [expiration] XX` command.
//
// Zero expiration means the key has no expiration time.
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
func ( cmdable) ( context.Context,  string,  interface{},  time.Duration) *BoolCmd {
	var  *BoolCmd
	switch  {
	case 0:
		 = NewBoolCmd(, "set", , , "xx")
	case KeepTTL:
		 = NewBoolCmd(, "set", , , "keepttl", "xx")
	default:
		if usePrecise() {
			 = NewBoolCmd(, "set", , , "px", formatMs(, ), "xx")
		} else {
			 = NewBoolCmd(, "set", , , "ex", formatSec(, ), "xx")
		}
	}

	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int64,  string) *IntCmd {
	 := NewIntCmd(, "setrange", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "strlen", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  int,  bool) *IntCmd {
	 := []interface{}{"copy", , , "DB", }
	if  {
		 = append(, "REPLACE")
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  string,  int64) *IntCmd {
	 := NewIntCmd(, "getbit", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int64,  int) *IntCmd {
	 := NewIntCmd(
		,
		"setbit",
		,
		,
		,
	)
	_ = (, )
	return 
}

type BitCount struct {
	Start, End int64
}

func ( cmdable) ( context.Context,  string,  *BitCount) *IntCmd {
	 := []interface{}{"bitcount", }
	if  != nil {
		 = append(
			,
			.Start,
			.End,
		)
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  ...string) *IntCmd {
	 := make([]interface{}, 3+len())
	[0] = "bitop"
	[1] = 
	[2] = 
	for ,  := range  {
		[3+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	return .bitOp(, "and", , ...)
}

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	return .bitOp(, "or", , ...)
}

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	return .bitOp(, "xor", , ...)
}

func ( cmdable) ( context.Context,  string,  string) *IntCmd {
	return .bitOp(, "not", , )
}

// BitPos is an API before Redis version 7.0, cmd: bitpos key bit start end
// if you need the `byte | bit` parameter, please use `BitPosSpan`.
func ( cmdable) ( context.Context,  string,  int64,  ...int64) *IntCmd {
	 := make([]interface{}, 3+len())
	[0] = "bitpos"
	[1] = 
	[2] = 
	switch len() {
	case 0:
	case 1:
		[3] = [0]
	case 2:
		[3] = [0]
		[4] = [1]
	default:
		panic("too many arguments")
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

// BitPosSpan supports the `byte | bit` parameters in redis version 7.0,
// the bitpos command defaults to using byte type for the `start-end` range,
// which means it counts in bytes from start to end. you can set the value
// of "span" to determine the type of `start-end`.
// span = "bit", cmd: bitpos key bit start end bit
// span = "byte", cmd: bitpos key bit start end byte
func ( cmdable) ( context.Context,  string,  int8, ,  int64,  string) *IntCmd {
	 := NewIntCmd(, "bitpos", , , , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntSliceCmd {
	 := make([]interface{}, 0, 2+len())
	 = append(, "bitfield")
	 = append(, )
	 = append(, ...)
	 := NewIntSliceCmd(, ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  uint64,  string,  int64) *ScanCmd {
	 := []interface{}{"scan", }
	if  != "" {
		 = append(, "match", )
	}
	if  > 0 {
		 = append(, "count", )
	}
	 := NewScanCmd(, , ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  uint64,  string,  int64,  string) *ScanCmd {
	 := []interface{}{"scan", }
	if  != "" {
		 = append(, "match", )
	}
	if  > 0 {
		 = append(, "count", )
	}
	if  != "" {
		 = append(, "type", )
	}
	 := NewScanCmd(, , ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  uint64,  string,  int64) *ScanCmd {
	 := []interface{}{"sscan", , }
	if  != "" {
		 = append(, "match", )
	}
	if  > 0 {
		 = append(, "count", )
	}
	 := NewScanCmd(, , ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  uint64,  string,  int64) *ScanCmd {
	 := []interface{}{"hscan", , }
	if  != "" {
		 = append(, "match", )
	}
	if  > 0 {
		 = append(, "count", )
	}
	 := NewScanCmd(, , ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  uint64,  string,  int64) *ScanCmd {
	 := []interface{}{"zscan", , }
	if  != "" {
		 = append(, "match", )
	}
	if  > 0 {
		 = append(, "count", )
	}
	 := NewScanCmd(, , ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	 := make([]interface{}, 2+len())
	[0] = "hdel"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *BoolCmd {
	 := NewBoolCmd(, "hexists", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *StringCmd {
	 := NewStringCmd(, "hget", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *MapStringStringCmd {
	 := NewMapStringStringCmd(, "hgetall", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  int64) *IntCmd {
	 := NewIntCmd(, "hincrby", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  float64) *FloatCmd {
	 := NewFloatCmd(, "hincrbyfloat", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringSliceCmd {
	 := NewStringSliceCmd(, "hkeys", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "hlen", )
	_ = (, )
	return 
}

// HMGet returns the values for the specified fields in the hash stored at key.
// It returns an interface{} to distinguish between empty string and nil value.
func ( cmdable) ( context.Context,  string,  ...string) *SliceCmd {
	 := make([]interface{}, 2+len())
	[0] = "hmget"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewSliceCmd(, ...)
	_ = (, )
	return 
}

// HSet accepts values in following formats:
//
//   - HSet("myhash", "key1", "value1", "key2", "value2")
//
//   - HSet("myhash", []string{"key1", "value1", "key2", "value2"})
//
//   - HSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"})
//
//     Playing struct With "redis" tag.
//     type MyHash struct { Key1 string `redis:"key1"`; Key2 int `redis:"key2"` }
//
//   - HSet("myhash", MyHash{"value1", "value2"}) Warn: redis-server >= 4.0
//
//     For struct, can be a structure pointer type, we only parse the field whose tag is redis.
//     if you don't want the field to be read, you can use the `redis:"-"` flag to ignore it,
//     or you don't need to set the redis tag.
//     For the type of structure field, we only support simple data types:
//     string, int/uint(8,16,32,64), float(32,64), time.Time(to RFC3339Nano), time.Duration(to Nanoseconds ),
//     if you are other more complex or custom data types, please implement the encoding.BinaryMarshaler interface.
//
// Note that in older versions of Redis server(redis-server < 4.0), HSet only supports a single key-value pair.
// redis-docs: https://redis.io/commands/hset (Starting with Redis version 4.0.0: Accepts multiple field and value arguments.)
// If you are using a Struct type and the number of fields is greater than one,
// you will receive an error similar to "ERR wrong number of arguments", you can use HMSet as a substitute.
func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "hset"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

// HMSet is a deprecated version of HSet left for compatibility with Redis 3.
func ( cmdable) ( context.Context,  string,  ...interface{}) *BoolCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "hmset"
	[1] = 
	 = appendArgs(, )
	 := NewBoolCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  interface{}) *BoolCmd {
	 := NewBoolCmd(, "hsetnx", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringSliceCmd {
	 := NewStringSliceCmd(, "hvals", )
	_ = (, )
	return 
}

// HRandField redis-server version >= 6.2.0.
func ( cmdable) ( context.Context,  string,  int) *StringSliceCmd {
	 := NewStringSliceCmd(, "hrandfield", , )
	_ = (, )
	return 
}

// HRandFieldWithValues redis-server version >= 6.2.0.
func ( cmdable) ( context.Context,  string,  int) *KeyValueSliceCmd {
	 := NewKeyValueSliceCmd(, "hrandfield", , , "withvalues")
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  time.Duration,  ...string) *StringSliceCmd {
	 := make([]interface{}, 1+len()+1)
	[0] = "blpop"
	for ,  := range  {
		[1+] = 
	}
	[len()-1] = formatSec(, )
	 := NewStringSliceCmd(, ...)
	.setReadTimeout()
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  time.Duration,  string,  int64,  ...string) *KeyValuesCmd {
	 := make([]interface{}, 3+len(), 6+len())
	[0] = "blmpop"
	[1] = formatSec(, )
	[2] = len()
	for ,  := range  {
		[3+] = 
	}
	 = append(, strings.ToLower(), "count", )
	 := NewKeyValuesCmd(, ...)
	.setReadTimeout()
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  time.Duration,  ...string) *StringSliceCmd {
	 := make([]interface{}, 1+len()+1)
	[0] = "brpop"
	for ,  := range  {
		[1+] = 
	}
	[len()+1] = formatSec(, )
	 := NewStringSliceCmd(, ...)
	.setReadTimeout()
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  time.Duration) *StringCmd {
	 := NewStringCmd(
		,
		"brpoplpush",
		,
		,
		formatSec(, ),
	)
	.setReadTimeout()
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  *LCSQuery) *LCSCmd {
	 := NewLCSCmd(, )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int64) *StringCmd {
	 := NewStringCmd(, "lindex", , )
	_ = (, )
	return 
}

// LMPop Pops one or more elements from the first non-empty list key from the list of provided key names.
// direction: left or right, count: > 0
// example: client.LMPop(ctx, "left", 3, "key1", "key2")
func ( cmdable) ( context.Context,  string,  int64,  ...string) *KeyValuesCmd {
	 := make([]interface{}, 2+len(), 5+len())
	[0] = "lmpop"
	[1] = len()
	for ,  := range  {
		[2+] = 
	}
	 = append(, strings.ToLower(), "count", )
	 := NewKeyValuesCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string, ,  interface{}) *IntCmd {
	 := NewIntCmd(, "linsert", , , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  interface{}) *IntCmd {
	 := NewIntCmd(, "linsert", , "before", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  interface{}) *IntCmd {
	 := NewIntCmd(, "linsert", , "after", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "llen", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "lpop", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int) *StringSliceCmd {
	 := NewStringSliceCmd(, "lpop", , )
	_ = (, )
	return 
}

type LPosArgs struct {
	Rank, MaxLen int64
}

func ( cmdable) ( context.Context,  string,  string,  LPosArgs) *IntCmd {
	 := []interface{}{"lpos", , }
	if .Rank != 0 {
		 = append(, "rank", .Rank)
	}
	if .MaxLen != 0 {
		 = append(, "maxlen", .MaxLen)
	}

	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  string,  int64,  LPosArgs) *IntSliceCmd {
	 := []interface{}{"lpos", , , "count", }
	if .Rank != 0 {
		 = append(, "rank", .Rank)
	}
	if .MaxLen != 0 {
		 = append(, "maxlen", .MaxLen)
	}
	 := NewIntSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "lpush"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "lpushx"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  int64) *StringSliceCmd {
	 := NewStringSliceCmd(
		,
		"lrange",
		,
		,
		,
	)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int64,  interface{}) *IntCmd {
	 := NewIntCmd(, "lrem", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int64,  interface{}) *StatusCmd {
	 := NewStatusCmd(, "lset", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  int64) *StatusCmd {
	 := NewStatusCmd(
		,
		"ltrim",
		,
		,
		,
	)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "rpop", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  int) *StringSliceCmd {
	 := NewStringSliceCmd(, "rpop", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *StringCmd {
	 := NewStringCmd(, "rpoplpush", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "rpush"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "rpushx"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , , ,  string) *StringCmd {
	 := NewStringCmd(, "lmove", , , , )
	_ = (, )
	return 
}

func ( cmdable) (
	 context.Context, , , ,  string,  time.Duration,
) *StringCmd {
	 := NewStringCmd(, "blmove", , , , , formatSec(, ))
	.setReadTimeout()
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "sadd"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "scard", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *StringSliceCmd {
	 := make([]interface{}, 1+len())
	[0] = "sdiff"
	for ,  := range  {
		[1+] = 
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	 := make([]interface{}, 2+len())
	[0] = "sdiffstore"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *StringSliceCmd {
	 := make([]interface{}, 1+len())
	[0] = "sinter"
	for ,  := range  {
		[1+] = 
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int64,  ...string) *IntCmd {
	 := make([]interface{}, 4+len())
	[0] = "sintercard"
	 := int64(0)
	for ,  := range  {
		[2+] = 
		++
	}
	[1] = 
	[2+] = "limit"
	[3+] = 
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	 := make([]interface{}, 2+len())
	[0] = "sinterstore"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  interface{}) *BoolCmd {
	 := NewBoolCmd(, "sismember", , )
	_ = (, )
	return 
}

// SMIsMember Redis `SMISMEMBER key member [member ...]` command.
func ( cmdable) ( context.Context,  string,  ...interface{}) *BoolSliceCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "smismember"
	[1] = 
	 = appendArgs(, )
	 := NewBoolSliceCmd(, ...)
	_ = (, )
	return 
}

// SMembers Redis `SMEMBERS key` command output as a slice.
func ( cmdable) ( context.Context,  string) *StringSliceCmd {
	 := NewStringSliceCmd(, "smembers", )
	_ = (, )
	return 
}

// SMembersMap Redis `SMEMBERS key` command output as a map.
func ( cmdable) ( context.Context,  string) *StringStructMapCmd {
	 := NewStringStructMapCmd(, "smembers", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  interface{}) *BoolCmd {
	 := NewBoolCmd(, "smove", , , )
	_ = (, )
	return 
}

// SPop Redis `SPOP key` command.
func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "spop", )
	_ = (, )
	return 
}

// SPopN Redis `SPOP key count` command.
func ( cmdable) ( context.Context,  string,  int64) *StringSliceCmd {
	 := NewStringSliceCmd(, "spop", , )
	_ = (, )
	return 
}

// SRandMember Redis `SRANDMEMBER key` command.
func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "srandmember", )
	_ = (, )
	return 
}

// SRandMemberN Redis `SRANDMEMBER key count` command.
func ( cmdable) ( context.Context,  string,  int64) *StringSliceCmd {
	 := NewStringSliceCmd(, "srandmember", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "srem"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *StringSliceCmd {
	 := make([]interface{}, 1+len())
	[0] = "sunion"
	for ,  := range  {
		[1+] = 
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	 := make([]interface{}, 2+len())
	[0] = "sunionstore"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

// XAddArgs accepts values in the following formats:
//   - XAddArgs.Values = []interface{}{"key1", "value1", "key2", "value2"}
//   - XAddArgs.Values = []string("key1", "value1", "key2", "value2")
//   - XAddArgs.Values = map[string]interface{}{"key1": "value1", "key2": "value2"}
//
// Note that map will not preserve the order of key-value pairs.
// MaxLen/MaxLenApprox and MinID are in conflict, only one of them can be used.
type XAddArgs struct {
	Stream     string
	NoMkStream bool
	MaxLen     int64 // MAXLEN N
	MinID      string
	// Approx causes MaxLen and MinID to use "~" matcher (instead of "=").
	Approx bool
	Limit  int64
	ID     string
	Values interface{}
}

func ( cmdable) ( context.Context,  *XAddArgs) *StringCmd {
	 := make([]interface{}, 0, 11)
	 = append(, "xadd", .Stream)
	if .NoMkStream {
		 = append(, "nomkstream")
	}
	switch {
	case .MaxLen > 0:
		if .Approx {
			 = append(, "maxlen", "~", .MaxLen)
		} else {
			 = append(, "maxlen", .MaxLen)
		}
	case .MinID != "":
		if .Approx {
			 = append(, "minid", "~", .MinID)
		} else {
			 = append(, "minid", .MinID)
		}
	}
	if .Limit > 0 {
		 = append(, "limit", .Limit)
	}
	if .ID != "" {
		 = append(, .ID)
	} else {
		 = append(, "*")
	}
	 = appendArg(, .Values)

	 := NewStringCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	 := []interface{}{"xdel", }
	for ,  := range  {
		 = append(, )
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "xlen", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *XMessageSliceCmd {
	 := NewXMessageSliceCmd(, "xrange", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string,  int64) *XMessageSliceCmd {
	 := NewXMessageSliceCmd(, "xrange", , , , "count", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *XMessageSliceCmd {
	 := NewXMessageSliceCmd(, "xrevrange", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string,  int64) *XMessageSliceCmd {
	 := NewXMessageSliceCmd(, "xrevrange", , , , "count", )
	_ = (, )
	return 
}

type XReadArgs struct {
	Streams []string // list of streams and ids, e.g. stream1 stream2 id1 id2
	Count   int64
	Block   time.Duration
}

func ( cmdable) ( context.Context,  *XReadArgs) *XStreamSliceCmd {
	 := make([]interface{}, 0, 6+len(.Streams))
	 = append(, "xread")

	 := int8(1)
	if .Count > 0 {
		 = append(, "count")
		 = append(, .Count)
		 += 2
	}
	if .Block >= 0 {
		 = append(, "block")
		 = append(, int64(.Block/time.Millisecond))
		 += 2
	}
	 = append(, "streams")
	++
	for ,  := range .Streams {
		 = append(, )
	}

	 := NewXStreamSliceCmd(, ...)
	if .Block >= 0 {
		.setReadTimeout(.Block)
	}
	.SetFirstKeyPos()
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *XStreamSliceCmd {
	return .XRead(, &XReadArgs{
		Streams: ,
		Block:   -1,
	})
}

func ( cmdable) ( context.Context, , ,  string) *StatusCmd {
	 := NewStatusCmd(, "xgroup", "create", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *StatusCmd {
	 := NewStatusCmd(, "xgroup", "create", , , , "mkstream")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *StatusCmd {
	 := NewStatusCmd(, "xgroup", "setid", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *IntCmd {
	 := NewIntCmd(, "xgroup", "destroy", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *IntCmd {
	 := NewIntCmd(, "xgroup", "createconsumer", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *IntCmd {
	 := NewIntCmd(, "xgroup", "delconsumer", , , )
	_ = (, )
	return 
}

type XReadGroupArgs struct {
	Group    string
	Consumer string
	Streams  []string // list of streams and ids, e.g. stream1 stream2 id1 id2
	Count    int64
	Block    time.Duration
	NoAck    bool
}

func ( cmdable) ( context.Context,  *XReadGroupArgs) *XStreamSliceCmd {
	 := make([]interface{}, 0, 10+len(.Streams))
	 = append(, "xreadgroup", "group", .Group, .Consumer)

	 := int8(4)
	if .Count > 0 {
		 = append(, "count", .Count)
		 += 2
	}
	if .Block >= 0 {
		 = append(, "block", int64(.Block/time.Millisecond))
		 += 2
	}
	if .NoAck {
		 = append(, "noack")
		++
	}
	 = append(, "streams")
	++
	for ,  := range .Streams {
		 = append(, )
	}

	 := NewXStreamSliceCmd(, ...)
	if .Block >= 0 {
		.setReadTimeout(.Block)
	}
	.SetFirstKeyPos()
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  ...string) *IntCmd {
	 := []interface{}{"xack", , }
	for ,  := range  {
		 = append(, )
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *XPendingCmd {
	 := NewXPendingCmd(, "xpending", , )
	_ = (, )
	return 
}

type XPendingExtArgs struct {
	Stream   string
	Group    string
	Idle     time.Duration
	Start    string
	End      string
	Count    int64
	Consumer string
}

func ( cmdable) ( context.Context,  *XPendingExtArgs) *XPendingExtCmd {
	 := make([]interface{}, 0, 9)
	 = append(, "xpending", .Stream, .Group)
	if .Idle != 0 {
		 = append(, "idle", formatMs(, .Idle))
	}
	 = append(, .Start, .End, .Count)
	if .Consumer != "" {
		 = append(, .Consumer)
	}
	 := NewXPendingExtCmd(, ...)
	_ = (, )
	return 
}

type XAutoClaimArgs struct {
	Stream   string
	Group    string
	MinIdle  time.Duration
	Start    string
	Count    int64
	Consumer string
}

func ( cmdable) ( context.Context,  *XAutoClaimArgs) *XAutoClaimCmd {
	 := xAutoClaimArgs(, )
	 := NewXAutoClaimCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  *XAutoClaimArgs) *XAutoClaimJustIDCmd {
	 := xAutoClaimArgs(, )
	 = append(, "justid")
	 := NewXAutoClaimJustIDCmd(, ...)
	_ = (, )
	return 
}

func xAutoClaimArgs( context.Context,  *XAutoClaimArgs) []interface{} {
	 := make([]interface{}, 0, 8)
	 = append(, "xautoclaim", .Stream, .Group, .Consumer, formatMs(, .MinIdle), .Start)
	if .Count > 0 {
		 = append(, "count", .Count)
	}
	return 
}

type XClaimArgs struct {
	Stream   string
	Group    string
	Consumer string
	MinIdle  time.Duration
	Messages []string
}

func ( cmdable) ( context.Context,  *XClaimArgs) *XMessageSliceCmd {
	 := xClaimArgs()
	 := NewXMessageSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  *XClaimArgs) *StringSliceCmd {
	 := xClaimArgs()
	 = append(, "justid")
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func xClaimArgs( *XClaimArgs) []interface{} {
	 := make([]interface{}, 0, 5+len(.Messages))
	 = append(,
		"xclaim",
		.Stream,
		.Group, .Consumer,
		int64(.MinIdle/time.Millisecond))
	for ,  := range .Messages {
		 = append(, )
	}
	return 
}

// xTrim If approx is true, add the "~" parameter, otherwise it is the default "=" (redis default).
// example:
//
//	XTRIM key MAXLEN/MINID threshold LIMIT limit.
//	XTRIM key MAXLEN/MINID ~ threshold LIMIT limit.
//
// The redis-server version is lower than 6.2, please set limit to 0.
func ( cmdable) (
	 context.Context, ,  string,
	 bool,  interface{},  int64,
) *IntCmd {
	 := make([]interface{}, 0, 7)
	 = append(, "xtrim", , )
	if  {
		 = append(, "~")
	}
	 = append(, )
	if  > 0 {
		 = append(, "limit", )
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

// XTrimMaxLen No `~` rules are used, `limit` cannot be used.
// cmd: XTRIM key MAXLEN maxLen
func ( cmdable) ( context.Context,  string,  int64) *IntCmd {
	return .xTrim(, , "maxlen", false, , 0)
}

func ( cmdable) ( context.Context,  string, ,  int64) *IntCmd {
	return .xTrim(, , "maxlen", true, , )
}

func ( cmdable) ( context.Context,  string,  string) *IntCmd {
	return .xTrim(, , "minid", false, , 0)
}

func ( cmdable) ( context.Context,  string,  string,  int64) *IntCmd {
	return .xTrim(, , "minid", true, , )
}

func ( cmdable) ( context.Context,  string,  string) *XInfoConsumersCmd {
	 := NewXInfoConsumersCmd(, , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *XInfoGroupsCmd {
	 := NewXInfoGroupsCmd(, )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *XInfoStreamCmd {
	 := NewXInfoStreamCmd(, )
	_ = (, )
	return 
}

// XInfoStreamFull XINFO STREAM FULL [COUNT count]
// redis-server >= 6.0.
func ( cmdable) ( context.Context,  string,  int) *XInfoStreamFullCmd {
	 := make([]interface{}, 0, 6)
	 = append(, "xinfo", "stream", , "full")
	if  > 0 {
		 = append(, "count", )
	}
	 := NewXInfoStreamFullCmd(, ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

// Z represents sorted set member.
type Z struct {
	Score  float64
	Member interface{}
}

// ZWithKey represents sorted set member including the name of the key where it was popped.
type ZWithKey struct {
	Z
	Key string
}

// ZStore is used as an arg to ZInter/ZInterStore and ZUnion/ZUnionStore.
type ZStore struct {
	Keys    []string
	Weights []float64
	// Can be SUM, MIN or MAX.
	Aggregate string
}

func ( ZStore) () ( int) {
	 = len(.Keys)
	if len(.Weights) > 0 {
		 += 1 + len(.Weights)
	}
	if .Aggregate != "" {
		 += 2
	}
	return 
}

func ( ZStore) ( []interface{}) []interface{} {
	for ,  := range .Keys {
		 = append(, )
	}
	if len(.Weights) > 0 {
		 = append(, "weights")
		for ,  := range .Weights {
			 = append(, )
		}
	}
	if .Aggregate != "" {
		 = append(, "aggregate", .Aggregate)
	}
	return 
}

// BZPopMax Redis `BZPOPMAX key [key ...] timeout` command.
func ( cmdable) ( context.Context,  time.Duration,  ...string) *ZWithKeyCmd {
	 := make([]interface{}, 1+len()+1)
	[0] = "bzpopmax"
	for ,  := range  {
		[1+] = 
	}
	[len()-1] = formatSec(, )
	 := NewZWithKeyCmd(, ...)
	.setReadTimeout()
	_ = (, )
	return 
}

// BZPopMin Redis `BZPOPMIN key [key ...] timeout` command.
func ( cmdable) ( context.Context,  time.Duration,  ...string) *ZWithKeyCmd {
	 := make([]interface{}, 1+len()+1)
	[0] = "bzpopmin"
	for ,  := range  {
		[1+] = 
	}
	[len()-1] = formatSec(, )
	 := NewZWithKeyCmd(, ...)
	.setReadTimeout()
	_ = (, )
	return 
}

// BZMPop is the blocking variant of ZMPOP.
// When any of the sorted sets contains elements, this command behaves exactly like ZMPOP.
// When all sorted sets are empty, Redis will block the connection until another client adds members to one of the keys or until the timeout elapses.
// A timeout of zero can be used to block indefinitely.
// example: client.BZMPop(ctx, 0,"max", 1, "set")
func ( cmdable) ( context.Context,  time.Duration,  string,  int64,  ...string) *ZSliceWithKeyCmd {
	 := make([]interface{}, 3+len(), 6+len())
	[0] = "bzmpop"
	[1] = formatSec(, )
	[2] = len()
	for ,  := range  {
		[3+] = 
	}
	 = append(, strings.ToLower(), "count", )
	 := NewZSliceWithKeyCmd(, ...)
	.setReadTimeout()
	_ = (, )
	return 
}

// ZAddArgs WARN: The GT, LT and NX options are mutually exclusive.
type ZAddArgs struct {
	NX      bool
	XX      bool
	LT      bool
	GT      bool
	Ch      bool
	Members []Z
}

func ( cmdable) ( string,  ZAddArgs,  bool) []interface{} {
	 := make([]interface{}, 0, 6+2*len(.Members))
	 = append(, "zadd", )

	// The GT, LT and NX options are mutually exclusive.
	if .NX {
		 = append(, "nx")
	} else {
		if .XX {
			 = append(, "xx")
		}
		if .GT {
			 = append(, "gt")
		} else if .LT {
			 = append(, "lt")
		}
	}
	if .Ch {
		 = append(, "ch")
	}
	if  {
		 = append(, "incr")
	}
	for ,  := range .Members {
		 = append(, .Score)
		 = append(, .Member)
	}
	return 
}

func ( cmdable) ( context.Context,  string,  ZAddArgs) *IntCmd {
	 := NewIntCmd(, .zAddArgs(, , false)...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ZAddArgs) *FloatCmd {
	 := NewFloatCmd(, .zAddArgs(, , true)...)
	_ = (, )
	return 
}

// ZAdd Redis `ZADD key score member [score member ...]` command.
func ( cmdable) ( context.Context,  string,  ...Z) *IntCmd {
	return .ZAddArgs(, , ZAddArgs{
		Members: ,
	})
}

// ZAddLT Redis `ZADD key LT score member [score member ...]` command.
func ( cmdable) ( context.Context,  string,  ...Z) *IntCmd {
	return .ZAddArgs(, , ZAddArgs{
		LT:      true,
		Members: ,
	})
}

// ZAddGT Redis `ZADD key GT score member [score member ...]` command.
func ( cmdable) ( context.Context,  string,  ...Z) *IntCmd {
	return .ZAddArgs(, , ZAddArgs{
		GT:      true,
		Members: ,
	})
}

// ZAddNX Redis `ZADD key NX score member [score member ...]` command.
func ( cmdable) ( context.Context,  string,  ...Z) *IntCmd {
	return .ZAddArgs(, , ZAddArgs{
		NX:      true,
		Members: ,
	})
}

// ZAddXX Redis `ZADD key XX score member [score member ...]` command.
func ( cmdable) ( context.Context,  string,  ...Z) *IntCmd {
	return .ZAddArgs(, , ZAddArgs{
		XX:      true,
		Members: ,
	})
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "zcard", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *IntCmd {
	 := NewIntCmd(, "zcount", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *IntCmd {
	 := NewIntCmd(, "zlexcount", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  float64,  string) *FloatCmd {
	 := NewFloatCmd(, "zincrby", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  *ZStore) *IntCmd {
	 := make([]interface{}, 0, 3+.len())
	 = append(, "zinterstore", , len(.Keys))
	 = .appendArgs()
	 := NewIntCmd(, ...)
	.SetFirstKeyPos(3)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  *ZStore) *StringSliceCmd {
	 := make([]interface{}, 0, 2+.len())
	 = append(, "zinter", len(.Keys))
	 = .appendArgs()
	 := NewStringSliceCmd(, ...)
	.SetFirstKeyPos(2)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  *ZStore) *ZSliceCmd {
	 := make([]interface{}, 0, 3+.len())
	 = append(, "zinter", len(.Keys))
	 = .appendArgs()
	 = append(, "withscores")
	 := NewZSliceCmd(, ...)
	.SetFirstKeyPos(2)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int64,  ...string) *IntCmd {
	 := make([]interface{}, 4+len())
	[0] = "zintercard"
	 := int64(0)
	for ,  := range  {
		[2+] = 
		++
	}
	[1] = 
	[2+] = "limit"
	[3+] = 
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

// ZMPop Pops one or more elements with the highest or lowest score from the first non-empty sorted set key from the list of provided key names.
// direction: "max" (highest score) or "min" (lowest score), count: > 0
// example: client.ZMPop(ctx, "max", 5, "set1", "set2")
func ( cmdable) ( context.Context,  string,  int64,  ...string) *ZSliceWithKeyCmd {
	 := make([]interface{}, 2+len(), 5+len())
	[0] = "zmpop"
	[1] = len()
	for ,  := range  {
		[2+] = 
	}
	 = append(, strings.ToLower(), "count", )
	 := NewZSliceWithKeyCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *FloatSliceCmd {
	 := make([]interface{}, 2+len())
	[0] = "zmscore"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewFloatSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...int64) *ZSliceCmd {
	 := []interface{}{
		"zpopmax",
		,
	}

	switch len() {
	case 0:
		break
	case 1:
		 = append(, [0])
	default:
		panic("too many arguments")
	}

	 := NewZSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...int64) *ZSliceCmd {
	 := []interface{}{
		"zpopmin",
		,
	}

	switch len() {
	case 0:
		break
	case 1:
		 = append(, [0])
	default:
		panic("too many arguments")
	}

	 := NewZSliceCmd(, ...)
	_ = (, )
	return 
}

// ZRangeArgs is all the options of the ZRange command.
// In version> 6.2.0, you can replace the(cmd):
//
//	ZREVRANGE,
//	ZRANGEBYSCORE,
//	ZREVRANGEBYSCORE,
//	ZRANGEBYLEX,
//	ZREVRANGEBYLEX.
//
// Please pay attention to your redis-server version.
//
// Rev, ByScore, ByLex and Offset+Count options require redis-server 6.2.0 and higher.
type ZRangeArgs struct {
	Key string

	// When the ByScore option is provided, the open interval(exclusive) can be set.
	// By default, the score intervals specified by <Start> and <Stop> are closed (inclusive).
	// It is similar to the deprecated(6.2.0+) ZRangeByScore command.
	// For example:
	//		ZRangeArgs{
	//			Key: 				"example-key",
	//	 		Start: 				"(3",
	//	 		Stop: 				8,
	//			ByScore:			true,
	//	 	}
	// 	 	cmd: "ZRange example-key (3 8 ByScore"  (3 < score <= 8).
	//
	// For the ByLex option, it is similar to the deprecated(6.2.0+) ZRangeByLex command.
	// You can set the <Start> and <Stop> options as follows:
	//		ZRangeArgs{
	//			Key: 				"example-key",
	//	 		Start: 				"[abc",
	//	 		Stop: 				"(def",
	//			ByLex:				true,
	//	 	}
	//		cmd: "ZRange example-key [abc (def ByLex"
	//
	// For normal cases (ByScore==false && ByLex==false), <Start> and <Stop> should be set to the index range (int).
	// You can read the documentation for more information: https://redis.io/commands/zrange
	Start interface{}
	Stop  interface{}

	// The ByScore and ByLex options are mutually exclusive.
	ByScore bool
	ByLex   bool

	Rev bool

	// limit offset count.
	Offset int64
	Count  int64
}

func ( ZRangeArgs) ( []interface{}) []interface{} {
	// For Rev+ByScore/ByLex, we need to adjust the position of <Start> and <Stop>.
	if .Rev && (.ByScore || .ByLex) {
		 = append(, .Key, .Stop, .Start)
	} else {
		 = append(, .Key, .Start, .Stop)
	}

	if .ByScore {
		 = append(, "byscore")
	} else if .ByLex {
		 = append(, "bylex")
	}
	if .Rev {
		 = append(, "rev")
	}
	if .Offset != 0 || .Count != 0 {
		 = append(, "limit", .Offset, .Count)
	}
	return 
}

func ( cmdable) ( context.Context,  ZRangeArgs) *StringSliceCmd {
	 := make([]interface{}, 0, 9)
	 = append(, "zrange")
	 = .appendArgs()
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ZRangeArgs) *ZSliceCmd {
	 := make([]interface{}, 0, 10)
	 = append(, "zrange")
	 = .appendArgs()
	 = append(, "withscores")
	 := NewZSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  int64) *StringSliceCmd {
	return .ZRangeArgs(, ZRangeArgs{
		Key:   ,
		Start: ,
		Stop:  ,
	})
}

func ( cmdable) ( context.Context,  string, ,  int64) *ZSliceCmd {
	return .ZRangeArgsWithScores(, ZRangeArgs{
		Key:   ,
		Start: ,
		Stop:  ,
	})
}

type ZRangeBy struct {
	Min, Max      string
	Offset, Count int64
}

func ( cmdable) ( context.Context, ,  string,  *ZRangeBy,  bool) *StringSliceCmd {
	 := []interface{}{, , .Min, .Max}
	if  {
		 = append(, "withscores")
	}
	if .Offset != 0 || .Count != 0 {
		 = append(
			,
			"limit",
			.Offset,
			.Count,
		)
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  *ZRangeBy) *StringSliceCmd {
	return .zRangeBy(, "zrangebyscore", , , false)
}

func ( cmdable) ( context.Context,  string,  *ZRangeBy) *StringSliceCmd {
	return .zRangeBy(, "zrangebylex", , , false)
}

func ( cmdable) ( context.Context,  string,  *ZRangeBy) *ZSliceCmd {
	 := []interface{}{"zrangebyscore", , .Min, .Max, "withscores"}
	if .Offset != 0 || .Count != 0 {
		 = append(
			,
			"limit",
			.Offset,
			.Count,
		)
	}
	 := NewZSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ZRangeArgs) *IntCmd {
	 := make([]interface{}, 0, 10)
	 = append(, "zrangestore", )
	 = .appendArgs()
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *IntCmd {
	 := NewIntCmd(, "zrank", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "zrem"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  int64) *IntCmd {
	 := NewIntCmd(
		,
		"zremrangebyrank",
		,
		,
		,
	)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *IntCmd {
	 := NewIntCmd(, "zremrangebyscore", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, , ,  string) *IntCmd {
	 := NewIntCmd(, "zremrangebylex", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  int64) *StringSliceCmd {
	 := NewStringSliceCmd(, "zrevrange", , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string, ,  int64) *ZSliceCmd {
	 := NewZSliceCmd(, "zrevrange", , , , "withscores")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  *ZRangeBy) *StringSliceCmd {
	 := []interface{}{, , .Max, .Min}
	if .Offset != 0 || .Count != 0 {
		 = append(
			,
			"limit",
			.Offset,
			.Count,
		)
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  *ZRangeBy) *StringSliceCmd {
	return .zRevRangeBy(, "zrevrangebyscore", , )
}

func ( cmdable) ( context.Context,  string,  *ZRangeBy) *StringSliceCmd {
	return .zRevRangeBy(, "zrevrangebylex", , )
}

func ( cmdable) ( context.Context,  string,  *ZRangeBy) *ZSliceCmd {
	 := []interface{}{"zrevrangebyscore", , .Max, .Min, "withscores"}
	if .Offset != 0 || .Count != 0 {
		 = append(
			,
			"limit",
			.Offset,
			.Count,
		)
	}
	 := NewZSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *IntCmd {
	 := NewIntCmd(, "zrevrank", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *FloatCmd {
	 := NewFloatCmd(, "zscore", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ZStore) *StringSliceCmd {
	 := make([]interface{}, 0, 2+.len())
	 = append(, "zunion", len(.Keys))
	 = .appendArgs()
	 := NewStringSliceCmd(, ...)
	.SetFirstKeyPos(2)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ZStore) *ZSliceCmd {
	 := make([]interface{}, 0, 3+.len())
	 = append(, "zunion", len(.Keys))
	 = .appendArgs()
	 = append(, "withscores")
	 := NewZSliceCmd(, ...)
	.SetFirstKeyPos(2)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  *ZStore) *IntCmd {
	 := make([]interface{}, 0, 3+.len())
	 = append(, "zunionstore", , len(.Keys))
	 = .appendArgs()
	 := NewIntCmd(, ...)
	.SetFirstKeyPos(3)
	_ = (, )
	return 
}

// ZRandMember redis-server version >= 6.2.0.
func ( cmdable) ( context.Context,  string,  int) *StringSliceCmd {
	 := NewStringSliceCmd(, "zrandmember", , )
	_ = (, )
	return 
}

// ZRandMemberWithScores redis-server version >= 6.2.0.
func ( cmdable) ( context.Context,  string,  int) *ZSliceCmd {
	 := NewZSliceCmd(, "zrandmember", , , "withscores")
	_ = (, )
	return 
}

// ZDiff redis-server version >= 6.2.0.
func ( cmdable) ( context.Context,  ...string) *StringSliceCmd {
	 := make([]interface{}, 2+len())
	[0] = "zdiff"
	[1] = len()
	for ,  := range  {
		[+2] = 
	}

	 := NewStringSliceCmd(, ...)
	.SetFirstKeyPos(2)
	_ = (, )
	return 
}

// ZDiffWithScores redis-server version >= 6.2.0.
func ( cmdable) ( context.Context,  ...string) *ZSliceCmd {
	 := make([]interface{}, 3+len())
	[0] = "zdiff"
	[1] = len()
	for ,  := range  {
		[+2] = 
	}
	[len()+2] = "withscores"

	 := NewZSliceCmd(, ...)
	.SetFirstKeyPos(2)
	_ = (, )
	return 
}

// ZDiffStore redis-server version >=6.2.0.
func ( cmdable) ( context.Context,  string,  ...string) *IntCmd {
	 := make([]interface{}, 0, 3+len())
	 = append(, "zdiffstore", , len())
	for ,  := range  {
		 = append(, )
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  string,  ...interface{}) *IntCmd {
	 := make([]interface{}, 2, 2+len())
	[0] = "pfadd"
	[1] = 
	 = appendArgs(, )
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *IntCmd {
	 := make([]interface{}, 1+len())
	[0] = "pfcount"
	for ,  := range  {
		[1+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *StatusCmd {
	 := make([]interface{}, 2+len())
	[0] = "pfmerge"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewStatusCmd(, ...)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "bgrewriteaof")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "bgsave")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StatusCmd {
	 := NewStatusCmd(, "client", "kill", )
	_ = (, )
	return 
}

// ClientKillByFilter is new style syntax, while the ClientKill is old
//
//	CLIENT KILL <option> [value] ... <option> [value]
func ( cmdable) ( context.Context,  ...string) *IntCmd {
	 := make([]interface{}, 2+len())
	[0] = "client"
	[1] = "kill"
	for ,  := range  {
		[2+] = 
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "client", "list")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  time.Duration) *BoolCmd {
	 := NewBoolCmd(, "client", "pause", formatMs(, ))
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *BoolCmd {
	 := NewBoolCmd(, "client", "unpause")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *IntCmd {
	 := NewIntCmd(, "client", "id")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int64) *IntCmd {
	 := NewIntCmd(, "client", "unblock", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int64) *IntCmd {
	 := NewIntCmd(, "client", "unblock", , "error")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *MapStringStringCmd {
	 := NewMapStringStringCmd(, "config", "get", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "config", "resetstat")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *StatusCmd {
	 := NewStatusCmd(, "config", "set", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "config", "rewrite")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *IntCmd {
	 := NewIntCmd(, "dbsize")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "flushall")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "flushall", "async")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "flushdb")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "flushdb", "async")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *StringCmd {
	 := make([]interface{}, 1+len())
	[0] = "info"
	for ,  := range  {
		[+1] = 
	}
	 := NewStringCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *IntCmd {
	 := NewIntCmd(, "lastsave")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "save")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StatusCmd {
	var  []interface{}
	if  == "" {
		 = []interface{}{"shutdown"}
	} else {
		 = []interface{}{"shutdown", }
	}
	 := NewStatusCmd(, ...)
	_ = (, )
	if  := .Err();  != nil {
		if  == io.EOF {
			// Server quit as expected.
			.err = nil
		}
	} else {
		// Server did not quit. String reply contains the reason.
		.err = errors.New(.val)
		.val = ""
	}
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	return .shutdown(, "")
}

func ( cmdable) ( context.Context) *StatusCmd {
	return .shutdown(, "save")
}

func ( cmdable) ( context.Context) *StatusCmd {
	return .shutdown(, "nosave")
}

func ( cmdable) ( context.Context, ,  string) *StatusCmd {
	 := NewStatusCmd(, "slaveof", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int64) *SlowLogCmd {
	 := NewSlowLogCmd(context.Background(), "slowlog", "get", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) {
	panic("not implemented")
}

func ( cmdable) ( context.Context) *TimeCmd {
	 := NewTimeCmd(, "time")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "debug", "object", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "readonly")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "readwrite")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...int) *IntCmd {
	 := []interface{}{"memory", "usage", }
	if len() > 0 {
		if len() != 1 {
			panic("MemoryUsage expects single sample count")
		}
		 = append(, "SAMPLES", [0])
	}
	 := NewIntCmd(, ...)
	.SetFirstKeyPos(2)
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  string,  []string,  ...interface{}) *Cmd {
	return .eval(, "eval", , , ...)
}

func ( cmdable) ( context.Context,  string,  []string,  ...interface{}) *Cmd {
	return .eval(, "eval_ro", , , ...)
}

func ( cmdable) ( context.Context,  string,  []string,  ...interface{}) *Cmd {
	return .eval(, "evalsha", , , ...)
}

func ( cmdable) ( context.Context,  string,  []string,  ...interface{}) *Cmd {
	return .eval(, "evalsha_ro", , , ...)
}

func ( cmdable) ( context.Context, ,  string,  []string,  ...interface{}) *Cmd {
	 := make([]interface{}, 3+len(), 3+len()+len())
	[0] = 
	[1] = 
	[2] = len()
	for ,  := range  {
		[3+] = 
	}
	 = appendArgs(, )
	 := NewCmd(, ...)

	// it is possible that only args exist without a key.
	// rdb.eval(ctx, eval, script, nil, arg1, arg2)
	if len() > 0 {
		.SetFirstKeyPos(3)
	}
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *BoolSliceCmd {
	 := make([]interface{}, 2+len())
	[0] = "script"
	[1] = "exists"
	for ,  := range  {
		[2+] = 
	}
	 := NewBoolSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "script", "flush")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "script", "kill")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "script", "load", )
	_ = (, )
	return 
}

// ------------------------------------------------------------------------------

// FunctionListQuery is used with FunctionList to query for Redis libraries
//
//	  	LibraryNamePattern 	- Use an empty string to get all libraries.
//	  						- Use a glob-style pattern to match multiple libraries with a matching name
//	  						- Use a library's full name to match a single library
//		WithCode			- If true, it will return the code of the library
type FunctionListQuery struct {
	LibraryNamePattern string
	WithCode           bool
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "function", "load", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "function", "load", "replace", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "function", "delete", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "function", "flush")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "function", "kill")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "function", "flush", "async")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  FunctionListQuery) *FunctionListCmd {
	 := make([]interface{}, 2, 5)
	[0] = "function"
	[1] = "list"
	if .LibraryNamePattern != "" {
		 = append(, "libraryname", .LibraryNamePattern)
	}
	if .WithCode {
		 = append(, "withcode")
	}
	 := NewFunctionListCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "function", "dump")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringCmd {
	 := NewStringCmd(, "function", "restore", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *FunctionStatsCmd {
	 := NewFunctionStatsCmd(, "function", "stats")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  []string,  ...interface{}) *Cmd {
	 := fcallArgs("fcall", , , ...)
	 := NewCmd(, ...)
	if len() > 0 {
		.SetFirstKeyPos(3)
	}
	_ = (, )
	return 
}
func ( cmdable) ( context.Context,  string,  []string,  ...interface{}) *Cmd {
	 := fcallArgs("fcall_ro", , , ...)
	 := NewCmd(, ...)
	if len() > 0 {
		.SetFirstKeyPos(3)
	}
	_ = (, )
	return 
}

func fcallArgs( string,  string,  []string,  ...interface{}) []interface{} {
	 := make([]interface{}, 3+len(), 3+len()+len())
	[0] = 
	[1] = 
	[2] = len()
	for ,  := range  {
		[3+] = 
	}

	 = append(, ...)
	return 
}

//------------------------------------------------------------------------------

// Publish posts the message to the channel.
func ( cmdable) ( context.Context,  string,  interface{}) *IntCmd {
	 := NewIntCmd(, "publish", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  interface{}) *IntCmd {
	 := NewIntCmd(, "spublish", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringSliceCmd {
	 := []interface{}{"pubsub", "channels"}
	if  != "*" {
		 = append(, )
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *MapStringIntCmd {
	 := make([]interface{}, 2+len())
	[0] = "pubsub"
	[1] = "numsub"
	for ,  := range  {
		[2+] = 
	}
	 := NewMapStringIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringSliceCmd {
	 := []interface{}{"pubsub", "shardchannels"}
	if  != "*" {
		 = append(, )
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...string) *MapStringIntCmd {
	 := make([]interface{}, 2+len())
	[0] = "pubsub"
	[1] = "shardnumsub"
	for ,  := range  {
		[2+] = 
	}
	 := NewMapStringIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *IntCmd {
	 := NewIntCmd(, "pubsub", "numpat")
	_ = (, )
	return 
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context) *ClusterSlotsCmd {
	 := NewClusterSlotsCmd(, "cluster", "slots")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *ClusterShardsCmd {
	 := NewClusterShardsCmd(, "cluster", "shards")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *ClusterLinksCmd {
	 := NewClusterLinksCmd(, "cluster", "links")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "cluster", "nodes")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string) *StatusCmd {
	 := NewStatusCmd(, "cluster", "meet", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StatusCmd {
	 := NewStatusCmd(, "cluster", "forget", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StatusCmd {
	 := NewStatusCmd(, "cluster", "replicate", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "cluster", "reset", "soft")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "cluster", "reset", "hard")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StringCmd {
	 := NewStringCmd(, "cluster", "info")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "cluster", "keyslot", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int,  int) *StringSliceCmd {
	 := NewStringSliceCmd(, "cluster", "getkeysinslot", , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *IntCmd {
	 := NewIntCmd(, "cluster", "count-failure-reports", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  int) *IntCmd {
	 := NewIntCmd(, "cluster", "countkeysinslot", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...int) *StatusCmd {
	 := make([]interface{}, 2+len())
	[0] = "cluster"
	[1] = "delslots"
	for ,  := range  {
		[2+] = 
	}
	 := NewStatusCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  int) *StatusCmd {
	 :=  -  + 1
	 := make([]int, )
	for  := 0;  < ; ++ {
		[] =  + 
	}
	return .ClusterDelSlots(, ...)
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "cluster", "saveconfig")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string) *StringSliceCmd {
	 := NewStringSliceCmd(, "cluster", "slaves", )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context) *StatusCmd {
	 := NewStatusCmd(, "cluster", "failover")
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  ...int) *StatusCmd {
	 := make([]interface{}, 2+len())
	[0] = "cluster"
	[1] = "addslots"
	for ,  := range  {
		[2+] = 
	}
	 := NewStatusCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  int) *StatusCmd {
	 :=  -  + 1
	 := make([]int, )
	for  := 0;  < ; ++ {
		[] =  + 
	}
	return .ClusterAddSlots(, ...)
}

//------------------------------------------------------------------------------

func ( cmdable) ( context.Context,  string,  ...*GeoLocation) *IntCmd {
	 := make([]interface{}, 2+3*len())
	[0] = "geoadd"
	[1] = 
	for ,  := range  {
		[2+3*] = .Longitude
		[2+3*+1] = .Latitude
		[2+3*+2] = .Name
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

// GeoRadius is a read-only GEORADIUS_RO command.
func ( cmdable) (
	 context.Context,  string, ,  float64,  *GeoRadiusQuery,
) *GeoLocationCmd {
	 := NewGeoLocationCmd(, , "georadius_ro", , , )
	if .Store != "" || .StoreDist != "" {
		.SetErr(errors.New("GeoRadius does not support Store or StoreDist"))
		return 
	}
	_ = (, )
	return 
}

// GeoRadiusStore is a writing GEORADIUS command.
func ( cmdable) (
	 context.Context,  string, ,  float64,  *GeoRadiusQuery,
) *IntCmd {
	 := geoLocationArgs(, "georadius", , , )
	 := NewIntCmd(, ...)
	if .Store == "" && .StoreDist == "" {
		.SetErr(errors.New("GeoRadiusStore requires Store or StoreDist"))
		return 
	}
	_ = (, )
	return 
}

// GeoRadiusByMember is a read-only GEORADIUSBYMEMBER_RO command.
func ( cmdable) (
	 context.Context, ,  string,  *GeoRadiusQuery,
) *GeoLocationCmd {
	 := NewGeoLocationCmd(, , "georadiusbymember_ro", , )
	if .Store != "" || .StoreDist != "" {
		.SetErr(errors.New("GeoRadiusByMember does not support Store or StoreDist"))
		return 
	}
	_ = (, )
	return 
}

// GeoRadiusByMemberStore is a writing GEORADIUSBYMEMBER command.
func ( cmdable) (
	 context.Context, ,  string,  *GeoRadiusQuery,
) *IntCmd {
	 := geoLocationArgs(, "georadiusbymember", , )
	 := NewIntCmd(, ...)
	if .Store == "" && .StoreDist == "" {
		.SetErr(errors.New("GeoRadiusByMemberStore requires Store or StoreDist"))
		return 
	}
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  *GeoSearchQuery) *StringSliceCmd {
	 := make([]interface{}, 0, 13)
	 = append(, "geosearch", )
	 = geoSearchArgs(, )
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) (
	 context.Context,  string,  *GeoSearchLocationQuery,
) *GeoSearchLocationCmd {
	 := make([]interface{}, 0, 16)
	 = append(, "geosearch", )
	 = geoSearchLocationArgs(, )
	 := NewGeoSearchLocationCmd(, , ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context, ,  string,  *GeoSearchStoreQuery) *IntCmd {
	 := make([]interface{}, 0, 15)
	 = append(, "geosearchstore", , )
	 = geoSearchArgs(&.GeoSearchQuery, )
	if .StoreDist {
		 = append(, "storedist")
	}
	 := NewIntCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) (
	 context.Context,  string, , ,  string,
) *FloatCmd {
	if  == "" {
		 = "km"
	}
	 := NewFloatCmd(, "geodist", , , , )
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *StringSliceCmd {
	 := make([]interface{}, 2+len())
	[0] = "geohash"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewStringSliceCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...string) *GeoPosCmd {
	 := make([]interface{}, 2+len())
	[0] = "geopos"
	[1] = 
	for ,  := range  {
		[2+] = 
	}
	 := NewGeoPosCmd(, ...)
	_ = (, )
	return 
}

func ( cmdable) ( context.Context,  string,  ...interface{}) *StringCmd {
	 := make([]interface{}, 0, 3+len())
	 = append(, "acl", "dryrun", )
	 = append(, ...)
	 := NewStringCmd(, ...)
	_ = (, )
	return 
}