From 540554043bfa8330ad16562ad07c3883f29aaf2b Mon Sep 17 00:00:00 2001 From: Monkey Date: Thu, 23 Mar 2023 00:05:50 +0800 Subject: [PATCH] feat(cmd): support for adding byte,bit parameters to the bitpos command (#2498) Signed-off-by: monkey92t --- commands.go | 15 +++++++++++++++ commands_test.go | 13 +++++++++++++ 2 files changed, 28 insertions(+) diff --git a/commands.go b/commands.go index da23db22..247ee30c 100644 --- a/commands.go +++ b/commands.go @@ -194,6 +194,7 @@ type Cmdable interface { 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 @@ -1211,6 +1212,8 @@ func (c cmdable) BitOpNot(ctx context.Context, destKey string, key string) *IntC return c.bitOp(ctx, "not", destKey, key) } +// 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 (c cmdable) BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd { args := make([]interface{}, 3+len(pos)) args[0] = "bitpos" @@ -1231,6 +1234,18 @@ func (c cmdable) BitPos(ctx context.Context, key string, bit int64, pos ...int64 return cmd } +// 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 (c cmdable) BitPosSpan(ctx context.Context, key string, bit int8, start, end int64, span string) *IntCmd { + cmd := NewIntCmd(ctx, "bitpos", key, bit, start, end, span) + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) BitField(ctx context.Context, key string, args ...interface{}) *IntSliceCmd { a := make([]interface{}, 0, 2+len(args)) a = append(a, "bitfield") diff --git a/commands_test.go b/commands_test.go index 1ddb6bae..80599d48 100644 --- a/commands_test.go +++ b/commands_test.go @@ -1091,6 +1091,19 @@ var _ = Describe("Commands", func() { Expect(pos).To(Equal(int64(-1))) }) + It("should BitPosSpan", func() { + err := client.Set(ctx, "mykey", "\x00\xff\x00", 0).Err() + Expect(err).NotTo(HaveOccurred()) + + pos, err := client.BitPosSpan(ctx, "mykey", 0, 1, 3, "byte").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(16))) + + pos, err = client.BitPosSpan(ctx, "mykey", 0, 1, 3, "bit").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(1))) + }) + It("should BitField", func() { nn, err := client.BitField(ctx, "mykey", "INCRBY", "i5", 100, 1, "GET", "u4", 0).Result() Expect(err).NotTo(HaveOccurred())