9 "github.com/go-redis/redis/internal/util"
20 //------------------------------------------------------------------------------
22 const Nil = RedisError("redis: nil")
24 type RedisError string
26 func (e RedisError) Error() string { return string(e) }
28 //------------------------------------------------------------------------------
30 type MultiBulkParse func(*Reader, int64) (interface{}, error)
37 func NewReader(rd io.Reader) *Reader {
39 rd: bufio.NewReader(rd),
40 _buf: make([]byte, 64),
44 func (r *Reader) Reset(rd io.Reader) {
48 func (r *Reader) ReadLine() ([]byte, error) {
49 line, isPrefix, err := r.rd.ReadLine()
54 return nil, bufio.ErrBufferFull
57 return nil, fmt.Errorf("redis: reply is empty")
65 func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) {
66 line, err := r.ReadLine()
73 return nil, ParseErrorReply(line)
75 return string(line[1:]), nil
77 return util.ParseInt(line[1:], 10, 64)
79 return r.readStringReply(line)
81 n, err := parseArrayLen(line)
87 return nil, fmt.Errorf("redis: can't parse %.100q", line)
90 func (r *Reader) ReadIntReply() (int64, error) {
91 line, err := r.ReadLine()
97 return 0, ParseErrorReply(line)
99 return util.ParseInt(line[1:], 10, 64)
101 return 0, fmt.Errorf("redis: can't parse int reply: %.100q", line)
105 func (r *Reader) ReadString() (string, error) {
106 line, err := r.ReadLine()
112 return "", ParseErrorReply(line)
114 return r.readStringReply(line)
116 return string(line[1:]), nil
118 return string(line[1:]), nil
120 return "", fmt.Errorf("redis: can't parse reply=%.100q reading string", line)
124 func (r *Reader) readStringReply(line []byte) (string, error) {
125 if isNilReply(line) {
129 replyLen, err := strconv.Atoi(string(line[1:]))
134 b := make([]byte, replyLen+2)
135 _, err = io.ReadFull(r.rd, b)
140 return util.BytesToString(b[:replyLen]), nil
143 func (r *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) {
144 line, err := r.ReadLine()
150 return nil, ParseErrorReply(line)
152 n, err := parseArrayLen(line)
158 return nil, fmt.Errorf("redis: can't parse array reply: %.100q", line)
162 func (r *Reader) ReadArrayLen() (int64, error) {
163 line, err := r.ReadLine()
169 return 0, ParseErrorReply(line)
171 return parseArrayLen(line)
173 return 0, fmt.Errorf("redis: can't parse array reply: %.100q", line)
177 func (r *Reader) ReadScanReply() ([]string, uint64, error) {
178 n, err := r.ReadArrayLen()
183 return nil, 0, fmt.Errorf("redis: got %d elements in scan reply, expected 2", n)
186 cursor, err := r.ReadUint()
191 n, err = r.ReadArrayLen()
196 keys := make([]string, n)
197 for i := int64(0); i < n; i++ {
198 key, err := r.ReadString()
205 return keys, cursor, err
208 func (r *Reader) ReadInt() (int64, error) {
209 b, err := r.readTmpBytesReply()
213 return util.ParseInt(b, 10, 64)
216 func (r *Reader) ReadUint() (uint64, error) {
217 b, err := r.readTmpBytesReply()
221 return util.ParseUint(b, 10, 64)
224 func (r *Reader) ReadFloatReply() (float64, error) {
225 b, err := r.readTmpBytesReply()
229 return util.ParseFloat(b, 64)
232 func (r *Reader) readTmpBytesReply() ([]byte, error) {
233 line, err := r.ReadLine()
239 return nil, ParseErrorReply(line)
241 return r._readTmpBytesReply(line)
245 return nil, fmt.Errorf("redis: can't parse string reply: %.100q", line)
249 func (r *Reader) _readTmpBytesReply(line []byte) ([]byte, error) {
250 if isNilReply(line) {
254 replyLen, err := strconv.Atoi(string(line[1:]))
259 buf := r.buf(replyLen + 2)
260 _, err = io.ReadFull(r.rd, buf)
265 return buf[:replyLen], nil
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)...)
275 func isNilReply(b []byte) bool {
276 return len(b) == 3 &&
277 (b[0] == StringReply || b[0] == ArrayReply) &&
278 b[1] == '-' && b[2] == '1'
281 func ParseErrorReply(line []byte) error {
282 return RedisError(string(line[1:]))
285 func parseArrayLen(line []byte) (int64, error) {
286 if isNilReply(line) {
289 return util.ParseInt(line[1:], 10, 64)