summaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan.go')
-rw-r--r--Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan.go92
1 files changed, 67 insertions, 25 deletions
diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan.go
index 8c9cfa18d..962e94bcc 100644
--- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan.go
+++ b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan.go
@@ -32,11 +32,25 @@ func ensureLen(d reflect.Value, n int) {
}
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() {
case reflect.Float32, reflect.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) {
switch s := s.(type) {
case []byte:
- err = convertAssignBytes(d, s)
+ err = convertAssignBulkString(d, s)
case int64:
err = convertAssignInt(d, s)
default:
@@ -107,7 +121,7 @@ func convertAssignValue(d reflect.Value, s interface{}) (err error) {
return err
}
-func convertAssignValues(d reflect.Value, s []interface{}) error {
+func convertAssignArray(d reflect.Value, s []interface{}) error {
if d.Type().Kind() != reflect.Slice {
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 {
err = cannotConvert(d, s)
} else {
- err = convertAssignBytes(d.Elem(), s)
+ err = convertAssignBulkString(d.Elem(), s)
}
}
case int64:
@@ -169,6 +183,13 @@ func convertAssign(d interface{}, s interface{}) (err error) {
err = convertAssignInt(d.Elem(), s)
}
}
+ case string:
+ switch d := d.(type) {
+ case *string:
+ *d = string(s)
+ default:
+ err = cannotConvert(reflect.ValueOf(d), s)
+ }
case []interface{}:
switch d := d.(type) {
case *[]interface{}:
@@ -181,7 +202,7 @@ func convertAssign(d interface{}, s interface{}) (err error) {
if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
err = cannotConvert(d, s)
} else {
- err = convertAssignValues(d.Elem(), s)
+ err = convertAssignArray(d.Elem(), s)
}
}
case Error:
@@ -206,12 +227,13 @@ func convertAssign(d interface{}, s interface{}) (err error) {
// following the copied values.
func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
if len(src) < len(dest) {
- return nil, errors.New("redigo: Scan array short")
+ return nil, errors.New("redigo.Scan: array short")
}
var err error
for i, d := range dest {
err = convertAssign(d, src[i])
if err != nil {
+ err = fmt.Errorf("redigo.Scan: cannot assign to dest %d: %v", i, err)
break
}
}
@@ -219,9 +241,9 @@ func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
}
type fieldSpec struct {
- name string
- index []int
- //omitEmpty bool
+ name string
+ index []int
+ omitEmpty bool
}
type structSpec struct {
@@ -237,7 +259,7 @@ func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *st
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
switch {
- case f.PkgPath != "":
+ case f.PkgPath != "" && !f.Anonymous:
// Ignore unexported fields.
case f.Anonymous:
// TODO: Handle pointers. Requires change to decoder and
@@ -258,10 +280,10 @@ func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *st
}
for _, s := range p[1:] {
switch s {
- //case "omitempty":
- // fs.omitempty = true
+ case "omitempty":
+ fs.omitEmpty = true
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 +343,7 @@ func structSpecForType(t reflect.Type) *structSpec {
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
// HGETALL and CONFIG GET commands return replies in this format.
@@ -350,7 +372,7 @@ func ScanStruct(src []interface{}, dest interface{}) error {
ss := structSpecForType(d.Type())
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 {
@@ -360,21 +382,21 @@ func ScanStruct(src []interface{}, dest interface{}) error {
}
name, ok := src[i].([]byte)
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)
if fs == nil {
continue
}
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
}
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
@@ -407,7 +429,7 @@ func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error
continue
}
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
@@ -420,18 +442,18 @@ func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error
for i, name := range fieldNames {
fss[i] = ss.m[name]
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 {
- return errors.New("redigo: ScanSlice no struct fields")
+ return errors.New("redigo.ScanSlice: no struct fields")
}
n := len(src) / len(fss)
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)
@@ -449,7 +471,7 @@ func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error
continue
}
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)
}
}
}
@@ -507,6 +529,26 @@ func flattenStruct(args Args, v reflect.Value) Args {
ss := structSpecForType(v.Type())
for _, fs := range ss.l {
fv := v.FieldByIndex(fs.index)
+ if fs.omitEmpty {
+ var empty = false
+ switch fv.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ empty = fv.Len() == 0
+ case reflect.Bool:
+ empty = !fv.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ empty = fv.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ empty = fv.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ empty = fv.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ empty = fv.IsNil()
+ }
+ if empty {
+ continue
+ }
+ }
args = append(args, fs.name, fv.Interface())
}
return args