parser.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package redis
  2. import (
  3. "errors"
  4. "fmt"
  5. "strconv"
  6. "gopkg.in/bufio.v1"
  7. )
  8. type multiBulkParser func(rd *bufio.Reader, n int64) (interface{}, error)
  9. var (
  10. errReaderTooSmall = errors.New("redis: reader is too small")
  11. )
  12. //------------------------------------------------------------------------------
  13. func appendArgs(buf []byte, args []string) []byte {
  14. buf = append(buf, '*')
  15. buf = strconv.AppendUint(buf, uint64(len(args)), 10)
  16. buf = append(buf, '\r', '\n')
  17. for _, arg := range args {
  18. buf = append(buf, '$')
  19. buf = strconv.AppendUint(buf, uint64(len(arg)), 10)
  20. buf = append(buf, '\r', '\n')
  21. buf = append(buf, arg...)
  22. buf = append(buf, '\r', '\n')
  23. }
  24. return buf
  25. }
  26. //------------------------------------------------------------------------------
  27. func readLine(rd *bufio.Reader) ([]byte, error) {
  28. line, isPrefix, err := rd.ReadLine()
  29. if err != nil {
  30. return line, err
  31. }
  32. if isPrefix {
  33. return line, errReaderTooSmall
  34. }
  35. return line, nil
  36. }
  37. func readN(rd *bufio.Reader, n int) ([]byte, error) {
  38. b, err := rd.ReadN(n)
  39. if err == bufio.ErrBufferFull {
  40. tmp := make([]byte, n)
  41. r := copy(tmp, b)
  42. b = tmp
  43. for {
  44. nn, err := rd.Read(b[r:])
  45. r += nn
  46. if r >= n {
  47. // Ignore error if we read enough.
  48. break
  49. }
  50. if err != nil {
  51. return nil, err
  52. }
  53. }
  54. } else if err != nil {
  55. return nil, err
  56. }
  57. return b, nil
  58. }
  59. //------------------------------------------------------------------------------
  60. func parseReq(rd *bufio.Reader) ([]string, error) {
  61. line, err := readLine(rd)
  62. if err != nil {
  63. return nil, err
  64. }
  65. if line[0] != '*' {
  66. return []string{string(line)}, nil
  67. }
  68. numReplies, err := strconv.ParseInt(string(line[1:]), 10, 64)
  69. if err != nil {
  70. return nil, err
  71. }
  72. args := make([]string, 0, numReplies)
  73. for i := int64(0); i < numReplies; i++ {
  74. line, err = readLine(rd)
  75. if err != nil {
  76. return nil, err
  77. }
  78. if line[0] != '$' {
  79. return nil, fmt.Errorf("redis: expected '$', but got %q", line)
  80. }
  81. argLen, err := strconv.ParseInt(string(line[1:]), 10, 32)
  82. if err != nil {
  83. return nil, err
  84. }
  85. arg, err := readN(rd, int(argLen)+2)
  86. if err != nil {
  87. return nil, err
  88. }
  89. args = append(args, string(arg[:argLen]))
  90. }
  91. return args, nil
  92. }
  93. //------------------------------------------------------------------------------
  94. func parseReply(rd *bufio.Reader, p multiBulkParser) (interface{}, error) {
  95. line, err := readLine(rd)
  96. if err != nil {
  97. return nil, err
  98. }
  99. switch line[0] {
  100. case '-':
  101. return nil, errorf(string(line[1:]))
  102. case '+':
  103. return string(line[1:]), nil
  104. case ':':
  105. v, err := strconv.ParseInt(string(line[1:]), 10, 64)
  106. if err != nil {
  107. return nil, err
  108. }
  109. return v, nil
  110. case '$':
  111. if len(line) == 3 && line[1] == '-' && line[2] == '1' {
  112. return nil, Nil
  113. }
  114. replyLen, err := strconv.Atoi(string(line[1:]))
  115. if err != nil {
  116. return nil, err
  117. }
  118. b, err := readN(rd, replyLen+2)
  119. if err != nil {
  120. return nil, err
  121. }
  122. return string(b[:replyLen]), nil
  123. case '*':
  124. if len(line) == 3 && line[1] == '-' && line[2] == '1' {
  125. return nil, Nil
  126. }
  127. repliesNum, err := strconv.ParseInt(string(line[1:]), 10, 64)
  128. if err != nil {
  129. return nil, err
  130. }
  131. return p(rd, repliesNum)
  132. }
  133. return nil, fmt.Errorf("redis: can't parse %q", line)
  134. }
  135. func parseSlice(rd *bufio.Reader, n int64) (interface{}, error) {
  136. vals := make([]interface{}, 0, n)
  137. for i := int64(0); i < n; i++ {
  138. v, err := parseReply(rd, parseSlice)
  139. if err == Nil {
  140. vals = append(vals, nil)
  141. } else if err != nil {
  142. return nil, err
  143. } else {
  144. vals = append(vals, v)
  145. }
  146. }
  147. return vals, nil
  148. }
  149. func parseStringSlice(rd *bufio.Reader, n int64) (interface{}, error) {
  150. vals := make([]string, 0, n)
  151. for i := int64(0); i < n; i++ {
  152. viface, err := parseReply(rd, nil)
  153. if err != nil {
  154. return nil, err
  155. }
  156. v, ok := viface.(string)
  157. if !ok {
  158. return nil, fmt.Errorf("got %T, expected string", viface)
  159. }
  160. vals = append(vals, v)
  161. }
  162. return vals, nil
  163. }
  164. func parseBoolSlice(rd *bufio.Reader, n int64) (interface{}, error) {
  165. vals := make([]bool, 0, n)
  166. for i := int64(0); i < n; i++ {
  167. viface, err := parseReply(rd, nil)
  168. if err != nil {
  169. return nil, err
  170. }
  171. v, ok := viface.(int64)
  172. if !ok {
  173. return nil, fmt.Errorf("got %T, expected int64", viface)
  174. }
  175. vals = append(vals, v == 1)
  176. }
  177. return vals, nil
  178. }
  179. func parseStringStringMap(rd *bufio.Reader, n int64) (interface{}, error) {
  180. m := make(map[string]string, n/2)
  181. for i := int64(0); i < n; i += 2 {
  182. keyiface, err := parseReply(rd, nil)
  183. if err != nil {
  184. return nil, err
  185. }
  186. key, ok := keyiface.(string)
  187. if !ok {
  188. return nil, fmt.Errorf("got %T, expected string", keyiface)
  189. }
  190. valueiface, err := parseReply(rd, nil)
  191. if err != nil {
  192. return nil, err
  193. }
  194. value, ok := valueiface.(string)
  195. if !ok {
  196. return nil, fmt.Errorf("got %T, expected string", valueiface)
  197. }
  198. m[key] = value
  199. }
  200. return m, nil
  201. }
  202. func parseZSlice(rd *bufio.Reader, n int64) (interface{}, error) {
  203. zz := make([]Z, n/2)
  204. for i := int64(0); i < n; i += 2 {
  205. z := &zz[i/2]
  206. memberiface, err := parseReply(rd, nil)
  207. if err != nil {
  208. return nil, err
  209. }
  210. member, ok := memberiface.(string)
  211. if !ok {
  212. return nil, fmt.Errorf("got %T, expected string", memberiface)
  213. }
  214. z.Member = member
  215. scoreiface, err := parseReply(rd, nil)
  216. if err != nil {
  217. return nil, err
  218. }
  219. scorestr, ok := scoreiface.(string)
  220. if !ok {
  221. return nil, fmt.Errorf("got %T, expected string", scoreiface)
  222. }
  223. score, err := strconv.ParseFloat(scorestr, 64)
  224. if err != nil {
  225. return nil, err
  226. }
  227. z.Score = score
  228. }
  229. return zz, nil
  230. }