|
@@ -32,11 +32,25 @@ func ensureLen(d reflect.Value, n int) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func cannotConvert(d reflect.Value, s interface{}) error {
|
|
func cannotConvert(d reflect.Value, s interface{}) error {
|
|
|
- return fmt.Errorf("redigo: Scan cannot convert from %s to %s",
|
|
|
|
|
- reflect.TypeOf(s), d.Type())
|
|
|
|
|
|
|
+ var sname string
|
|
|
|
|
+ switch s.(type) {
|
|
|
|
|
+ case string:
|
|
|
|
|
+ sname = "Redis simple string"
|
|
|
|
|
+ case Error:
|
|
|
|
|
+ sname = "Redis error"
|
|
|
|
|
+ case int64:
|
|
|
|
|
+ sname = "Redis integer"
|
|
|
|
|
+ case []byte:
|
|
|
|
|
+ sname = "Redis bulk string"
|
|
|
|
|
+ case []interface{}:
|
|
|
|
|
+ sname = "Redis array"
|
|
|
|
|
+ default:
|
|
|
|
|
+ sname = reflect.TypeOf(s).String()
|
|
|
|
|
+ }
|
|
|
|
|
+ return fmt.Errorf("cannot convert from %s to %s", sname, d.Type())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func convertAssignBytes(d reflect.Value, s []byte) (err error) {
|
|
|
|
|
|
|
+func convertAssignBulkString(d reflect.Value, s []byte) (err error) {
|
|
|
switch d.Type().Kind() {
|
|
switch d.Type().Kind() {
|
|
|
case reflect.Float32, reflect.Float64:
|
|
case reflect.Float32, reflect.Float64:
|
|
|
var x float64
|
|
var x float64
|
|
@@ -98,7 +112,7 @@ func convertAssignInt(d reflect.Value, s int64) (err error) {
|
|
|
func convertAssignValue(d reflect.Value, s interface{}) (err error) {
|
|
func convertAssignValue(d reflect.Value, s interface{}) (err error) {
|
|
|
switch s := s.(type) {
|
|
switch s := s.(type) {
|
|
|
case []byte:
|
|
case []byte:
|
|
|
- err = convertAssignBytes(d, s)
|
|
|
|
|
|
|
+ err = convertAssignBulkString(d, s)
|
|
|
case int64:
|
|
case int64:
|
|
|
err = convertAssignInt(d, s)
|
|
err = convertAssignInt(d, s)
|
|
|
default:
|
|
default:
|
|
@@ -107,7 +121,7 @@ func convertAssignValue(d reflect.Value, s interface{}) (err error) {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func convertAssignValues(d reflect.Value, s []interface{}) error {
|
|
|
|
|
|
|
+func convertAssignArray(d reflect.Value, s []interface{}) error {
|
|
|
if d.Type().Kind() != reflect.Slice {
|
|
if d.Type().Kind() != reflect.Slice {
|
|
|
return cannotConvert(d, s)
|
|
return cannotConvert(d, s)
|
|
|
}
|
|
}
|
|
@@ -144,7 +158,7 @@ func convertAssign(d interface{}, s interface{}) (err error) {
|
|
|
if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
|
|
if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
|
|
|
err = cannotConvert(d, s)
|
|
err = cannotConvert(d, s)
|
|
|
} else {
|
|
} else {
|
|
|
- err = convertAssignBytes(d.Elem(), s)
|
|
|
|
|
|
|
+ err = convertAssignBulkString(d.Elem(), s)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
case int64:
|
|
case int64:
|
|
@@ -181,7 +195,7 @@ func convertAssign(d interface{}, s interface{}) (err error) {
|
|
|
if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
|
|
if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
|
|
|
err = cannotConvert(d, s)
|
|
err = cannotConvert(d, s)
|
|
|
} else {
|
|
} else {
|
|
|
- err = convertAssignValues(d.Elem(), s)
|
|
|
|
|
|
|
+ err = convertAssignArray(d.Elem(), s)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
case Error:
|
|
case Error:
|
|
@@ -206,12 +220,13 @@ func convertAssign(d interface{}, s interface{}) (err error) {
|
|
|
// following the copied values.
|
|
// following the copied values.
|
|
|
func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
|
|
func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
|
|
|
if len(src) < len(dest) {
|
|
if len(src) < len(dest) {
|
|
|
- return nil, errors.New("redigo: Scan array short")
|
|
|
|
|
|
|
+ return nil, errors.New("redigo.Scan: array short")
|
|
|
}
|
|
}
|
|
|
var err error
|
|
var err error
|
|
|
for i, d := range dest {
|
|
for i, d := range dest {
|
|
|
err = convertAssign(d, src[i])
|
|
err = convertAssign(d, src[i])
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
|
+ err = fmt.Errorf("redigo.Scan: cannot assign to dest %d: %v", i, err)
|
|
|
break
|
|
break
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -261,7 +276,7 @@ func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *st
|
|
|
//case "omitempty":
|
|
//case "omitempty":
|
|
|
// fs.omitempty = true
|
|
// fs.omitempty = true
|
|
|
default:
|
|
default:
|
|
|
- panic(errors.New("redigo: unknown field flag " + s + " for type " + t.Name()))
|
|
|
|
|
|
|
+ panic(fmt.Errorf("redigo: unknown field tag %s for type %s", s, t.Name()))
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -321,7 +336,7 @@ func structSpecForType(t reflect.Type) *structSpec {
|
|
|
return ss
|
|
return ss
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-var errScanStructValue = errors.New("redigo: ScanStruct value must be non-nil pointer to a struct")
|
|
|
|
|
|
|
+var errScanStructValue = errors.New("redigo.ScanStruct: value must be non-nil pointer to a struct")
|
|
|
|
|
|
|
|
// ScanStruct scans alternating names and values from src to a struct. The
|
|
// ScanStruct scans alternating names and values from src to a struct. The
|
|
|
// HGETALL and CONFIG GET commands return replies in this format.
|
|
// HGETALL and CONFIG GET commands return replies in this format.
|
|
@@ -350,7 +365,7 @@ func ScanStruct(src []interface{}, dest interface{}) error {
|
|
|
ss := structSpecForType(d.Type())
|
|
ss := structSpecForType(d.Type())
|
|
|
|
|
|
|
|
if len(src)%2 != 0 {
|
|
if len(src)%2 != 0 {
|
|
|
- return errors.New("redigo: ScanStruct expects even number of values in values")
|
|
|
|
|
|
|
+ return errors.New("redigo.ScanStruct: number of values not a multiple of 2")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(src); i += 2 {
|
|
for i := 0; i < len(src); i += 2 {
|
|
@@ -360,21 +375,21 @@ func ScanStruct(src []interface{}, dest interface{}) error {
|
|
|
}
|
|
}
|
|
|
name, ok := src[i].([]byte)
|
|
name, ok := src[i].([]byte)
|
|
|
if !ok {
|
|
if !ok {
|
|
|
- return errors.New("redigo: ScanStruct key not a bulk string value")
|
|
|
|
|
|
|
+ return fmt.Errorf("redigo.ScanStruct: key %d not a bulk string value", i)
|
|
|
}
|
|
}
|
|
|
fs := ss.fieldSpec(name)
|
|
fs := ss.fieldSpec(name)
|
|
|
if fs == nil {
|
|
if fs == nil {
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
|
|
if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
|
|
|
- return err
|
|
|
|
|
|
|
+ return fmt.Errorf("redigo.ScanStruct: cannot assign field %s: %v", fs.name, err)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
var (
|
|
|
- errScanSliceValue = errors.New("redigo: ScanSlice dest must be non-nil pointer to a struct")
|
|
|
|
|
|
|
+ errScanSliceValue = errors.New("redigo.ScanSlice: dest must be non-nil pointer to a struct")
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// ScanSlice scans src to the slice pointed to by dest. The elements the dest
|
|
// ScanSlice scans src to the slice pointed to by dest. The elements the dest
|
|
@@ -407,7 +422,7 @@ func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
if err := convertAssignValue(d.Index(i), s); err != nil {
|
|
if err := convertAssignValue(d.Index(i), s); err != nil {
|
|
|
- return err
|
|
|
|
|
|
|
+ return fmt.Errorf("redigo.ScanSlice: cannot assign element %d: %v", i, err)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return nil
|
|
return nil
|
|
@@ -420,18 +435,18 @@ func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error
|
|
|
for i, name := range fieldNames {
|
|
for i, name := range fieldNames {
|
|
|
fss[i] = ss.m[name]
|
|
fss[i] = ss.m[name]
|
|
|
if fss[i] == nil {
|
|
if fss[i] == nil {
|
|
|
- return errors.New("redigo: ScanSlice bad field name " + name)
|
|
|
|
|
|
|
+ return fmt.Errorf("redigo.ScanSlice: ScanSlice bad field name %s", name)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if len(fss) == 0 {
|
|
if len(fss) == 0 {
|
|
|
- return errors.New("redigo: ScanSlice no struct fields")
|
|
|
|
|
|
|
+ return errors.New("redigo.ScanSlice: no struct fields")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
n := len(src) / len(fss)
|
|
n := len(src) / len(fss)
|
|
|
if n*len(fss) != len(src) {
|
|
if n*len(fss) != len(src) {
|
|
|
- return errors.New("redigo: ScanSlice length not a multiple of struct field count")
|
|
|
|
|
|
|
+ return errors.New("redigo.ScanSlice: length not a multiple of struct field count")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ensureLen(d, n)
|
|
ensureLen(d, n)
|
|
@@ -449,7 +464,7 @@ func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
|
|
if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
|
|
|
- return err
|
|
|
|
|
|
|
+ return fmt.Errorf("redigo.ScanSlice: cannot assign element %d to field %s: %v", i*len(fss)+j, fs.name, err)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|