1 package proto
2
3 import (
4 "encoding"
5 "fmt"
6 "reflect"
7
8 "github.com/go-redis/redis/internal/util"
9 )
10
11 func Scan(b []byte, v interface{}) error {
12 switch v := v.(type) {
13 case nil:
14 return fmt.Errorf("redis: Scan(nil)")
15 case *string:
16 *v = util.BytesToString(b)
17 return nil
18 case *[]byte:
19 *v = b
20 return nil
21 case *int:
22 var err error
23 *v, err = util.Atoi(b)
24 return err
25 case *int8:
26 n, err := util.ParseInt(b, 10, 8)
27 if err != nil {
28 return err
29 }
30 *v = int8(n)
31 return nil
32 case *int16:
33 n, err := util.ParseInt(b, 10, 16)
34 if err != nil {
35 return err
36 }
37 *v = int16(n)
38 return nil
39 case *int32:
40 n, err := util.ParseInt(b, 10, 32)
41 if err != nil {
42 return err
43 }
44 *v = int32(n)
45 return nil
46 case *int64:
47 n, err := util.ParseInt(b, 10, 64)
48 if err != nil {
49 return err
50 }
51 *v = n
52 return nil
53 case *uint:
54 n, err := util.ParseUint(b, 10, 64)
55 if err != nil {
56 return err
57 }
58 *v = uint(n)
59 return nil
60 case *uint8:
61 n, err := util.ParseUint(b, 10, 8)
62 if err != nil {
63 return err
64 }
65 *v = uint8(n)
66 return nil
67 case *uint16:
68 n, err := util.ParseUint(b, 10, 16)
69 if err != nil {
70 return err
71 }
72 *v = uint16(n)
73 return nil
74 case *uint32:
75 n, err := util.ParseUint(b, 10, 32)
76 if err != nil {
77 return err
78 }
79 *v = uint32(n)
80 return nil
81 case *uint64:
82 n, err := util.ParseUint(b, 10, 64)
83 if err != nil {
84 return err
85 }
86 *v = n
87 return nil
88 case *float32:
89 n, err := util.ParseFloat(b, 32)
90 if err != nil {
91 return err
92 }
93 *v = float32(n)
94 return err
95 case *float64:
96 var err error
97 *v, err = util.ParseFloat(b, 64)
98 return err
99 case *bool:
100 *v = len(b) == 1 && b[0] == '1'
101 return nil
102 case encoding.BinaryUnmarshaler:
103 return v.UnmarshalBinary(b)
104 default:
105 return fmt.Errorf(
106 "redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v)
107 }
108 }
109
110 func ScanSlice(data []string, slice interface{}) error {
111 v := reflect.ValueOf(slice)
112 if !v.IsValid() {
113 return fmt.Errorf("redis: ScanSlice(nil)")
114 }
115 if v.Kind() != reflect.Ptr {
116 return fmt.Errorf("redis: ScanSlice(non-pointer %T)", slice)
117 }
118 v = v.Elem()
119 if v.Kind() != reflect.Slice {
120 return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice)
121 }
122
123 next := makeSliceNextElemFunc(v)
124 for i, s := range data {
125 elem := next()
126 if err := Scan([]byte(s), elem.Addr().Interface()); err != nil {
127 err = fmt.Errorf("redis: ScanSlice index=%d value=%q failed: %s", i, s, err)
128 return err
129 }
130 }
131
132 return nil
133 }
134
135 func makeSliceNextElemFunc(v reflect.Value) func() reflect.Value {
136 elemType := v.Type().Elem()
137
138 if elemType.Kind() == reflect.Ptr {
139 elemType = elemType.Elem()
140 return func() reflect.Value {
141 if v.Len() < v.Cap() {
142 v.Set(v.Slice(0, v.Len()+1))
143 elem := v.Index(v.Len() - 1)
144 if elem.IsNil() {
145 elem.Set(reflect.New(elemType))
146 }
147 return elem.Elem()
148 }
149
150 elem := reflect.New(elemType)
151 v.Set(reflect.Append(v, elem))
152 return elem.Elem()
153 }
154 }
155
156 zero := reflect.Zero(elemType)
157 return func() reflect.Value {
158 if v.Len() < v.Cap() {
159 v.Set(v.Slice(0, v.Len()+1))
160 return v.Index(v.Len() - 1)
161 }
162
163 v.Set(reflect.Append(v, zero))
164 return v.Index(v.Len() - 1)
165 }
166 }
167
View as plain text