mirror of https://github.com/go-redis/redis.git
Add SliceCmd.Scan() (hscan pkg) and tests
This commit is contained in:
parent
380ab17274
commit
a4144ea98e
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8/internal"
|
"github.com/go-redis/redis/v8/internal"
|
||||||
|
"github.com/go-redis/redis/v8/internal/hscan"
|
||||||
"github.com/go-redis/redis/v8/internal/proto"
|
"github.com/go-redis/redis/v8/internal/proto"
|
||||||
"github.com/go-redis/redis/v8/internal/util"
|
"github.com/go-redis/redis/v8/internal/util"
|
||||||
)
|
)
|
||||||
|
@ -371,6 +372,13 @@ func (cmd *SliceCmd) String() string {
|
||||||
return cmdString(cmd, cmd.val)
|
return cmdString(cmd, cmd.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan scans the results from a key-value Redis map result set ([]interface{})
|
||||||
|
// like HMGET and HGETALL to a destination struct.
|
||||||
|
// The Redis keys are matched to the struct's field with the `redis` tag.
|
||||||
|
func (cmd *SliceCmd) Scan(val interface{}) error {
|
||||||
|
return hscan.Scan(cmd.val, val)
|
||||||
|
}
|
||||||
|
|
||||||
func (cmd *SliceCmd) readReply(rd *proto.Reader) error {
|
func (cmd *SliceCmd) readReply(rd *proto.Reader) error {
|
||||||
v, err := rd.ReadArrayReply(sliceParser)
|
v, err := rd.ReadArrayReply(sliceParser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
type decoderFunc func(reflect.Value, string) error
|
type decoderFunc func(reflect.Value, string) error
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// List of built-in decoders indexed by their numeric constant values (eg: reflect.Bool = 1)
|
// List of built-in decoders indexed by their numeric constant values (eg: reflect.Bool = 1).
|
||||||
decoders = []decoderFunc{
|
decoders = []decoderFunc{
|
||||||
reflect.Bool: decodeBool,
|
reflect.Bool: decodeBool,
|
||||||
reflect.Int: decodeInt,
|
reflect.Int: decodeInt,
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
package hscan
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
type data struct {
|
||||||
|
Omit string `redis:"-"`
|
||||||
|
Empty string
|
||||||
|
|
||||||
|
String string `redis:"string"`
|
||||||
|
Bytes []byte `redis:"byte"`
|
||||||
|
Int int `redis:"int"`
|
||||||
|
Uint uint `redis:"uint"`
|
||||||
|
Float float32 `redis:"float"`
|
||||||
|
Bool bool `redis:"bool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGinkgoSuite(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "hscan")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Describe("Scan", func() {
|
||||||
|
It("catches bad args", func() {
|
||||||
|
var d data
|
||||||
|
|
||||||
|
Expect(Scan([]interface{}{}, &d)).NotTo(HaveOccurred())
|
||||||
|
Expect(d).To(Equal(data{}))
|
||||||
|
|
||||||
|
Expect(Scan([]interface{}{"key"}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"key", "1", "2"}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"key", "1"}, nil)).To(HaveOccurred())
|
||||||
|
|
||||||
|
var i map[string]interface{}
|
||||||
|
Expect(Scan([]interface{}{"key", "1"}, &i)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"key", "1"}, data{})).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"key", nil, "string", nil}, data{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("scans good values", func() {
|
||||||
|
var d data
|
||||||
|
|
||||||
|
// non-tagged fields.
|
||||||
|
Expect(Scan([]interface{}{"key", "value"}, &d)).NotTo(HaveOccurred())
|
||||||
|
Expect(d).To(Equal(data{}))
|
||||||
|
|
||||||
|
res := []interface{}{"string", "str!",
|
||||||
|
"byte", "bytes!",
|
||||||
|
"int", "123",
|
||||||
|
"uint", "456",
|
||||||
|
"float", "123.456",
|
||||||
|
"bool", "1"}
|
||||||
|
Expect(Scan(res, &d)).NotTo(HaveOccurred())
|
||||||
|
Expect(d).To(Equal(data{
|
||||||
|
String: "str!",
|
||||||
|
Bytes: []byte("bytes!"),
|
||||||
|
Int: 123,
|
||||||
|
Uint: 456,
|
||||||
|
Float: 123.456,
|
||||||
|
Bool: true,
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Scan a different type with the same values to test that
|
||||||
|
// the struct spec maps don't conflict.
|
||||||
|
type data2 struct {
|
||||||
|
String string `redis:"string"`
|
||||||
|
Bytes []byte `redis:"byte"`
|
||||||
|
Int int `redis:"int"`
|
||||||
|
Uint uint `redis:"uint"`
|
||||||
|
Float float32 `redis:"float"`
|
||||||
|
Bool bool `redis:"bool"`
|
||||||
|
}
|
||||||
|
var d2 data2
|
||||||
|
Expect(Scan(res, &d2)).NotTo(HaveOccurred())
|
||||||
|
Expect(d2).To(Equal(data2{
|
||||||
|
String: "str!",
|
||||||
|
Bytes: []byte("bytes!"),
|
||||||
|
Int: 123,
|
||||||
|
Uint: 456,
|
||||||
|
Float: 123.456,
|
||||||
|
Bool: true,
|
||||||
|
}))
|
||||||
|
|
||||||
|
Expect(Scan([]interface{}{
|
||||||
|
"string", "",
|
||||||
|
"float", "1",
|
||||||
|
"bool", "t"}, &d)).NotTo(HaveOccurred())
|
||||||
|
Expect(d).To(Equal(data{
|
||||||
|
String: "",
|
||||||
|
Bytes: []byte("bytes!"),
|
||||||
|
Int: 123,
|
||||||
|
Uint: 456,
|
||||||
|
Float: 1.0,
|
||||||
|
Bool: true,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("omits untagged fields", func() {
|
||||||
|
var d data
|
||||||
|
|
||||||
|
Expect(Scan([]interface{}{
|
||||||
|
"empty", "value",
|
||||||
|
"omit", "value",
|
||||||
|
"string", "str!"}, &d)).NotTo(HaveOccurred())
|
||||||
|
Expect(d).To(Equal(data{
|
||||||
|
String: "str!",
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("catches bad values", func() {
|
||||||
|
var d data
|
||||||
|
|
||||||
|
Expect(Scan([]interface{}{"int", "a"}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"uint", "a"}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"uint", ""}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"float", "b"}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"bool", "-1"}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"bool", ""}, &d)).To(HaveOccurred())
|
||||||
|
Expect(Scan([]interface{}{"bool", "123"}, &d)).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
|
@ -61,7 +61,7 @@ func getStructFields(t reflect.Type, fieldTag string) *structFields {
|
||||||
for i := 0; i < num; i++ {
|
for i := 0; i < num; i++ {
|
||||||
f := t.Field(i)
|
f := t.Field(i)
|
||||||
|
|
||||||
tag := t.Field(i).Tag.Get(fieldTag)
|
tag := f.Tag.Get(fieldTag)
|
||||||
if tag == "" || tag == "-" {
|
if tag == "" || tag == "-" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue