mirror of
https://github.com/redis/go-redis.git
synced 2025-07-29 17:41:15 +03:00
hscan adds support for i386 platform (#1652)
* hscan adds support for i386 platform Signed-off-by: monkey <monkey92t@gmail.com> * update go.sum Signed-off-by: monkey <monkey92t@gmail.com> * detect overflow of scan Signed-off-by: monkey <golang@88.com> * restore the return value type of decoderFunc to error Signed-off-by: monkey <golang@88.com> * fix clean Signed-off-by: monkey <golang@88.com> * fix clean Signed-off-by: monkey <golang@88.com> Co-authored-by: Monkey <monkey@MonkeydeiMac.local>
This commit is contained in:
@ -15,17 +15,17 @@ var (
|
||||
decoders = []decoderFunc{
|
||||
reflect.Bool: decodeBool,
|
||||
reflect.Int: decodeInt,
|
||||
reflect.Int8: decodeInt,
|
||||
reflect.Int16: decodeInt,
|
||||
reflect.Int32: decodeInt,
|
||||
reflect.Int64: decodeInt,
|
||||
reflect.Int8: decodeInt8,
|
||||
reflect.Int16: decodeInt16,
|
||||
reflect.Int32: decodeInt32,
|
||||
reflect.Int64: decodeInt64,
|
||||
reflect.Uint: decodeUint,
|
||||
reflect.Uint8: decodeUint,
|
||||
reflect.Uint16: decodeUint,
|
||||
reflect.Uint32: decodeUint,
|
||||
reflect.Uint64: decodeUint,
|
||||
reflect.Float32: decodeFloat,
|
||||
reflect.Float64: decodeFloat,
|
||||
reflect.Uint8: decodeUint8,
|
||||
reflect.Uint16: decodeUint16,
|
||||
reflect.Uint32: decodeUint32,
|
||||
reflect.Uint64: decodeUint64,
|
||||
reflect.Float32: decodeFloat32,
|
||||
reflect.Float64: decodeFloat64,
|
||||
reflect.Complex64: decodeUnsupported,
|
||||
reflect.Complex128: decodeUnsupported,
|
||||
reflect.Array: decodeUnsupported,
|
||||
@ -106,8 +106,28 @@ func decodeBool(f reflect.Value, s string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeInt8(f reflect.Value, s string) error {
|
||||
return decodeNumber(f, s, 8)
|
||||
}
|
||||
|
||||
func decodeInt16(f reflect.Value, s string) error {
|
||||
return decodeNumber(f, s, 16)
|
||||
}
|
||||
|
||||
func decodeInt32(f reflect.Value, s string) error {
|
||||
return decodeNumber(f, s, 32)
|
||||
}
|
||||
|
||||
func decodeInt64(f reflect.Value, s string) error {
|
||||
return decodeNumber(f, s, 64)
|
||||
}
|
||||
|
||||
func decodeInt(f reflect.Value, s string) error {
|
||||
v, err := strconv.ParseInt(s, 10, 0)
|
||||
return decodeNumber(f, s, 0)
|
||||
}
|
||||
|
||||
func decodeNumber(f reflect.Value, s string, bitSize int) error {
|
||||
v, err := strconv.ParseInt(s, 10, bitSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -115,8 +135,28 @@ func decodeInt(f reflect.Value, s string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeUint8(f reflect.Value, s string) error {
|
||||
return decodeUnsignedNumber(f, s, 8)
|
||||
}
|
||||
|
||||
func decodeUint16(f reflect.Value, s string) error {
|
||||
return decodeUnsignedNumber(f, s, 16)
|
||||
}
|
||||
|
||||
func decodeUint32(f reflect.Value, s string) error {
|
||||
return decodeUnsignedNumber(f, s, 32)
|
||||
}
|
||||
|
||||
func decodeUint64(f reflect.Value, s string) error {
|
||||
return decodeUnsignedNumber(f, s, 64)
|
||||
}
|
||||
|
||||
func decodeUint(f reflect.Value, s string) error {
|
||||
v, err := strconv.ParseUint(s, 10, 0)
|
||||
return decodeUnsignedNumber(f, s, 0)
|
||||
}
|
||||
|
||||
func decodeUnsignedNumber(f reflect.Value, s string, bitSize int) error {
|
||||
v, err := strconv.ParseUint(s, 10, bitSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -124,8 +164,18 @@ func decodeUint(f reflect.Value, s string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeFloat(f reflect.Value, s string) error {
|
||||
v, err := strconv.ParseFloat(s, 0)
|
||||
func decodeFloat32(f reflect.Value, s string) error {
|
||||
v, err := strconv.ParseFloat(s, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.SetFloat(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// although the default is float64, but we better define it.
|
||||
func decodeFloat64(f reflect.Value, s string) error {
|
||||
v, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package hscan
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
@ -11,12 +13,21 @@ 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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
type i []interface{}
|
||||
@ -43,6 +54,47 @@ var _ = Describe("Scan", func() {
|
||||
Expect(Scan(data{}, i{"key", "string"}, i{nil, nil})).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("number out of range", func() {
|
||||
f := func(v uint64) string {
|
||||
return strconv.FormatUint(v, 10) + "1"
|
||||
}
|
||||
keys := i{"int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "float64"}
|
||||
vals := i{
|
||||
f(math.MaxInt8), f(math.MaxInt16), f(math.MaxInt32), f(math.MaxInt64),
|
||||
f(math.MaxUint8), f(math.MaxUint16), f(math.MaxUint32), strconv.FormatUint(math.MaxUint64, 10) + "1",
|
||||
"13.4028234663852886e+38", "11.79769313486231570e+308",
|
||||
}
|
||||
for k, v := range keys {
|
||||
var d data
|
||||
Expect(Scan(&d, i{v}, i{vals[k]})).To(HaveOccurred())
|
||||
}
|
||||
|
||||
//success
|
||||
f = func(v uint64) string {
|
||||
return strconv.FormatUint(v, 10)
|
||||
}
|
||||
keys = i{"int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "float64"}
|
||||
vals = i{
|
||||
f(math.MaxInt8), f(math.MaxInt16), f(math.MaxInt32), f(math.MaxInt64),
|
||||
f(math.MaxUint8), f(math.MaxUint16), f(math.MaxUint32), strconv.FormatUint(math.MaxUint64, 10),
|
||||
"3.40282346638528859811704183484516925440e+38", "1.797693134862315708145274237317043567981e+308",
|
||||
}
|
||||
var d data
|
||||
Expect(Scan(&d, keys, vals)).NotTo(HaveOccurred())
|
||||
Expect(d).To(Equal(data{
|
||||
Int8: math.MaxInt8,
|
||||
Int16: math.MaxInt16,
|
||||
Int32: math.MaxInt32,
|
||||
Int64: math.MaxInt64,
|
||||
Uint8: math.MaxUint8,
|
||||
Uint16: math.MaxUint16,
|
||||
Uint32: math.MaxUint32,
|
||||
Uint64: math.MaxUint64,
|
||||
Float: math.MaxFloat32,
|
||||
Float64: math.MaxFloat64,
|
||||
}))
|
||||
})
|
||||
|
||||
It("scans good values", func() {
|
||||
var d data
|
||||
|
||||
@ -50,16 +102,22 @@ var _ = Describe("Scan", func() {
|
||||
Expect(Scan(&d, i{"key"}, i{"value"})).NotTo(HaveOccurred())
|
||||
Expect(d).To(Equal(data{}))
|
||||
|
||||
keys := i{"string", "byte", "int", "uint", "float", "bool"}
|
||||
vals := i{"str!", "bytes!", "123", "456", "123.456", "1"}
|
||||
keys := i{"string", "byte", "int", "int64", "uint", "uint64", "float", "float64", "bool"}
|
||||
vals := i{
|
||||
"str!", "bytes!", "123", "123456789123456789", "456", "987654321987654321",
|
||||
"123.456", "123456789123456789.987654321987654321", "1",
|
||||
}
|
||||
Expect(Scan(&d, keys, vals)).NotTo(HaveOccurred())
|
||||
Expect(d).To(Equal(data{
|
||||
String: "str!",
|
||||
Bytes: []byte("bytes!"),
|
||||
Int: 123,
|
||||
Uint: 456,
|
||||
Float: 123.456,
|
||||
Bool: true,
|
||||
String: "str!",
|
||||
Bytes: []byte("bytes!"),
|
||||
Int: 123,
|
||||
Int64: 123456789123456789,
|
||||
Uint: 456,
|
||||
Uint64: 987654321987654321,
|
||||
Float: 123.456,
|
||||
Float64: 1.2345678912345678e+17,
|
||||
Bool: true,
|
||||
}))
|
||||
|
||||
// Scan a different type with the same values to test that
|
||||
@ -85,12 +143,15 @@ var _ = Describe("Scan", func() {
|
||||
|
||||
Expect(Scan(&d, i{"string", "float", "bool"}, i{"", "1", "t"})).NotTo(HaveOccurred())
|
||||
Expect(d).To(Equal(data{
|
||||
String: "",
|
||||
Bytes: []byte("bytes!"),
|
||||
Int: 123,
|
||||
Uint: 456,
|
||||
Float: 1.0,
|
||||
Bool: true,
|
||||
String: "",
|
||||
Bytes: []byte("bytes!"),
|
||||
Int: 123,
|
||||
Int64: 123456789123456789,
|
||||
Uint: 456,
|
||||
Uint64: 987654321987654321,
|
||||
Float: 1.0,
|
||||
Float64: 1.2345678912345678e+17,
|
||||
Bool: true,
|
||||
}))
|
||||
})
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hscan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -83,5 +84,10 @@ func (s StructValue) Scan(key string, value string) error {
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return field.fn(s.value.Field(field.index), value)
|
||||
if err := field.fn(s.value.Field(field.index), value); err != nil {
|
||||
t := s.value.Type()
|
||||
return fmt.Errorf("cannot scan redis.result %s into struct field %s.%s of type %s, error-%s",
|
||||
value, t.Name(), t.Field(field.index).Name, t.Field(field.index).Type, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user