diff options
Diffstat (limited to 'vendor/github.com/go-redis/redis/v7/internal/proto/scan.go')
-rw-r--r-- | vendor/github.com/go-redis/redis/v7/internal/proto/scan.go | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/vendor/github.com/go-redis/redis/v7/internal/proto/scan.go b/vendor/github.com/go-redis/redis/v7/internal/proto/scan.go new file mode 100644 index 0000000000..90c1e4ae6e --- /dev/null +++ b/vendor/github.com/go-redis/redis/v7/internal/proto/scan.go @@ -0,0 +1,166 @@ +package proto + +import ( + "encoding" + "fmt" + "reflect" + + "github.com/go-redis/redis/v7/internal/util" +) + +func Scan(b []byte, v interface{}) error { + switch v := v.(type) { + case nil: + return fmt.Errorf("redis: Scan(nil)") + case *string: + *v = util.BytesToString(b) + return nil + case *[]byte: + *v = b + return nil + case *int: + var err error + *v, err = util.Atoi(b) + return err + case *int8: + n, err := util.ParseInt(b, 10, 8) + if err != nil { + return err + } + *v = int8(n) + return nil + case *int16: + n, err := util.ParseInt(b, 10, 16) + if err != nil { + return err + } + *v = int16(n) + return nil + case *int32: + n, err := util.ParseInt(b, 10, 32) + if err != nil { + return err + } + *v = int32(n) + return nil + case *int64: + n, err := util.ParseInt(b, 10, 64) + if err != nil { + return err + } + *v = n + return nil + case *uint: + n, err := util.ParseUint(b, 10, 64) + if err != nil { + return err + } + *v = uint(n) + return nil + case *uint8: + n, err := util.ParseUint(b, 10, 8) + if err != nil { + return err + } + *v = uint8(n) + return nil + case *uint16: + n, err := util.ParseUint(b, 10, 16) + if err != nil { + return err + } + *v = uint16(n) + return nil + case *uint32: + n, err := util.ParseUint(b, 10, 32) + if err != nil { + return err + } + *v = uint32(n) + return nil + case *uint64: + n, err := util.ParseUint(b, 10, 64) + if err != nil { + return err + } + *v = n + return nil + case *float32: + n, err := util.ParseFloat(b, 32) + if err != nil { + return err + } + *v = float32(n) + return err + case *float64: + var err error + *v, err = util.ParseFloat(b, 64) + return err + case *bool: + *v = len(b) == 1 && b[0] == '1' + return nil + case encoding.BinaryUnmarshaler: + return v.UnmarshalBinary(b) + default: + return fmt.Errorf( + "redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v) + } +} + +func ScanSlice(data []string, slice interface{}) error { + v := reflect.ValueOf(slice) + if !v.IsValid() { + return fmt.Errorf("redis: ScanSlice(nil)") + } + if v.Kind() != reflect.Ptr { + return fmt.Errorf("redis: ScanSlice(non-pointer %T)", slice) + } + v = v.Elem() + if v.Kind() != reflect.Slice { + return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice) + } + + next := makeSliceNextElemFunc(v) + for i, s := range data { + elem := next() + if err := Scan([]byte(s), elem.Addr().Interface()); err != nil { + err = fmt.Errorf("redis: ScanSlice index=%d value=%q failed: %s", i, s, err) + return err + } + } + + return nil +} + +func makeSliceNextElemFunc(v reflect.Value) func() reflect.Value { + elemType := v.Type().Elem() + + if elemType.Kind() == reflect.Ptr { + elemType = elemType.Elem() + return func() reflect.Value { + if v.Len() < v.Cap() { + v.Set(v.Slice(0, v.Len()+1)) + elem := v.Index(v.Len() - 1) + if elem.IsNil() { + elem.Set(reflect.New(elemType)) + } + return elem.Elem() + } + + elem := reflect.New(elemType) + v.Set(reflect.Append(v, elem)) + return elem.Elem() + } + } + + zero := reflect.Zero(elemType) + return func() reflect.Value { + if v.Len() < v.Cap() { + v.Set(v.Slice(0, v.Len()+1)) + return v.Index(v.Len() - 1) + } + + v.Set(reflect.Append(v, zero)) + return v.Index(v.Len() - 1) + } +} |