You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

reader.go 5.5KB

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