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.

597 lines
10 KiB

  1. package redis
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "time"
  7. "gopkg.in/bufio.v1"
  8. )
  9. var (
  10. _ Cmder = (*Cmd)(nil)
  11. _ Cmder = (*SliceCmd)(nil)
  12. _ Cmder = (*StatusCmd)(nil)
  13. _ Cmder = (*IntCmd)(nil)
  14. _ Cmder = (*DurationCmd)(nil)
  15. _ Cmder = (*BoolCmd)(nil)
  16. _ Cmder = (*StringCmd)(nil)
  17. _ Cmder = (*FloatCmd)(nil)
  18. _ Cmder = (*StringSliceCmd)(nil)
  19. _ Cmder = (*BoolSliceCmd)(nil)
  20. _ Cmder = (*StringStringMapCmd)(nil)
  21. _ Cmder = (*ZSliceCmd)(nil)
  22. _ Cmder = (*ScanCmd)(nil)
  23. )
  24. type Cmder interface {
  25. args() []string
  26. parseReply(*bufio.Reader) error
  27. setErr(error)
  28. writeTimeout() *time.Duration
  29. readTimeout() *time.Duration
  30. Err() error
  31. String() string
  32. }
  33. func setCmdsErr(cmds []Cmder, e error) {
  34. for _, cmd := range cmds {
  35. cmd.setErr(e)
  36. }
  37. }
  38. func cmdString(cmd Cmder, val interface{}) string {
  39. s := strings.Join(cmd.args(), " ")
  40. if err := cmd.Err(); err != nil {
  41. return s + ": " + err.Error()
  42. }
  43. if val != nil {
  44. return s + ": " + fmt.Sprint(val)
  45. }
  46. return s
  47. }
  48. //------------------------------------------------------------------------------
  49. type baseCmd struct {
  50. _args []string
  51. err error
  52. _writeTimeout, _readTimeout *time.Duration
  53. }
  54. func newBaseCmd(args ...string) *baseCmd {
  55. return &baseCmd{
  56. _args: args,
  57. }
  58. }
  59. func (cmd *baseCmd) Err() error {
  60. if cmd.err != nil {
  61. return cmd.err
  62. }
  63. return nil
  64. }
  65. func (cmd *baseCmd) args() []string {
  66. return cmd._args
  67. }
  68. func (cmd *baseCmd) readTimeout() *time.Duration {
  69. return cmd._readTimeout
  70. }
  71. func (cmd *baseCmd) setReadTimeout(d time.Duration) {
  72. cmd._readTimeout = &d
  73. }
  74. func (cmd *baseCmd) writeTimeout() *time.Duration {
  75. return cmd._writeTimeout
  76. }
  77. func (cmd *baseCmd) setWriteTimeout(d time.Duration) {
  78. cmd._writeTimeout = &d
  79. }
  80. func (cmd *baseCmd) setErr(e error) {
  81. cmd.err = e
  82. }
  83. //------------------------------------------------------------------------------
  84. type Cmd struct {
  85. *baseCmd
  86. val interface{}
  87. }
  88. func NewCmd(args ...string) *Cmd {
  89. return &Cmd{
  90. baseCmd: newBaseCmd(args...),
  91. }
  92. }
  93. func (cmd *Cmd) Val() interface{} {
  94. return cmd.val
  95. }
  96. func (cmd *Cmd) Result() (interface{}, error) {
  97. return cmd.val, cmd.err
  98. }
  99. func (cmd *Cmd) String() string {
  100. return cmdString(cmd, cmd.val)
  101. }
  102. func (cmd *Cmd) parseReply(rd *bufio.Reader) error {
  103. cmd.val, cmd.err = parseReply(rd, parseSlice)
  104. return cmd.err
  105. }
  106. //------------------------------------------------------------------------------
  107. type SliceCmd struct {
  108. *baseCmd
  109. val []interface{}
  110. }
  111. func NewSliceCmd(args ...string) *SliceCmd {
  112. return &SliceCmd{
  113. baseCmd: newBaseCmd(args...),
  114. }
  115. }
  116. func (cmd *SliceCmd) Val() []interface{} {
  117. return cmd.val
  118. }
  119. func (cmd *SliceCmd) Result() ([]interface{}, error) {
  120. return cmd.val, cmd.err
  121. }
  122. func (cmd *SliceCmd) String() string {
  123. return cmdString(cmd, cmd.val)
  124. }
  125. func (cmd *SliceCmd) parseReply(rd *bufio.Reader) error {
  126. v, err := parseReply(rd, parseSlice)
  127. if err != nil {
  128. cmd.err = err
  129. return err
  130. }
  131. cmd.val = v.([]interface{})
  132. return nil
  133. }
  134. //------------------------------------------------------------------------------
  135. type StatusCmd struct {
  136. *baseCmd
  137. val string
  138. }
  139. func NewStatusCmd(args ...string) *StatusCmd {
  140. return &StatusCmd{
  141. baseCmd: newBaseCmd(args...),
  142. }
  143. }
  144. func (cmd *StatusCmd) Val() string {
  145. return cmd.val
  146. }
  147. func (cmd *StatusCmd) Result() (string, error) {
  148. return cmd.val, cmd.err
  149. }
  150. func (cmd *StatusCmd) String() string {
  151. return cmdString(cmd, cmd.val)
  152. }
  153. func (cmd *StatusCmd) parseReply(rd *bufio.Reader) error {
  154. v, err := parseReply(rd, nil)
  155. if err != nil {
  156. cmd.err = err
  157. return err
  158. }
  159. cmd.val = v.(string)
  160. return nil
  161. }
  162. //------------------------------------------------------------------------------
  163. type IntCmd struct {
  164. *baseCmd
  165. val int64
  166. }
  167. func NewIntCmd(args ...string) *IntCmd {
  168. return &IntCmd{
  169. baseCmd: newBaseCmd(args...),
  170. }
  171. }
  172. func (cmd *IntCmd) Val() int64 {
  173. return cmd.val
  174. }
  175. func (cmd *IntCmd) Result() (int64, error) {
  176. return cmd.val, cmd.err
  177. }
  178. func (cmd *IntCmd) String() string {
  179. return cmdString(cmd, cmd.val)
  180. }
  181. func (cmd *IntCmd) parseReply(rd *bufio.Reader) error {
  182. v, err := parseReply(rd, nil)
  183. if err != nil {
  184. cmd.err = err
  185. return err
  186. }
  187. cmd.val = v.(int64)
  188. return nil
  189. }
  190. //------------------------------------------------------------------------------
  191. type DurationCmd struct {
  192. *baseCmd
  193. val time.Duration
  194. precision time.Duration
  195. }
  196. func NewDurationCmd(precision time.Duration, args ...string) *DurationCmd {
  197. return &DurationCmd{
  198. baseCmd: newBaseCmd(args...),
  199. precision: precision,
  200. }
  201. }
  202. func (cmd *DurationCmd) Val() time.Duration {
  203. return cmd.val
  204. }
  205. func (cmd *DurationCmd) Result() (time.Duration, error) {
  206. return cmd.val, cmd.err
  207. }
  208. func (cmd *DurationCmd) String() string {
  209. return cmdString(cmd, cmd.val)
  210. }
  211. func (cmd *DurationCmd) parseReply(rd *bufio.Reader) error {
  212. v, err := parseReply(rd, nil)
  213. if err != nil {
  214. cmd.err = err
  215. return err
  216. }
  217. cmd.val = time.Duration(v.(int64)) * cmd.precision
  218. return nil
  219. }
  220. //------------------------------------------------------------------------------
  221. type BoolCmd struct {
  222. *baseCmd
  223. val bool
  224. }
  225. func NewBoolCmd(args ...string) *BoolCmd {
  226. return &BoolCmd{
  227. baseCmd: newBaseCmd(args...),
  228. }
  229. }
  230. func (cmd *BoolCmd) Val() bool {
  231. return cmd.val
  232. }
  233. func (cmd *BoolCmd) Result() (bool, error) {
  234. return cmd.val, cmd.err
  235. }
  236. func (cmd *BoolCmd) String() string {
  237. return cmdString(cmd, cmd.val)
  238. }
  239. func (cmd *BoolCmd) parseReply(rd *bufio.Reader) error {
  240. v, err := parseReply(rd, nil)
  241. if err != nil {
  242. cmd.err = err
  243. return err
  244. }
  245. cmd.val = v.(int64) == 1
  246. return nil
  247. }
  248. //------------------------------------------------------------------------------
  249. type StringCmd struct {
  250. *baseCmd
  251. val string
  252. }
  253. func NewStringCmd(args ...string) *StringCmd {
  254. return &StringCmd{
  255. baseCmd: newBaseCmd(args...),
  256. }
  257. }
  258. func (cmd *StringCmd) Val() string {
  259. return cmd.val
  260. }
  261. func (cmd *StringCmd) Result() (string, error) {
  262. return cmd.val, cmd.err
  263. }
  264. func (cmd *StringCmd) Int64() (int64, error) {
  265. if cmd.err != nil {
  266. return 0, cmd.err
  267. }
  268. return strconv.ParseInt(cmd.val, 10, 64)
  269. }
  270. func (cmd *StringCmd) Uint64() (uint64, error) {
  271. if cmd.err != nil {
  272. return 0, cmd.err
  273. }
  274. return strconv.ParseUint(cmd.val, 10, 64)
  275. }
  276. func (cmd *StringCmd) Float64() (float64, error) {
  277. if cmd.err != nil {
  278. return 0, cmd.err
  279. }
  280. return strconv.ParseFloat(cmd.val, 64)
  281. }
  282. func (cmd *StringCmd) String() string {
  283. return cmdString(cmd, cmd.val)
  284. }
  285. func (cmd *StringCmd) parseReply(rd *bufio.Reader) error {
  286. v, err := parseReply(rd, nil)
  287. if err != nil {
  288. cmd.err = err
  289. return err
  290. }
  291. cmd.val = v.(string)
  292. return nil
  293. }
  294. //------------------------------------------------------------------------------
  295. type FloatCmd struct {
  296. *baseCmd
  297. val float64
  298. }
  299. func NewFloatCmd(args ...string) *FloatCmd {
  300. return &FloatCmd{
  301. baseCmd: newBaseCmd(args...),
  302. }
  303. }
  304. func (cmd *FloatCmd) Val() float64 {
  305. return cmd.val
  306. }
  307. func (cmd *FloatCmd) String() string {
  308. return cmdString(cmd, cmd.val)
  309. }
  310. func (cmd *FloatCmd) parseReply(rd *bufio.Reader) error {
  311. v, err := parseReply(rd, nil)
  312. if err != nil {
  313. cmd.err = err
  314. return err
  315. }
  316. cmd.val, cmd.err = strconv.ParseFloat(v.(string), 64)
  317. return cmd.err
  318. }
  319. //------------------------------------------------------------------------------
  320. type StringSliceCmd struct {
  321. *baseCmd
  322. val []string
  323. }
  324. func NewStringSliceCmd(args ...string) *StringSliceCmd {
  325. return &StringSliceCmd{
  326. baseCmd: newBaseCmd(args...),
  327. }
  328. }
  329. func (cmd *StringSliceCmd) Val() []string {
  330. return cmd.val
  331. }
  332. func (cmd *StringSliceCmd) Result() ([]string, error) {
  333. return cmd.Val(), cmd.Err()
  334. }
  335. func (cmd *StringSliceCmd) String() string {
  336. return cmdString(cmd, cmd.val)
  337. }
  338. func (cmd *StringSliceCmd) parseReply(rd *bufio.Reader) error {
  339. v, err := parseReply(rd, parseStringSlice)
  340. if err != nil {
  341. cmd.err = err
  342. return err
  343. }
  344. cmd.val = v.([]string)
  345. return nil
  346. }
  347. //------------------------------------------------------------------------------
  348. type BoolSliceCmd struct {
  349. *baseCmd
  350. val []bool
  351. }
  352. func NewBoolSliceCmd(args ...string) *BoolSliceCmd {
  353. return &BoolSliceCmd{
  354. baseCmd: newBaseCmd(args...),
  355. }
  356. }
  357. func (cmd *BoolSliceCmd) Val() []bool {
  358. return cmd.val
  359. }
  360. func (cmd *BoolSliceCmd) Result() ([]bool, error) {
  361. return cmd.val, cmd.err
  362. }
  363. func (cmd *BoolSliceCmd) String() string {
  364. return cmdString(cmd, cmd.val)
  365. }
  366. func (cmd *BoolSliceCmd) parseReply(rd *bufio.Reader) error {
  367. v, err := parseReply(rd, parseBoolSlice)
  368. if err != nil {
  369. cmd.err = err
  370. return err
  371. }
  372. cmd.val = v.([]bool)
  373. return nil
  374. }
  375. //------------------------------------------------------------------------------
  376. type StringStringMapCmd struct {
  377. *baseCmd
  378. val map[string]string
  379. }
  380. func NewStringStringMapCmd(args ...string) *StringStringMapCmd {
  381. return &StringStringMapCmd{
  382. baseCmd: newBaseCmd(args...),
  383. }
  384. }
  385. func (cmd *StringStringMapCmd) Val() map[string]string {
  386. return cmd.val
  387. }
  388. func (cmd *StringStringMapCmd) Result() (map[string]string, error) {
  389. return cmd.val, cmd.err
  390. }
  391. func (cmd *StringStringMapCmd) String() string {
  392. return cmdString(cmd, cmd.val)
  393. }
  394. func (cmd *StringStringMapCmd) parseReply(rd *bufio.Reader) error {
  395. v, err := parseReply(rd, parseStringStringMap)
  396. if err != nil {
  397. cmd.err = err
  398. return err
  399. }
  400. cmd.val = v.(map[string]string)
  401. return nil
  402. }
  403. //------------------------------------------------------------------------------
  404. type ZSliceCmd struct {
  405. *baseCmd
  406. val []Z
  407. }
  408. func NewZSliceCmd(args ...string) *ZSliceCmd {
  409. return &ZSliceCmd{
  410. baseCmd: newBaseCmd(args...),
  411. }
  412. }
  413. func (cmd *ZSliceCmd) Val() []Z {
  414. return cmd.val
  415. }
  416. func (cmd *ZSliceCmd) Result() ([]Z, error) {
  417. return cmd.val, cmd.err
  418. }
  419. func (cmd *ZSliceCmd) String() string {
  420. return cmdString(cmd, cmd.val)
  421. }
  422. func (cmd *ZSliceCmd) parseReply(rd *bufio.Reader) error {
  423. v, err := parseReply(rd, parseZSlice)
  424. if err != nil {
  425. cmd.err = err
  426. return err
  427. }
  428. cmd.val = v.([]Z)
  429. return nil
  430. }
  431. //------------------------------------------------------------------------------
  432. type ScanCmd struct {
  433. *baseCmd
  434. cursor int64
  435. keys []string
  436. }
  437. func NewScanCmd(args ...string) *ScanCmd {
  438. return &ScanCmd{
  439. baseCmd: newBaseCmd(args...),
  440. }
  441. }
  442. func (cmd *ScanCmd) Val() (int64, []string) {
  443. return cmd.cursor, cmd.keys
  444. }
  445. func (cmd *ScanCmd) Result() (int64, []string, error) {
  446. return cmd.cursor, cmd.keys, cmd.err
  447. }
  448. func (cmd *ScanCmd) String() string {
  449. return cmdString(cmd, cmd.keys)
  450. }
  451. func (cmd *ScanCmd) parseReply(rd *bufio.Reader) error {
  452. vi, err := parseReply(rd, parseSlice)
  453. if err != nil {
  454. cmd.err = err
  455. return cmd.err
  456. }
  457. v := vi.([]interface{})
  458. cmd.cursor, cmd.err = strconv.ParseInt(v[0].(string), 10, 64)
  459. if cmd.err != nil {
  460. return cmd.err
  461. }
  462. keys := v[1].([]interface{})
  463. for _, keyi := range keys {
  464. cmd.keys = append(cmd.keys, keyi.(string))
  465. }
  466. return nil
  467. }