diff options
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.go | 92 |
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 |