barometer: update DMA's vendoring packages
[barometer.git] / src / dma / vendor / github.com / go-redis / redis / internal / proto / reader.go
1 package proto
2
3 import (
4         "bufio"
5         "fmt"
6         "io"
7         "strconv"
8
9         "github.com/go-redis/redis/internal/util"
10 )
11
12 const (
13         ErrorReply  = '-'
14         StatusReply = '+'
15         IntReply    = ':'
16         StringReply = '$'
17         ArrayReply  = '*'
18 )
19
20 //------------------------------------------------------------------------------
21
22 const Nil = RedisError("redis: nil")
23
24 type RedisError string
25
26 func (e RedisError) Error() string { return string(e) }
27
28 //------------------------------------------------------------------------------
29
30 type MultiBulkParse func(*Reader, int64) (interface{}, error)
31
32 type Reader struct {
33         rd   *bufio.Reader
34         _buf []byte
35 }
36
37 func NewReader(rd io.Reader) *Reader {
38         return &Reader{
39                 rd:   bufio.NewReader(rd),
40                 _buf: make([]byte, 64),
41         }
42 }
43
44 func (r *Reader) Reset(rd io.Reader) {
45         r.rd.Reset(rd)
46 }
47
48 func (r *Reader) ReadLine() ([]byte, error) {
49         line, isPrefix, err := r.rd.ReadLine()
50         if err != nil {
51                 return nil, err
52         }
53         if isPrefix {
54                 return nil, bufio.ErrBufferFull
55         }
56         if len(line) == 0 {
57                 return nil, fmt.Errorf("redis: reply is empty")
58         }
59         if isNilReply(line) {
60                 return nil, Nil
61         }
62         return line, nil
63 }
64
65 func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) {
66         line, err := r.ReadLine()
67         if err != nil {
68                 return nil, err
69         }
70
71         switch line[0] {
72         case ErrorReply:
73                 return nil, ParseErrorReply(line)
74         case StatusReply:
75                 return string(line[1:]), nil
76         case IntReply:
77                 return util.ParseInt(line[1:], 10, 64)
78         case StringReply:
79                 return r.readStringReply(line)
80         case ArrayReply:
81                 n, err := parseArrayLen(line)
82                 if err != nil {
83                         return nil, err
84                 }
85                 return m(r, n)
86         }
87         return nil, fmt.Errorf("redis: can't parse %.100q", line)
88 }
89
90 func (r *Reader) ReadIntReply() (int64, error) {
91         line, err := r.ReadLine()
92         if err != nil {
93                 return 0, err
94         }
95         switch line[0] {
96         case ErrorReply:
97                 return 0, ParseErrorReply(line)
98         case IntReply:
99                 return util.ParseInt(line[1:], 10, 64)
100         default:
101                 return 0, fmt.Errorf("redis: can't parse int reply: %.100q", line)
102         }
103 }
104
105 func (r *Reader) ReadString() (string, error) {
106         line, err := r.ReadLine()
107         if err != nil {
108                 return "", err
109         }
110         switch line[0] {
111         case ErrorReply:
112                 return "", ParseErrorReply(line)
113         case StringReply:
114                 return r.readStringReply(line)
115         case StatusReply:
116                 return string(line[1:]), nil
117         case IntReply:
118                 return string(line[1:]), nil
119         default:
120                 return "", fmt.Errorf("redis: can't parse reply=%.100q reading string", line)
121         }
122 }
123
124 func (r *Reader) readStringReply(line []byte) (string, error) {
125         if isNilReply(line) {
126                 return "", Nil
127         }
128
129         replyLen, err := strconv.Atoi(string(line[1:]))
130         if err != nil {
131                 return "", err
132         }
133
134         b := make([]byte, replyLen+2)
135         _, err = io.ReadFull(r.rd, b)
136         if err != nil {
137                 return "", err
138         }
139
140         return util.BytesToString(b[:replyLen]), nil
141 }
142
143 func (r *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) {
144         line, err := r.ReadLine()
145         if err != nil {
146                 return nil, err
147         }
148         switch line[0] {
149         case ErrorReply:
150                 return nil, ParseErrorReply(line)
151         case ArrayReply:
152                 n, err := parseArrayLen(line)
153                 if err != nil {
154                         return nil, err
155                 }
156                 return m(r, n)
157         default:
158                 return nil, fmt.Errorf("redis: can't parse array reply: %.100q", line)
159         }
160 }
161
162 func (r *Reader) ReadArrayLen() (int64, error) {
163         line, err := r.ReadLine()
164         if err != nil {
165                 return 0, err
166         }
167         switch line[0] {
168         case ErrorReply:
169                 return 0, ParseErrorReply(line)
170         case ArrayReply:
171                 return parseArrayLen(line)
172         default:
173                 return 0, fmt.Errorf("redis: can't parse array reply: %.100q", line)
174         }
175 }
176
177 func (r *Reader) ReadScanReply() ([]string, uint64, error) {
178         n, err := r.ReadArrayLen()
179         if err != nil {
180                 return nil, 0, err
181         }
182         if n != 2 {
183                 return nil, 0, fmt.Errorf("redis: got %d elements in scan reply, expected 2", n)
184         }
185
186         cursor, err := r.ReadUint()
187         if err != nil {
188                 return nil, 0, err
189         }
190
191         n, err = r.ReadArrayLen()
192         if err != nil {
193                 return nil, 0, err
194         }
195
196         keys := make([]string, n)
197         for i := int64(0); i < n; i++ {
198                 key, err := r.ReadString()
199                 if err != nil {
200                         return nil, 0, err
201                 }
202                 keys[i] = key
203         }
204
205         return keys, cursor, err
206 }
207
208 func (r *Reader) ReadInt() (int64, error) {
209         b, err := r.readTmpBytesReply()
210         if err != nil {
211                 return 0, err
212         }
213         return util.ParseInt(b, 10, 64)
214 }
215
216 func (r *Reader) ReadUint() (uint64, error) {
217         b, err := r.readTmpBytesReply()
218         if err != nil {
219                 return 0, err
220         }
221         return util.ParseUint(b, 10, 64)
222 }
223
224 func (r *Reader) ReadFloatReply() (float64, error) {
225         b, err := r.readTmpBytesReply()
226         if err != nil {
227                 return 0, err
228         }
229         return util.ParseFloat(b, 64)
230 }
231
232 func (r *Reader) readTmpBytesReply() ([]byte, error) {
233         line, err := r.ReadLine()
234         if err != nil {
235                 return nil, err
236         }
237         switch line[0] {
238         case ErrorReply:
239                 return nil, ParseErrorReply(line)
240         case StringReply:
241                 return r._readTmpBytesReply(line)
242         case StatusReply:
243                 return line[1:], nil
244         default:
245                 return nil, fmt.Errorf("redis: can't parse string reply: %.100q", line)
246         }
247 }
248
249 func (r *Reader) _readTmpBytesReply(line []byte) ([]byte, error) {
250         if isNilReply(line) {
251                 return nil, Nil
252         }
253
254         replyLen, err := strconv.Atoi(string(line[1:]))
255         if err != nil {
256                 return nil, err
257         }
258
259         buf := r.buf(replyLen + 2)
260         _, err = io.ReadFull(r.rd, buf)
261         if err != nil {
262                 return nil, err
263         }
264
265         return buf[:replyLen], nil
266 }
267
268 func (r *Reader) buf(n int) []byte {
269         if d := n - cap(r._buf); d > 0 {
270                 r._buf = append(r._buf, make([]byte, d)...)
271         }
272         return r._buf[:n]
273 }
274
275 func isNilReply(b []byte) bool {
276         return len(b) == 3 &&
277                 (b[0] == StringReply || b[0] == ArrayReply) &&
278                 b[1] == '-' && b[2] == '1'
279 }
280
281 func ParseErrorReply(line []byte) error {
282         return RedisError(string(line[1:]))
283 }
284
285 func parseArrayLen(line []byte) (int64, error) {
286         if isNilReply(line) {
287                 return 0, Nil
288         }
289         return util.ParseInt(line[1:], 10, 64)
290 }