reply.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2012 Gary Burd
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. // License for the specific language governing permissions and limitations
  13. // under the License.
  14. package redis
  15. import (
  16. "errors"
  17. "fmt"
  18. "strconv"
  19. )
  20. var ErrNil = errors.New("redigo: nil returned")
  21. func Values(multiBulk []interface{}, values ...interface{}) ([]interface{}, error) {
  22. if len(multiBulk) < len(values) {
  23. return nil, errors.New("redigo Values: short multibulk")
  24. }
  25. var err error
  26. for i, value := range values {
  27. bulk := multiBulk[i]
  28. if bulk != nil {
  29. switch value := value.(type) {
  30. case *string:
  31. *value, err = String(bulk, nil)
  32. case *int:
  33. *value, err = Int(bulk, nil)
  34. case *bool:
  35. *value, err = Bool(bulk, nil)
  36. case *[]byte:
  37. *value, err = Bytes(bulk, nil)
  38. default:
  39. panic("Value type not supported")
  40. }
  41. if err != nil {
  42. break
  43. }
  44. }
  45. }
  46. return multiBulk[len(values):], err
  47. }
  48. // Int is a helper that converts a Redis reply to an int.
  49. func Int(v interface{}, err error) (int, error) {
  50. if err != nil {
  51. return 0, err
  52. }
  53. switch v := v.(type) {
  54. case int64:
  55. return int(v), nil
  56. case []byte:
  57. n, err := strconv.ParseInt(string(v), 10, 0)
  58. return int(n), err
  59. case nil:
  60. return 0, ErrNil
  61. case Error:
  62. return 0, v
  63. }
  64. return 0, fmt.Errorf("redigo: unexpected type for Int, got type %T", v)
  65. }
  66. // String is a helper that converts a Redis reply to a string.
  67. func String(v interface{}, err error) (string, error) {
  68. if err != nil {
  69. return "", err
  70. }
  71. switch v := v.(type) {
  72. case []byte:
  73. return string(v), nil
  74. case int64:
  75. return strconv.FormatInt(v, 10), nil
  76. case nil:
  77. return "", ErrNil
  78. case Error:
  79. return "", v
  80. }
  81. panic("FOOBAR")
  82. return "", fmt.Errorf("redigo: unexpected type for String, got type %T", v)
  83. }
  84. // Bytes is a helper that converts a Redis reply to slice of bytes.
  85. func Bytes(v interface{}, err error) ([]byte, error) {
  86. if err != nil {
  87. return nil, err
  88. }
  89. switch v := v.(type) {
  90. case []byte:
  91. return v, nil
  92. case int64:
  93. return strconv.AppendInt(nil, v, 10), nil
  94. case nil:
  95. return nil, ErrNil
  96. case Error:
  97. return nil, v
  98. }
  99. return nil, fmt.Errorf("redigo: unexpected type for Bytes, got type %T", v)
  100. }
  101. // Bool is a helper that converts a Redis reply to a bool. Bool converts the
  102. // integer 0 and the bulk values "0" and "" to false. All other integer and
  103. // bulk values are converted to true. If the reply is not an integer or bulk
  104. // value or err is not equal to nil, then Bool returns an error.
  105. func Bool(v interface{}, err error) (bool, error) {
  106. if err != nil {
  107. return false, err
  108. }
  109. switch v := v.(type) {
  110. case int64:
  111. return v != 0, nil
  112. case []byte:
  113. if len(v) == 0 || (len(v) == 1 && v[0] == '0') {
  114. return false, nil
  115. }
  116. return true, nil
  117. case nil:
  118. return false, ErrNil
  119. case Error:
  120. return false, v
  121. }
  122. return false, fmt.Errorf("redigo: unexpected type for Bool, got type %T", v)
  123. }
  124. // MultiBulk is a helper that converts a Redis reply to a []interface{}. If err
  125. // is not equal to nil or the reply is not a multi-bulk reply, then MultiBulk
  126. // returns an error.
  127. func MultiBulk(v interface{}, err error) ([]interface{}, error) {
  128. if err != nil {
  129. return nil, err
  130. }
  131. switch v := v.(type) {
  132. case []interface{}:
  133. return v, nil
  134. case nil:
  135. return nil, ErrNil
  136. case Error:
  137. return nil, v
  138. }
  139. return nil, fmt.Errorf("redigo: unexpected type for MultiBulk, got type %T", v)
  140. }
  141. // Subscribe represents a subscribe or unsubscribe notification.
  142. type Subscription struct {
  143. // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe"
  144. Kind string
  145. // The channel that was changed.
  146. Channel string
  147. // The current number of subscriptions for connection.
  148. Count int
  149. }
  150. // Message represents a message notification.
  151. type Message struct {
  152. // The originating channel.
  153. Channel string
  154. // The message data.
  155. Data []byte
  156. }
  157. // Notification is a helper that returns a pub/sub notification as a
  158. // Subscription or a Message.
  159. func Notification(reply interface{}, err error) (interface{}, error) {
  160. multiBulk, err := MultiBulk(reply, err)
  161. if err != nil {
  162. return nil, err
  163. }
  164. var kind, channel string
  165. multiBulk, err = Values(multiBulk, &kind, &channel)
  166. if err != nil {
  167. return nil, err
  168. }
  169. if kind == "message" {
  170. var data []byte
  171. if _, err := Values(multiBulk, &data); err != nil {
  172. return nil, err
  173. }
  174. return Message{channel, data}, nil
  175. }
  176. var count int
  177. if _, err := Values(multiBulk, &count); err != nil {
  178. return nil, err
  179. }
  180. return Subscription{kind, channel, count}, nil
  181. }