Skip to content

Commit

Permalink
Merge pull request #388 from numberinho/main
Browse files Browse the repository at this point in the history
Support for pointers to primitives in Scan() and HSet()
  • Loading branch information
rueian authored Oct 9, 2023
2 parents f0f37fc + fe66d40 commit 78859ba
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 20 deletions.
11 changes: 11 additions & 0 deletions rueidiscompat/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3393,6 +3393,17 @@ func appendStructField(v reflect.Value) []string {
continue
}

// if its a nil pointer
if field.Kind() == reflect.Pointer && field.IsNil() {
continue
}

// if its a valid pointer
if field.Kind() == reflect.Pointer && field.Elem().CanInterface() {
dst = append(dst, name, str(field.Elem().Interface()))
continue
}

if field.CanInterface() {
dst = append(dst, name, str(field.Interface()))
}
Expand Down
12 changes: 9 additions & 3 deletions rueidiscompat/adapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2257,19 +2257,23 @@ func testAdapter(resp3 bool) {
Set4 interface{} `redis:"set4"`
Set5 map[string]interface{} `redis:"-"`
Set6 string `redis:"set6,omitempty"`
Set7 *string `redis:"set7"`
Set8 *string `redis:"set8"`
}

str := "str"
hSet = adapter.HSet(ctx, "hash", &set{
Set1: "val1",
Set2: 1024,
Set3: 2 * time.Millisecond,
Set4: nil,
Set5: map[string]interface{}{"k1": 1},
Set7: &str,
Set8: nil,
})
Expect(hSet.Err()).NotTo(HaveOccurred())
Expect(hSet.Val()).To(Equal(int64(4)))
Expect(hSet.Val()).To(Equal(int64(5)))

hMGet := adapter.HMGet(ctx, "hash", "set1", "set2", "set3", "set4", "set5", "set6")
hMGet := adapter.HMGet(ctx, "hash", "set1", "set2", "set3", "set4", "set5", "set6", "set7", "set8")
Expect(hMGet.Err()).NotTo(HaveOccurred())
Expect(hMGet.Val()).To(Equal([]interface{}{
"val1",
Expand All @@ -2278,6 +2282,8 @@ func testAdapter(resp3 bool) {
"",
nil,
nil,
str,
nil,
}))

hSet = adapter.HSet(ctx, "hash2", &set{
Expand Down
69 changes: 54 additions & 15 deletions rueidiscompat/hscan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,35 @@ type data struct {
Omit string `redis:"-"`
Empty string

String string `redis:"string"`
Bytes []byte `redis:"byte"`
Int int `redis:"int"`
Int8 int8 `redis:"int8"`
Int16 int16 `redis:"int16"`
Int32 int32 `redis:"int32"`
Int64 int64 `redis:"int64"`
Uint uint `redis:"uint"`
Uint8 uint8 `redis:"uint8"`
Uint16 uint16 `redis:"uint16"`
Uint32 uint32 `redis:"uint32"`
Uint64 uint64 `redis:"uint64"`
Float float32 `redis:"float"`
Float64 float64 `redis:"float64"`
Bool bool `redis:"bool"`
String string `redis:"string"`
Bytes []byte `redis:"byte"`
Int int `redis:"int"`
Int8 int8 `redis:"int8"`
Int16 int16 `redis:"int16"`
Int32 int32 `redis:"int32"`
Int64 int64 `redis:"int64"`
Uint uint `redis:"uint"`
Uint8 uint8 `redis:"uint8"`
Uint16 uint16 `redis:"uint16"`
Uint32 uint32 `redis:"uint32"`
Uint64 uint64 `redis:"uint64"`
Float float32 `redis:"float"`
Float64 float64 `redis:"float64"`
Bool bool `redis:"bool"`
StringPointer *string `redis:"stringPointer"`
IntPointer *int `redis:"intPointer"`
Int8Pointer *int8 `redis:"int8Pointer"`
Int16Pointer *int16 `redis:"int16Pointer"`
Int32Pointer *int32 `redis:"int32Pointer"`
Int64Pointer *int64 `redis:"int64Pointer"`
UintPointer *uint `redis:"uintPointer"`
Uint8Pointer *uint8 `redis:"uint8Pointer"`
Uint16Pointer *uint16 `redis:"uint16Pointer"`
Uint32Pointer *uint32 `redis:"uint32Pointer"`
Uint64Pointer *uint64 `redis:"uint64Pointer"`
FloatPointer *float32 `redis:"floatPointer"`
Float64Pointer *float64 `redis:"float64Pointer"`
BoolPointer *bool `redis:"boolPointer"`
}

type TimeRFC3339Nano struct {
Expand Down Expand Up @@ -188,6 +202,31 @@ var _ = Describe("Scan", func() {
Float64: 1.2345678912345678e+17,
Bool: true,
}))

// Scan to pointers
var String = "str"
var Int int = 123
var Int64 int64 = 123456789123456789
var Uint uint = 456
var Uint64 uint64 = 987654321987654321
var Float float32 = 123.456
var Float64 float64 = 1.2345678912345678e+17
var Bool bool = true

var d3 data
keys = []string{"stringPointer", "intPointer", "int64Pointer", "uintPointer", "uint64Pointer", "floatPointer", "float64Pointer", "boolPointer"}
vals = i{"str", "123", "123456789123456789", "456", "987654321987654321", "123.456", "123456789123456789.987654321987654321", "1"}
Expect(Scan(&d3, keys, vals)).NotTo(HaveOccurred())
Expect(d3).To(Equal(data{
StringPointer: &String,
IntPointer: &Int,
Int64Pointer: &Int64,
UintPointer: &Uint,
Uint64Pointer: &Uint64,
FloatPointer: &Float,
Float64Pointer: &Float64,
BoolPointer: &Bool,
}))
})

It("omits untagged fields", func() {
Expand Down
15 changes: 13 additions & 2 deletions rueidiscompat/structmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,19 @@ func newStructSpec(t reflect.Type, fieldTag string) *structSpec {
continue
}

// Use the built-in decoder.
out.set(tag, &structField{index: i, fn: decoders[f.Type.Kind()]})
// Added a check for Pointer here. If it's a Poiner use the built-in decoder of the element.
// This works, because in Scan() #129-131
// if isPtr && v.IsNil() {
// v.Set(reflect.New(v.Type().Elem()))
// }
// A new value is set

if f.Type.Kind() == reflect.Pointer {
out.set(tag, &structField{index: i, fn: decoders[f.Type.Elem().Kind()]})
} else {
// Use the built-in decoder.
out.set(tag, &structField{index: i, fn: decoders[f.Type.Kind()]})
}
}

return out
Expand Down

0 comments on commit 78859ba

Please sign in to comment.