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.

3473 lines
67 KiB

  1. package redis
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "time"
  8. "github.com/go-redis/redis/v8/internal"
  9. "github.com/go-redis/redis/v8/internal/hscan"
  10. "github.com/go-redis/redis/v8/internal/proto"
  11. "github.com/go-redis/redis/v8/internal/util"
  12. )
  13. type Cmder interface {
  14. Name() string
  15. FullName() string
  16. Args() []interface{}
  17. String() string
  18. stringArg(int) string
  19. firstKeyPos() int8
  20. setFirstKeyPos(int8)
  21. readTimeout() *time.Duration
  22. readReply(rd *proto.Reader) error
  23. SetErr(error)
  24. Err() error
  25. }
  26. func setCmdsErr(cmds []Cmder, e error) {
  27. for _, cmd := range cmds {
  28. if cmd.Err() == nil {
  29. cmd.SetErr(e)
  30. }
  31. }
  32. }
  33. func cmdsFirstErr(cmds []Cmder) error {
  34. for _, cmd := range cmds {
  35. if err := cmd.Err(); err != nil {
  36. return err
  37. }
  38. }
  39. return nil
  40. }
  41. func writeCmds(wr *proto.Writer, cmds []Cmder) error {
  42. for _, cmd := range cmds {
  43. if err := writeCmd(wr, cmd); err != nil {
  44. return err
  45. }
  46. }
  47. return nil
  48. }
  49. func writeCmd(wr *proto.Writer, cmd Cmder) error {
  50. return wr.WriteArgs(cmd.Args())
  51. }
  52. func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
  53. if pos := cmd.firstKeyPos(); pos != 0 {
  54. return int(pos)
  55. }
  56. switch cmd.Name() {
  57. case "eval", "evalsha":
  58. if cmd.stringArg(2) != "0" {
  59. return 3
  60. }
  61. return 0
  62. case "publish":
  63. return 1
  64. case "memory":
  65. // https://github.com/redis/redis/issues/7493
  66. if cmd.stringArg(1) == "usage" {
  67. return 2
  68. }
  69. }
  70. if info != nil {
  71. return int(info.FirstKeyPos)
  72. }
  73. return 0
  74. }
  75. func cmdString(cmd Cmder, val interface{}) string {
  76. b := make([]byte, 0, 64)
  77. for i, arg := range cmd.Args() {
  78. if i > 0 {
  79. b = append(b, ' ')
  80. }
  81. b = internal.AppendArg(b, arg)
  82. }
  83. if err := cmd.Err(); err != nil {
  84. b = append(b, ": "...)
  85. b = append(b, err.Error()...)
  86. } else if val != nil {
  87. b = append(b, ": "...)
  88. b = internal.AppendArg(b, val)
  89. }
  90. return internal.String(b)
  91. }
  92. //------------------------------------------------------------------------------
  93. type baseCmd struct {
  94. ctx context.Context
  95. args []interface{}
  96. err error
  97. keyPos int8
  98. _readTimeout *time.Duration
  99. }
  100. var _ Cmder = (*Cmd)(nil)
  101. func (cmd *baseCmd) Name() string {
  102. if len(cmd.args) == 0 {
  103. return ""
  104. }
  105. // Cmd name must be lower cased.
  106. return internal.ToLower(cmd.stringArg(0))
  107. }
  108. func (cmd *baseCmd) FullName() string {
  109. switch name := cmd.Name(); name {
  110. case "cluster", "command":
  111. if len(cmd.args) == 1 {
  112. return name
  113. }
  114. if s2, ok := cmd.args[1].(string); ok {
  115. return name + " " + s2
  116. }
  117. return name
  118. default:
  119. return name
  120. }
  121. }
  122. func (cmd *baseCmd) Args() []interface{} {
  123. return cmd.args
  124. }
  125. func (cmd *baseCmd) stringArg(pos int) string {
  126. if pos < 0 || pos >= len(cmd.args) {
  127. return ""
  128. }
  129. s, _ := cmd.args[pos].(string)
  130. return s
  131. }
  132. func (cmd *baseCmd) firstKeyPos() int8 {
  133. return cmd.keyPos
  134. }
  135. func (cmd *baseCmd) setFirstKeyPos(keyPos int8) {
  136. cmd.keyPos = keyPos
  137. }
  138. func (cmd *baseCmd) SetErr(e error) {
  139. cmd.err = e
  140. }
  141. func (cmd *baseCmd) Err() error {
  142. return cmd.err
  143. }
  144. func (cmd *baseCmd) readTimeout() *time.Duration {
  145. return cmd._readTimeout
  146. }
  147. func (cmd *baseCmd) setReadTimeout(d time.Duration) {
  148. cmd._readTimeout = &d
  149. }
  150. //------------------------------------------------------------------------------
  151. type Cmd struct {
  152. baseCmd
  153. val interface{}
  154. }
  155. func NewCmd(ctx context.Context, args ...interface{}) *Cmd {
  156. return &Cmd{
  157. baseCmd: baseCmd{
  158. ctx: ctx,
  159. args: args,
  160. },
  161. }
  162. }
  163. func (cmd *Cmd) String() string {
  164. return cmdString(cmd, cmd.val)
  165. }
  166. func (cmd *Cmd) SetVal(val interface{}) {
  167. cmd.val = val
  168. }
  169. func (cmd *Cmd) Val() interface{} {
  170. return cmd.val
  171. }
  172. func (cmd *Cmd) Result() (interface{}, error) {
  173. return cmd.val, cmd.err
  174. }
  175. func (cmd *Cmd) Text() (string, error) {
  176. if cmd.err != nil {
  177. return "", cmd.err
  178. }
  179. return toString(cmd.val)
  180. }
  181. func toString(val interface{}) (string, error) {
  182. switch val := val.(type) {
  183. case string:
  184. return val, nil
  185. default:
  186. err := fmt.Errorf("redis: unexpected type=%T for String", val)
  187. return "", err
  188. }
  189. }
  190. func (cmd *Cmd) Int() (int, error) {
  191. if cmd.err != nil {
  192. return 0, cmd.err
  193. }
  194. switch val := cmd.val.(type) {
  195. case int64:
  196. return int(val), nil
  197. case string:
  198. return strconv.Atoi(val)
  199. default:
  200. err := fmt.Errorf("redis: unexpected type=%T for Int", val)
  201. return 0, err
  202. }
  203. }
  204. func (cmd *Cmd) Int64() (int64, error) {
  205. if cmd.err != nil {
  206. return 0, cmd.err
  207. }
  208. return toInt64(cmd.val)
  209. }
  210. func toInt64(val interface{}) (int64, error) {
  211. switch val := val.(type) {
  212. case int64:
  213. return val, nil
  214. case string:
  215. return strconv.ParseInt(val, 10, 64)
  216. default:
  217. err := fmt.Errorf("redis: unexpected type=%T for Int64", val)
  218. return 0, err
  219. }
  220. }
  221. func (cmd *Cmd) Uint64() (uint64, error) {
  222. if cmd.err != nil {
  223. return 0, cmd.err
  224. }
  225. return toUint64(cmd.val)
  226. }
  227. func toUint64(val interface{}) (uint64, error) {
  228. switch val := val.(type) {
  229. case int64:
  230. return uint64(val), nil
  231. case string:
  232. return strconv.ParseUint(val, 10, 64)
  233. default:
  234. err := fmt.Errorf("redis: unexpected type=%T for Uint64", val)
  235. return 0, err
  236. }
  237. }
  238. func (cmd *Cmd) Float32() (float32, error) {
  239. if cmd.err != nil {
  240. return 0, cmd.err
  241. }
  242. return toFloat32(cmd.val)
  243. }
  244. func toFloat32(val interface{}) (float32, error) {
  245. switch val := val.(type) {
  246. case int64:
  247. return float32(val), nil
  248. case string:
  249. f, err := strconv.ParseFloat(val, 32)
  250. if err != nil {
  251. return 0, err
  252. }
  253. return float32(f), nil
  254. default:
  255. err := fmt.Errorf("redis: unexpected type=%T for Float32", val)
  256. return 0, err
  257. }
  258. }
  259. func (cmd *Cmd) Float64() (float64, error) {
  260. if cmd.err != nil {
  261. return 0, cmd.err
  262. }
  263. return toFloat64(cmd.val)
  264. }
  265. func toFloat64(val interface{}) (float64, error) {
  266. switch val := val.(type) {
  267. case int64:
  268. return float64(val), nil
  269. case string:
  270. return strconv.ParseFloat(val, 64)
  271. default:
  272. err := fmt.Errorf("redis: unexpected type=%T for Float64", val)
  273. return 0, err
  274. }
  275. }
  276. func (cmd *Cmd) Bool() (bool, error) {
  277. if cmd.err != nil {
  278. return false, cmd.err
  279. }
  280. return toBool(cmd.val)
  281. }
  282. func toBool(val interface{}) (bool, error) {
  283. switch val := val.(type) {
  284. case int64:
  285. return val != 0, nil
  286. case string:
  287. return strconv.ParseBool(val)
  288. default:
  289. err := fmt.Errorf("redis: unexpected type=%T for Bool", val)
  290. return false, err
  291. }
  292. }
  293. func (cmd *Cmd) Slice() ([]interface{}, error) {
  294. if cmd.err != nil {
  295. return nil, cmd.err
  296. }
  297. switch val := cmd.val.(type) {
  298. case []interface{}:
  299. return val, nil
  300. default:
  301. return nil, fmt.Errorf("redis: unexpected type=%T for Slice", val)
  302. }
  303. }
  304. func (cmd *Cmd) StringSlice() ([]string, error) {
  305. slice, err := cmd.Slice()
  306. if err != nil {
  307. return nil, err
  308. }
  309. ss := make([]string, len(slice))
  310. for i, iface := range slice {
  311. val, err := toString(iface)
  312. if err != nil {
  313. return nil, err
  314. }
  315. ss[i] = val
  316. }
  317. return ss, nil
  318. }
  319. func (cmd *Cmd) Int64Slice() ([]int64, error) {
  320. slice, err := cmd.Slice()
  321. if err != nil {
  322. return nil, err
  323. }
  324. nums := make([]int64, len(slice))
  325. for i, iface := range slice {
  326. val, err := toInt64(iface)
  327. if err != nil {
  328. return nil, err
  329. }
  330. nums[i] = val
  331. }
  332. return nums, nil
  333. }
  334. func (cmd *Cmd) Uint64Slice() ([]uint64, error) {
  335. slice, err := cmd.Slice()
  336. if err != nil {
  337. return nil, err
  338. }
  339. nums := make([]uint64, len(slice))
  340. for i, iface := range slice {
  341. val, err := toUint64(iface)
  342. if err != nil {
  343. return nil, err
  344. }
  345. nums[i] = val
  346. }
  347. return nums, nil
  348. }
  349. func (cmd *Cmd) Float32Slice() ([]float32, error) {
  350. slice, err := cmd.Slice()
  351. if err != nil {
  352. return nil, err
  353. }
  354. floats := make([]float32, len(slice))
  355. for i, iface := range slice {
  356. val, err := toFloat32(iface)
  357. if err != nil {
  358. return nil, err
  359. }
  360. floats[i] = val
  361. }
  362. return floats, nil
  363. }
  364. func (cmd *Cmd) Float64Slice() ([]float64, error) {
  365. slice, err := cmd.Slice()
  366. if err != nil {
  367. return nil, err
  368. }
  369. floats := make([]float64, len(slice))
  370. for i, iface := range slice {
  371. val, err := toFloat64(iface)
  372. if err != nil {
  373. return nil, err
  374. }
  375. floats[i] = val
  376. }
  377. return floats, nil
  378. }
  379. func (cmd *Cmd) BoolSlice() ([]bool, error) {
  380. slice, err := cmd.Slice()
  381. if err != nil {
  382. return nil, err
  383. }
  384. bools := make([]bool, len(slice))
  385. for i, iface := range slice {
  386. val, err := toBool(iface)
  387. if err != nil {
  388. return nil, err
  389. }
  390. bools[i] = val
  391. }
  392. return bools, nil
  393. }
  394. func (cmd *Cmd) readReply(rd *proto.Reader) (err error) {
  395. cmd.val, err = rd.ReadReply(sliceParser)
  396. return err
  397. }
  398. // sliceParser implements proto.MultiBulkParse.
  399. func sliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  400. vals := make([]interface{}, n)
  401. for i := 0; i < len(vals); i++ {
  402. v, err := rd.ReadReply(sliceParser)
  403. if err != nil {
  404. if err == Nil {
  405. vals[i] = nil
  406. continue
  407. }
  408. if err, ok := err.(proto.RedisError); ok {
  409. vals[i] = err
  410. continue
  411. }
  412. return nil, err
  413. }
  414. vals[i] = v
  415. }
  416. return vals, nil
  417. }
  418. //------------------------------------------------------------------------------
  419. type SliceCmd struct {
  420. baseCmd
  421. val []interface{}
  422. }
  423. var _ Cmder = (*SliceCmd)(nil)
  424. func NewSliceCmd(ctx context.Context, args ...interface{}) *SliceCmd {
  425. return &SliceCmd{
  426. baseCmd: baseCmd{
  427. ctx: ctx,
  428. args: args,
  429. },
  430. }
  431. }
  432. func (cmd *SliceCmd) SetVal(val []interface{}) {
  433. cmd.val = val
  434. }
  435. func (cmd *SliceCmd) Val() []interface{} {
  436. return cmd.val
  437. }
  438. func (cmd *SliceCmd) Result() ([]interface{}, error) {
  439. return cmd.val, cmd.err
  440. }
  441. func (cmd *SliceCmd) String() string {
  442. return cmdString(cmd, cmd.val)
  443. }
  444. // Scan scans the results from the map into a destination struct. The map keys
  445. // are matched in the Redis struct fields by the `redis:"field"` tag.
  446. func (cmd *SliceCmd) Scan(dst interface{}) error {
  447. if cmd.err != nil {
  448. return cmd.err
  449. }
  450. // Pass the list of keys and values.
  451. // Skip the first two args for: HMGET key
  452. var args []interface{}
  453. if cmd.args[0] == "hmget" {
  454. args = cmd.args[2:]
  455. } else {
  456. // Otherwise, it's: MGET field field ...
  457. args = cmd.args[1:]
  458. }
  459. return hscan.Scan(dst, args, cmd.val)
  460. }
  461. func (cmd *SliceCmd) readReply(rd *proto.Reader) error {
  462. v, err := rd.ReadArrayReply(sliceParser)
  463. if err != nil {
  464. return err
  465. }
  466. cmd.val = v.([]interface{})
  467. return nil
  468. }
  469. //------------------------------------------------------------------------------
  470. type StatusCmd struct {
  471. baseCmd
  472. val string
  473. }
  474. var _ Cmder = (*StatusCmd)(nil)
  475. func NewStatusCmd(ctx context.Context, args ...interface{}) *StatusCmd {
  476. return &StatusCmd{
  477. baseCmd: baseCmd{
  478. ctx: ctx,
  479. args: args,
  480. },
  481. }
  482. }
  483. func (cmd *StatusCmd) SetVal(val string) {
  484. cmd.val = val
  485. }
  486. func (cmd *StatusCmd) Val() string {
  487. return cmd.val
  488. }
  489. func (cmd *StatusCmd) Result() (string, error) {
  490. return cmd.val, cmd.err
  491. }
  492. func (cmd *StatusCmd) String() string {
  493. return cmdString(cmd, cmd.val)
  494. }
  495. func (cmd *StatusCmd) readReply(rd *proto.Reader) (err error) {
  496. cmd.val, err = rd.ReadString()
  497. return err
  498. }
  499. //------------------------------------------------------------------------------
  500. type IntCmd struct {
  501. baseCmd
  502. val int64
  503. }
  504. var _ Cmder = (*IntCmd)(nil)
  505. func NewIntCmd(ctx context.Context, args ...interface{}) *IntCmd {
  506. return &IntCmd{
  507. baseCmd: baseCmd{
  508. ctx: ctx,
  509. args: args,
  510. },
  511. }
  512. }
  513. func (cmd *IntCmd) SetVal(val int64) {
  514. cmd.val = val
  515. }
  516. func (cmd *IntCmd) Val() int64 {
  517. return cmd.val
  518. }
  519. func (cmd *IntCmd) Result() (int64, error) {
  520. return cmd.val, cmd.err
  521. }
  522. func (cmd *IntCmd) Uint64() (uint64, error) {
  523. return uint64(cmd.val), cmd.err
  524. }
  525. func (cmd *IntCmd) String() string {
  526. return cmdString(cmd, cmd.val)
  527. }
  528. func (cmd *IntCmd) readReply(rd *proto.Reader) (err error) {
  529. cmd.val, err = rd.ReadIntReply()
  530. return err
  531. }
  532. //------------------------------------------------------------------------------
  533. type IntSliceCmd struct {
  534. baseCmd
  535. val []int64
  536. }
  537. var _ Cmder = (*IntSliceCmd)(nil)
  538. func NewIntSliceCmd(ctx context.Context, args ...interface{}) *IntSliceCmd {
  539. return &IntSliceCmd{
  540. baseCmd: baseCmd{
  541. ctx: ctx,
  542. args: args,
  543. },
  544. }
  545. }
  546. func (cmd *IntSliceCmd) SetVal(val []int64) {
  547. cmd.val = val
  548. }
  549. func (cmd *IntSliceCmd) Val() []int64 {
  550. return cmd.val
  551. }
  552. func (cmd *IntSliceCmd) Result() ([]int64, error) {
  553. return cmd.val, cmd.err
  554. }
  555. func (cmd *IntSliceCmd) String() string {
  556. return cmdString(cmd, cmd.val)
  557. }
  558. func (cmd *IntSliceCmd) readReply(rd *proto.Reader) error {
  559. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  560. cmd.val = make([]int64, n)
  561. for i := 0; i < len(cmd.val); i++ {
  562. num, err := rd.ReadIntReply()
  563. if err != nil {
  564. return nil, err
  565. }
  566. cmd.val[i] = num
  567. }
  568. return nil, nil
  569. })
  570. return err
  571. }
  572. //------------------------------------------------------------------------------
  573. type DurationCmd struct {
  574. baseCmd
  575. val time.Duration
  576. precision time.Duration
  577. }
  578. var _ Cmder = (*DurationCmd)(nil)
  579. func NewDurationCmd(ctx context.Context, precision time.Duration, args ...interface{}) *DurationCmd {
  580. return &DurationCmd{
  581. baseCmd: baseCmd{
  582. ctx: ctx,
  583. args: args,
  584. },
  585. precision: precision,
  586. }
  587. }
  588. func (cmd *DurationCmd) SetVal(val time.Duration) {
  589. cmd.val = val
  590. }
  591. func (cmd *DurationCmd) Val() time.Duration {
  592. return cmd.val
  593. }
  594. func (cmd *DurationCmd) Result() (time.Duration, error) {
  595. return cmd.val, cmd.err
  596. }
  597. func (cmd *DurationCmd) String() string {
  598. return cmdString(cmd, cmd.val)
  599. }
  600. func (cmd *DurationCmd) readReply(rd *proto.Reader) error {
  601. n, err := rd.ReadIntReply()
  602. if err != nil {
  603. return err
  604. }
  605. switch n {
  606. // -2 if the key does not exist
  607. // -1 if the key exists but has no associated expire
  608. case -2, -1:
  609. cmd.val = time.Duration(n)
  610. default:
  611. cmd.val = time.Duration(n) * cmd.precision
  612. }
  613. return nil
  614. }
  615. //------------------------------------------------------------------------------
  616. type TimeCmd struct {
  617. baseCmd
  618. val time.Time
  619. }
  620. var _ Cmder = (*TimeCmd)(nil)
  621. func NewTimeCmd(ctx context.Context, args ...interface{}) *TimeCmd {
  622. return &TimeCmd{
  623. baseCmd: baseCmd{
  624. ctx: ctx,
  625. args: args,
  626. },
  627. }
  628. }
  629. func (cmd *TimeCmd) SetVal(val time.Time) {
  630. cmd.val = val
  631. }
  632. func (cmd *TimeCmd) Val() time.Time {
  633. return cmd.val
  634. }
  635. func (cmd *TimeCmd) Result() (time.Time, error) {
  636. return cmd.val, cmd.err
  637. }
  638. func (cmd *TimeCmd) String() string {
  639. return cmdString(cmd, cmd.val)
  640. }
  641. func (cmd *TimeCmd) readReply(rd *proto.Reader) error {
  642. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  643. if n != 2 {
  644. return nil, fmt.Errorf("got %d elements, expected 2", n)
  645. }
  646. sec, err := rd.ReadInt()
  647. if err != nil {
  648. return nil, err
  649. }
  650. microsec, err := rd.ReadInt()
  651. if err != nil {
  652. return nil, err
  653. }
  654. cmd.val = time.Unix(sec, microsec*1000)
  655. return nil, nil
  656. })
  657. return err
  658. }
  659. //------------------------------------------------------------------------------
  660. type BoolCmd struct {
  661. baseCmd
  662. val bool
  663. }
  664. var _ Cmder = (*BoolCmd)(nil)
  665. func NewBoolCmd(ctx context.Context, args ...interface{}) *BoolCmd {
  666. return &BoolCmd{
  667. baseCmd: baseCmd{
  668. ctx: ctx,
  669. args: args,
  670. },
  671. }
  672. }
  673. func (cmd *BoolCmd) SetVal(val bool) {
  674. cmd.val = val
  675. }
  676. func (cmd *BoolCmd) Val() bool {
  677. return cmd.val
  678. }
  679. func (cmd *BoolCmd) Result() (bool, error) {
  680. return cmd.val, cmd.err
  681. }
  682. func (cmd *BoolCmd) String() string {
  683. return cmdString(cmd, cmd.val)
  684. }
  685. func (cmd *BoolCmd) readReply(rd *proto.Reader) error {
  686. v, err := rd.ReadReply(nil)
  687. // `SET key value NX` returns nil when key already exists. But
  688. // `SETNX key value` returns bool (0/1). So convert nil to bool.
  689. if err == Nil {
  690. cmd.val = false
  691. return nil
  692. }
  693. if err != nil {
  694. return err
  695. }
  696. switch v := v.(type) {
  697. case int64:
  698. cmd.val = v == 1
  699. return nil
  700. case string:
  701. cmd.val = v == "OK"
  702. return nil
  703. default:
  704. return fmt.Errorf("got %T, wanted int64 or string", v)
  705. }
  706. }
  707. //------------------------------------------------------------------------------
  708. type StringCmd struct {
  709. baseCmd
  710. val string
  711. }
  712. var _ Cmder = (*StringCmd)(nil)
  713. func NewStringCmd(ctx context.Context, args ...interface{}) *StringCmd {
  714. return &StringCmd{
  715. baseCmd: baseCmd{
  716. ctx: ctx,
  717. args: args,
  718. },
  719. }
  720. }
  721. func (cmd *StringCmd) SetVal(val string) {
  722. cmd.val = val
  723. }
  724. func (cmd *StringCmd) Val() string {
  725. return cmd.val
  726. }
  727. func (cmd *StringCmd) Result() (string, error) {
  728. return cmd.Val(), cmd.err
  729. }
  730. func (cmd *StringCmd) Bytes() ([]byte, error) {
  731. return util.StringToBytes(cmd.val), cmd.err
  732. }
  733. func (cmd *StringCmd) Bool() (bool, error) {
  734. if cmd.err != nil {
  735. return false, cmd.err
  736. }
  737. return strconv.ParseBool(cmd.val)
  738. }
  739. func (cmd *StringCmd) Int() (int, error) {
  740. if cmd.err != nil {
  741. return 0, cmd.err
  742. }
  743. return strconv.Atoi(cmd.Val())
  744. }
  745. func (cmd *StringCmd) Int64() (int64, error) {
  746. if cmd.err != nil {
  747. return 0, cmd.err
  748. }
  749. return strconv.ParseInt(cmd.Val(), 10, 64)
  750. }
  751. func (cmd *StringCmd) Uint64() (uint64, error) {
  752. if cmd.err != nil {
  753. return 0, cmd.err
  754. }
  755. return strconv.ParseUint(cmd.Val(), 10, 64)
  756. }
  757. func (cmd *StringCmd) Float32() (float32, error) {
  758. if cmd.err != nil {
  759. return 0, cmd.err
  760. }
  761. f, err := strconv.ParseFloat(cmd.Val(), 32)
  762. if err != nil {
  763. return 0, err
  764. }
  765. return float32(f), nil
  766. }
  767. func (cmd *StringCmd) Float64() (float64, error) {
  768. if cmd.err != nil {
  769. return 0, cmd.err
  770. }
  771. return strconv.ParseFloat(cmd.Val(), 64)
  772. }
  773. func (cmd *StringCmd) Time() (time.Time, error) {
  774. if cmd.err != nil {
  775. return time.Time{}, cmd.err
  776. }
  777. return time.Parse(time.RFC3339Nano, cmd.Val())
  778. }
  779. func (cmd *StringCmd) Scan(val interface{}) error {
  780. if cmd.err != nil {
  781. return cmd.err
  782. }
  783. return proto.Scan([]byte(cmd.val), val)
  784. }
  785. func (cmd *StringCmd) String() string {
  786. return cmdString(cmd, cmd.val)
  787. }
  788. func (cmd *StringCmd) readReply(rd *proto.Reader) (err error) {
  789. cmd.val, err = rd.ReadString()
  790. return err
  791. }
  792. //------------------------------------------------------------------------------
  793. type FloatCmd struct {
  794. baseCmd
  795. val float64
  796. }
  797. var _ Cmder = (*FloatCmd)(nil)
  798. func NewFloatCmd(ctx context.Context, args ...interface{}) *FloatCmd {
  799. return &FloatCmd{
  800. baseCmd: baseCmd{
  801. ctx: ctx,
  802. args: args,
  803. },
  804. }
  805. }
  806. func (cmd *FloatCmd) SetVal(val float64) {
  807. cmd.val = val
  808. }
  809. func (cmd *FloatCmd) Val() float64 {
  810. return cmd.val
  811. }
  812. func (cmd *FloatCmd) Result() (float64, error) {
  813. return cmd.Val(), cmd.Err()
  814. }
  815. func (cmd *FloatCmd) String() string {
  816. return cmdString(cmd, cmd.val)
  817. }
  818. func (cmd *FloatCmd) readReply(rd *proto.Reader) (err error) {
  819. cmd.val, err = rd.ReadFloatReply()
  820. return err
  821. }
  822. //------------------------------------------------------------------------------
  823. type FloatSliceCmd struct {
  824. baseCmd
  825. val []float64
  826. }
  827. var _ Cmder = (*FloatSliceCmd)(nil)
  828. func NewFloatSliceCmd(ctx context.Context, args ...interface{}) *FloatSliceCmd {
  829. return &FloatSliceCmd{
  830. baseCmd: baseCmd{
  831. ctx: ctx,
  832. args: args,
  833. },
  834. }
  835. }
  836. func (cmd *FloatSliceCmd) SetVal(val []float64) {
  837. cmd.val = val
  838. }
  839. func (cmd *FloatSliceCmd) Val() []float64 {
  840. return cmd.val
  841. }
  842. func (cmd *FloatSliceCmd) Result() ([]float64, error) {
  843. return cmd.val, cmd.err
  844. }
  845. func (cmd *FloatSliceCmd) String() string {
  846. return cmdString(cmd, cmd.val)
  847. }
  848. func (cmd *FloatSliceCmd) readReply(rd *proto.Reader) error {
  849. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  850. cmd.val = make([]float64, n)
  851. for i := 0; i < len(cmd.val); i++ {
  852. switch num, err := rd.ReadFloatReply(); {
  853. case err == Nil:
  854. cmd.val[i] = 0
  855. case err != nil:
  856. return nil, err
  857. default:
  858. cmd.val[i] = num
  859. }
  860. }
  861. return nil, nil
  862. })
  863. return err
  864. }
  865. //------------------------------------------------------------------------------
  866. type StringSliceCmd struct {
  867. baseCmd
  868. val []string
  869. }
  870. var _ Cmder = (*StringSliceCmd)(nil)
  871. func NewStringSliceCmd(ctx context.Context, args ...interface{}) *StringSliceCmd {
  872. return &StringSliceCmd{
  873. baseCmd: baseCmd{
  874. ctx: ctx,
  875. args: args,
  876. },
  877. }
  878. }
  879. func (cmd *StringSliceCmd) SetVal(val []string) {
  880. cmd.val = val
  881. }
  882. func (cmd *StringSliceCmd) Val() []string {
  883. return cmd.val
  884. }
  885. func (cmd *StringSliceCmd) Result() ([]string, error) {
  886. return cmd.Val(), cmd.Err()
  887. }
  888. func (cmd *StringSliceCmd) String() string {
  889. return cmdString(cmd, cmd.val)
  890. }
  891. func (cmd *StringSliceCmd) ScanSlice(container interface{}) error {
  892. return proto.ScanSlice(cmd.Val(), container)
  893. }
  894. func (cmd *StringSliceCmd) readReply(rd *proto.Reader) error {
  895. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  896. cmd.val = make([]string, n)
  897. for i := 0; i < len(cmd.val); i++ {
  898. switch s, err := rd.ReadString(); {
  899. case err == Nil:
  900. cmd.val[i] = ""
  901. case err != nil:
  902. return nil, err
  903. default:
  904. cmd.val[i] = s
  905. }
  906. }
  907. return nil, nil
  908. })
  909. return err
  910. }
  911. //------------------------------------------------------------------------------
  912. type BoolSliceCmd struct {
  913. baseCmd
  914. val []bool
  915. }
  916. var _ Cmder = (*BoolSliceCmd)(nil)
  917. func NewBoolSliceCmd(ctx context.Context, args ...interface{}) *BoolSliceCmd {
  918. return &BoolSliceCmd{
  919. baseCmd: baseCmd{
  920. ctx: ctx,
  921. args: args,
  922. },
  923. }
  924. }
  925. func (cmd *BoolSliceCmd) SetVal(val []bool) {
  926. cmd.val = val
  927. }
  928. func (cmd *BoolSliceCmd) Val() []bool {
  929. return cmd.val
  930. }
  931. func (cmd *BoolSliceCmd) Result() ([]bool, error) {
  932. return cmd.val, cmd.err
  933. }
  934. func (cmd *BoolSliceCmd) String() string {
  935. return cmdString(cmd, cmd.val)
  936. }
  937. func (cmd *BoolSliceCmd) readReply(rd *proto.Reader) error {
  938. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  939. cmd.val = make([]bool, n)
  940. for i := 0; i < len(cmd.val); i++ {
  941. n, err := rd.ReadIntReply()
  942. if err != nil {
  943. return nil, err
  944. }
  945. cmd.val[i] = n == 1
  946. }
  947. return nil, nil
  948. })
  949. return err
  950. }
  951. //------------------------------------------------------------------------------
  952. type StringStringMapCmd struct {
  953. baseCmd
  954. val map[string]string
  955. }
  956. var _ Cmder = (*StringStringMapCmd)(nil)
  957. func NewStringStringMapCmd(ctx context.Context, args ...interface{}) *StringStringMapCmd {
  958. return &StringStringMapCmd{
  959. baseCmd: baseCmd{
  960. ctx: ctx,
  961. args: args,
  962. },
  963. }
  964. }
  965. func (cmd *StringStringMapCmd) SetVal(val map[string]string) {
  966. cmd.val = val
  967. }
  968. func (cmd *StringStringMapCmd) Val() map[string]string {
  969. return cmd.val
  970. }
  971. func (cmd *StringStringMapCmd) Result() (map[string]string, error) {
  972. return cmd.val, cmd.err
  973. }
  974. func (cmd *StringStringMapCmd) String() string {
  975. return cmdString(cmd, cmd.val)
  976. }
  977. // Scan scans the results from the map into a destination struct. The map keys
  978. // are matched in the Redis struct fields by the `redis:"field"` tag.
  979. func (cmd *StringStringMapCmd) Scan(dest interface{}) error {
  980. if cmd.err != nil {
  981. return cmd.err
  982. }
  983. strct, err := hscan.Struct(dest)
  984. if err != nil {
  985. return err
  986. }
  987. for k, v := range cmd.val {
  988. if err := strct.Scan(k, v); err != nil {
  989. return err
  990. }
  991. }
  992. return nil
  993. }
  994. func (cmd *StringStringMapCmd) readReply(rd *proto.Reader) error {
  995. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  996. cmd.val = make(map[string]string, n/2)
  997. for i := int64(0); i < n; i += 2 {
  998. key, err := rd.ReadString()
  999. if err != nil {
  1000. return nil, err
  1001. }
  1002. value, err := rd.ReadString()
  1003. if err != nil {
  1004. return nil, err
  1005. }
  1006. cmd.val[key] = value
  1007. }
  1008. return nil, nil
  1009. })
  1010. return err
  1011. }
  1012. //------------------------------------------------------------------------------
  1013. type StringIntMapCmd struct {
  1014. baseCmd
  1015. val map[string]int64
  1016. }
  1017. var _ Cmder = (*StringIntMapCmd)(nil)
  1018. func NewStringIntMapCmd(ctx context.Context, args ...interface{}) *StringIntMapCmd {
  1019. return &StringIntMapCmd{
  1020. baseCmd: baseCmd{
  1021. ctx: ctx,
  1022. args: args,
  1023. },
  1024. }
  1025. }
  1026. func (cmd *StringIntMapCmd) SetVal(val map[string]int64) {
  1027. cmd.val = val
  1028. }
  1029. func (cmd *StringIntMapCmd) Val() map[string]int64 {
  1030. return cmd.val
  1031. }
  1032. func (cmd *StringIntMapCmd) Result() (map[string]int64, error) {
  1033. return cmd.val, cmd.err
  1034. }
  1035. func (cmd *StringIntMapCmd) String() string {
  1036. return cmdString(cmd, cmd.val)
  1037. }
  1038. func (cmd *StringIntMapCmd) readReply(rd *proto.Reader) error {
  1039. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1040. cmd.val = make(map[string]int64, n/2)
  1041. for i := int64(0); i < n; i += 2 {
  1042. key, err := rd.ReadString()
  1043. if err != nil {
  1044. return nil, err
  1045. }
  1046. n, err := rd.ReadIntReply()
  1047. if err != nil {
  1048. return nil, err
  1049. }
  1050. cmd.val[key] = n
  1051. }
  1052. return nil, nil
  1053. })
  1054. return err
  1055. }
  1056. //------------------------------------------------------------------------------
  1057. type StringStructMapCmd struct {
  1058. baseCmd
  1059. val map[string]struct{}
  1060. }
  1061. var _ Cmder = (*StringStructMapCmd)(nil)
  1062. func NewStringStructMapCmd(ctx context.Context, args ...interface{}) *StringStructMapCmd {
  1063. return &StringStructMapCmd{
  1064. baseCmd: baseCmd{
  1065. ctx: ctx,
  1066. args: args,
  1067. },
  1068. }
  1069. }
  1070. func (cmd *StringStructMapCmd) SetVal(val map[string]struct{}) {
  1071. cmd.val = val
  1072. }
  1073. func (cmd *StringStructMapCmd) Val() map[string]struct{} {
  1074. return cmd.val
  1075. }
  1076. func (cmd *StringStructMapCmd) Result() (map[string]struct{}, error) {
  1077. return cmd.val, cmd.err
  1078. }
  1079. func (cmd *StringStructMapCmd) String() string {
  1080. return cmdString(cmd, cmd.val)
  1081. }
  1082. func (cmd *StringStructMapCmd) readReply(rd *proto.Reader) error {
  1083. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1084. cmd.val = make(map[string]struct{}, n)
  1085. for i := int64(0); i < n; i++ {
  1086. key, err := rd.ReadString()
  1087. if err != nil {
  1088. return nil, err
  1089. }
  1090. cmd.val[key] = struct{}{}
  1091. }
  1092. return nil, nil
  1093. })
  1094. return err
  1095. }
  1096. //------------------------------------------------------------------------------
  1097. type XMessage struct {
  1098. ID string
  1099. Values map[string]interface{}
  1100. }
  1101. type XMessageSliceCmd struct {
  1102. baseCmd
  1103. val []XMessage
  1104. }
  1105. var _ Cmder = (*XMessageSliceCmd)(nil)
  1106. func NewXMessageSliceCmd(ctx context.Context, args ...interface{}) *XMessageSliceCmd {
  1107. return &XMessageSliceCmd{
  1108. baseCmd: baseCmd{
  1109. ctx: ctx,
  1110. args: args,
  1111. },
  1112. }
  1113. }
  1114. func (cmd *XMessageSliceCmd) SetVal(val []XMessage) {
  1115. cmd.val = val
  1116. }
  1117. func (cmd *XMessageSliceCmd) Val() []XMessage {
  1118. return cmd.val
  1119. }
  1120. func (cmd *XMessageSliceCmd) Result() ([]XMessage, error) {
  1121. return cmd.val, cmd.err
  1122. }
  1123. func (cmd *XMessageSliceCmd) String() string {
  1124. return cmdString(cmd, cmd.val)
  1125. }
  1126. func (cmd *XMessageSliceCmd) readReply(rd *proto.Reader) error {
  1127. var err error
  1128. cmd.val, err = readXMessageSlice(rd)
  1129. return err
  1130. }
  1131. func readXMessageSlice(rd *proto.Reader) ([]XMessage, error) {
  1132. n, err := rd.ReadArrayLen()
  1133. if err != nil {
  1134. return nil, err
  1135. }
  1136. msgs := make([]XMessage, n)
  1137. for i := 0; i < n; i++ {
  1138. var err error
  1139. msgs[i], err = readXMessage(rd)
  1140. if err != nil {
  1141. return nil, err
  1142. }
  1143. }
  1144. return msgs, nil
  1145. }
  1146. func readXMessage(rd *proto.Reader) (XMessage, error) {
  1147. n, err := rd.ReadArrayLen()
  1148. if err != nil {
  1149. return XMessage{}, err
  1150. }
  1151. if n != 2 {
  1152. return XMessage{}, fmt.Errorf("got %d, wanted 2", n)
  1153. }
  1154. id, err := rd.ReadString()
  1155. if err != nil {
  1156. return XMessage{}, err
  1157. }
  1158. var values map[string]interface{}
  1159. v, err := rd.ReadArrayReply(stringInterfaceMapParser)
  1160. if err != nil {
  1161. if err != proto.Nil {
  1162. return XMessage{}, err
  1163. }
  1164. } else {
  1165. values = v.(map[string]interface{})
  1166. }
  1167. return XMessage{
  1168. ID: id,
  1169. Values: values,
  1170. }, nil
  1171. }
  1172. // stringInterfaceMapParser implements proto.MultiBulkParse.
  1173. func stringInterfaceMapParser(rd *proto.Reader, n int64) (interface{}, error) {
  1174. m := make(map[string]interface{}, n/2)
  1175. for i := int64(0); i < n; i += 2 {
  1176. key, err := rd.ReadString()
  1177. if err != nil {
  1178. return nil, err
  1179. }
  1180. value, err := rd.ReadString()
  1181. if err != nil {
  1182. return nil, err
  1183. }
  1184. m[key] = value
  1185. }
  1186. return m, nil
  1187. }
  1188. //------------------------------------------------------------------------------
  1189. type XStream struct {
  1190. Stream string
  1191. Messages []XMessage
  1192. }
  1193. type XStreamSliceCmd struct {
  1194. baseCmd
  1195. val []XStream
  1196. }
  1197. var _ Cmder = (*XStreamSliceCmd)(nil)
  1198. func NewXStreamSliceCmd(ctx context.Context, args ...interface{}) *XStreamSliceCmd {
  1199. return &XStreamSliceCmd{
  1200. baseCmd: baseCmd{
  1201. ctx: ctx,
  1202. args: args,
  1203. },
  1204. }
  1205. }
  1206. func (cmd *XStreamSliceCmd) SetVal(val []XStream) {
  1207. cmd.val = val
  1208. }
  1209. func (cmd *XStreamSliceCmd) Val() []XStream {
  1210. return cmd.val
  1211. }
  1212. func (cmd *XStreamSliceCmd) Result() ([]XStream, error) {
  1213. return cmd.val, cmd.err
  1214. }
  1215. func (cmd *XStreamSliceCmd) String() string {
  1216. return cmdString(cmd, cmd.val)
  1217. }
  1218. func (cmd *XStreamSliceCmd) readReply(rd *proto.Reader) error {
  1219. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1220. cmd.val = make([]XStream, n)
  1221. for i := 0; i < len(cmd.val); i++ {
  1222. i := i
  1223. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1224. if n != 2 {
  1225. return nil, fmt.Errorf("got %d, wanted 2", n)
  1226. }
  1227. stream, err := rd.ReadString()
  1228. if err != nil {
  1229. return nil, err
  1230. }
  1231. msgs, err := readXMessageSlice(rd)
  1232. if err != nil {
  1233. return nil, err
  1234. }
  1235. cmd.val[i] = XStream{
  1236. Stream: stream,
  1237. Messages: msgs,
  1238. }
  1239. return nil, nil
  1240. })
  1241. if err != nil {
  1242. return nil, err
  1243. }
  1244. }
  1245. return nil, nil
  1246. })
  1247. return err
  1248. }
  1249. //------------------------------------------------------------------------------
  1250. type XPending struct {
  1251. Count int64
  1252. Lower string
  1253. Higher string
  1254. Consumers map[string]int64
  1255. }
  1256. type XPendingCmd struct {
  1257. baseCmd
  1258. val *XPending
  1259. }
  1260. var _ Cmder = (*XPendingCmd)(nil)
  1261. func NewXPendingCmd(ctx context.Context, args ...interface{}) *XPendingCmd {
  1262. return &XPendingCmd{
  1263. baseCmd: baseCmd{
  1264. ctx: ctx,
  1265. args: args,
  1266. },
  1267. }
  1268. }
  1269. func (cmd *XPendingCmd) SetVal(val *XPending) {
  1270. cmd.val = val
  1271. }
  1272. func (cmd *XPendingCmd) Val() *XPending {
  1273. return cmd.val
  1274. }
  1275. func (cmd *XPendingCmd) Result() (*XPending, error) {
  1276. return cmd.val, cmd.err
  1277. }
  1278. func (cmd *XPendingCmd) String() string {
  1279. return cmdString(cmd, cmd.val)
  1280. }
  1281. func (cmd *XPendingCmd) readReply(rd *proto.Reader) error {
  1282. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1283. if n != 4 {
  1284. return nil, fmt.Errorf("got %d, wanted 4", n)
  1285. }
  1286. count, err := rd.ReadIntReply()
  1287. if err != nil {
  1288. return nil, err
  1289. }
  1290. lower, err := rd.ReadString()
  1291. if err != nil && err != Nil {
  1292. return nil, err
  1293. }
  1294. higher, err := rd.ReadString()
  1295. if err != nil && err != Nil {
  1296. return nil, err
  1297. }
  1298. cmd.val = &XPending{
  1299. Count: count,
  1300. Lower: lower,
  1301. Higher: higher,
  1302. }
  1303. _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1304. for i := int64(0); i < n; i++ {
  1305. _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1306. if n != 2 {
  1307. return nil, fmt.Errorf("got %d, wanted 2", n)
  1308. }
  1309. consumerName, err := rd.ReadString()
  1310. if err != nil {
  1311. return nil, err
  1312. }
  1313. consumerPending, err := rd.ReadInt()
  1314. if err != nil {
  1315. return nil, err
  1316. }
  1317. if cmd.val.Consumers == nil {
  1318. cmd.val.Consumers = make(map[string]int64)
  1319. }
  1320. cmd.val.Consumers[consumerName] = consumerPending
  1321. return nil, nil
  1322. })
  1323. if err != nil {
  1324. return nil, err
  1325. }
  1326. }
  1327. return nil, nil
  1328. })
  1329. if err != nil && err != Nil {
  1330. return nil, err
  1331. }
  1332. return nil, nil
  1333. })
  1334. return err
  1335. }
  1336. //------------------------------------------------------------------------------
  1337. type XPendingExt struct {
  1338. ID string
  1339. Consumer string
  1340. Idle time.Duration
  1341. RetryCount int64
  1342. }
  1343. type XPendingExtCmd struct {
  1344. baseCmd
  1345. val []XPendingExt
  1346. }
  1347. var _ Cmder = (*XPendingExtCmd)(nil)
  1348. func NewXPendingExtCmd(ctx context.Context, args ...interface{}) *XPendingExtCmd {
  1349. return &XPendingExtCmd{
  1350. baseCmd: baseCmd{
  1351. ctx: ctx,
  1352. args: args,
  1353. },
  1354. }
  1355. }
  1356. func (cmd *XPendingExtCmd) SetVal(val []XPendingExt) {
  1357. cmd.val = val
  1358. }
  1359. func (cmd *XPendingExtCmd) Val() []XPendingExt {
  1360. return cmd.val
  1361. }
  1362. func (cmd *XPendingExtCmd) Result() ([]XPendingExt, error) {
  1363. return cmd.val, cmd.err
  1364. }
  1365. func (cmd *XPendingExtCmd) String() string {
  1366. return cmdString(cmd, cmd.val)
  1367. }
  1368. func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error {
  1369. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1370. cmd.val = make([]XPendingExt, 0, n)
  1371. for i := int64(0); i < n; i++ {
  1372. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1373. if n != 4 {
  1374. return nil, fmt.Errorf("got %d, wanted 4", n)
  1375. }
  1376. id, err := rd.ReadString()
  1377. if err != nil {
  1378. return nil, err
  1379. }
  1380. consumer, err := rd.ReadString()
  1381. if err != nil && err != Nil {
  1382. return nil, err
  1383. }
  1384. idle, err := rd.ReadIntReply()
  1385. if err != nil && err != Nil {
  1386. return nil, err
  1387. }
  1388. retryCount, err := rd.ReadIntReply()
  1389. if err != nil && err != Nil {
  1390. return nil, err
  1391. }
  1392. cmd.val = append(cmd.val, XPendingExt{
  1393. ID: id,
  1394. Consumer: consumer,
  1395. Idle: time.Duration(idle) * time.Millisecond,
  1396. RetryCount: retryCount,
  1397. })
  1398. return nil, nil
  1399. })
  1400. if err != nil {
  1401. return nil, err
  1402. }
  1403. }
  1404. return nil, nil
  1405. })
  1406. return err
  1407. }
  1408. //------------------------------------------------------------------------------
  1409. type XAutoClaimCmd struct {
  1410. baseCmd
  1411. start string
  1412. val []XMessage
  1413. }
  1414. var _ Cmder = (*XAutoClaimCmd)(nil)
  1415. func NewXAutoClaimCmd(ctx context.Context, args ...interface{}) *XAutoClaimCmd {
  1416. return &XAutoClaimCmd{
  1417. baseCmd: baseCmd{
  1418. ctx: ctx,
  1419. args: args,
  1420. },
  1421. }
  1422. }
  1423. func (cmd *XAutoClaimCmd) SetVal(val []XMessage, start string) {
  1424. cmd.val = val
  1425. cmd.start = start
  1426. }
  1427. func (cmd *XAutoClaimCmd) Val() (messages []XMessage, start string) {
  1428. return cmd.val, cmd.start
  1429. }
  1430. func (cmd *XAutoClaimCmd) Result() (messages []XMessage, start string, err error) {
  1431. return cmd.val, cmd.start, cmd.err
  1432. }
  1433. func (cmd *XAutoClaimCmd) String() string {
  1434. return cmdString(cmd, cmd.val)
  1435. }
  1436. func (cmd *XAutoClaimCmd) readReply(rd *proto.Reader) error {
  1437. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1438. if n != 2 {
  1439. return nil, fmt.Errorf("got %d, wanted 2", n)
  1440. }
  1441. var err error
  1442. cmd.start, err = rd.ReadString()
  1443. if err != nil {
  1444. return nil, err
  1445. }
  1446. cmd.val, err = readXMessageSlice(rd)
  1447. if err != nil {
  1448. return nil, err
  1449. }
  1450. return nil, nil
  1451. })
  1452. return err
  1453. }
  1454. //------------------------------------------------------------------------------
  1455. type XAutoClaimJustIDCmd struct {
  1456. baseCmd
  1457. start string
  1458. val []string
  1459. }
  1460. var _ Cmder = (*XAutoClaimJustIDCmd)(nil)
  1461. func NewXAutoClaimJustIDCmd(ctx context.Context, args ...interface{}) *XAutoClaimJustIDCmd {
  1462. return &XAutoClaimJustIDCmd{
  1463. baseCmd: baseCmd{
  1464. ctx: ctx,
  1465. args: args,
  1466. },
  1467. }
  1468. }
  1469. func (cmd *XAutoClaimJustIDCmd) SetVal(val []string, start string) {
  1470. cmd.val = val
  1471. cmd.start = start
  1472. }
  1473. func (cmd *XAutoClaimJustIDCmd) Val() (ids []string, start string) {
  1474. return cmd.val, cmd.start
  1475. }
  1476. func (cmd *XAutoClaimJustIDCmd) Result() (ids []string, start string, err error) {
  1477. return cmd.val, cmd.start, cmd.err
  1478. }
  1479. func (cmd *XAutoClaimJustIDCmd) String() string {
  1480. return cmdString(cmd, cmd.val)
  1481. }
  1482. func (cmd *XAutoClaimJustIDCmd) readReply(rd *proto.Reader) error {
  1483. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1484. if n != 2 {
  1485. return nil, fmt.Errorf("got %d, wanted 2", n)
  1486. }
  1487. var err error
  1488. cmd.start, err = rd.ReadString()
  1489. if err != nil {
  1490. return nil, err
  1491. }
  1492. nn, err := rd.ReadArrayLen()
  1493. if err != nil {
  1494. return nil, err
  1495. }
  1496. cmd.val = make([]string, nn)
  1497. for i := 0; i < nn; i++ {
  1498. cmd.val[i], err = rd.ReadString()
  1499. if err != nil {
  1500. return nil, err
  1501. }
  1502. }
  1503. return nil, nil
  1504. })
  1505. return err
  1506. }
  1507. //------------------------------------------------------------------------------
  1508. type XInfoConsumersCmd struct {
  1509. baseCmd
  1510. val []XInfoConsumer
  1511. }
  1512. type XInfoConsumer struct {
  1513. Name string
  1514. Pending int64
  1515. Idle int64
  1516. }
  1517. var _ Cmder = (*XInfoConsumersCmd)(nil)
  1518. func NewXInfoConsumersCmd(ctx context.Context, stream string, group string) *XInfoConsumersCmd {
  1519. return &XInfoConsumersCmd{
  1520. baseCmd: baseCmd{
  1521. ctx: ctx,
  1522. args: []interface{}{"xinfo", "consumers", stream, group},
  1523. },
  1524. }
  1525. }
  1526. func (cmd *XInfoConsumersCmd) SetVal(val []XInfoConsumer) {
  1527. cmd.val = val
  1528. }
  1529. func (cmd *XInfoConsumersCmd) Val() []XInfoConsumer {
  1530. return cmd.val
  1531. }
  1532. func (cmd *XInfoConsumersCmd) Result() ([]XInfoConsumer, error) {
  1533. return cmd.val, cmd.err
  1534. }
  1535. func (cmd *XInfoConsumersCmd) String() string {
  1536. return cmdString(cmd, cmd.val)
  1537. }
  1538. func (cmd *XInfoConsumersCmd) readReply(rd *proto.Reader) error {
  1539. n, err := rd.ReadArrayLen()
  1540. if err != nil {
  1541. return err
  1542. }
  1543. cmd.val = make([]XInfoConsumer, n)
  1544. for i := 0; i < n; i++ {
  1545. cmd.val[i], err = readXConsumerInfo(rd)
  1546. if err != nil {
  1547. return err
  1548. }
  1549. }
  1550. return nil
  1551. }
  1552. func readXConsumerInfo(rd *proto.Reader) (XInfoConsumer, error) {
  1553. var consumer XInfoConsumer
  1554. n, err := rd.ReadArrayLen()
  1555. if err != nil {
  1556. return consumer, err
  1557. }
  1558. if n != 6 {
  1559. return consumer, fmt.Errorf("redis: got %d elements in XINFO CONSUMERS reply, wanted 6", n)
  1560. }
  1561. for i := 0; i < 3; i++ {
  1562. key, err := rd.ReadString()
  1563. if err != nil {
  1564. return consumer, err
  1565. }
  1566. val, err := rd.ReadString()
  1567. if err != nil {
  1568. return consumer, err
  1569. }
  1570. switch key {
  1571. case "name":
  1572. consumer.Name = val
  1573. case "pending":
  1574. consumer.Pending, err = strconv.ParseInt(val, 0, 64)
  1575. if err != nil {
  1576. return consumer, err
  1577. }
  1578. case "idle":
  1579. consumer.Idle, err = strconv.ParseInt(val, 0, 64)
  1580. if err != nil {
  1581. return consumer, err
  1582. }
  1583. default:
  1584. return consumer, fmt.Errorf("redis: unexpected content %s in XINFO CONSUMERS reply", key)
  1585. }
  1586. }
  1587. return consumer, nil
  1588. }
  1589. //------------------------------------------------------------------------------
  1590. type XInfoGroupsCmd struct {
  1591. baseCmd
  1592. val []XInfoGroup
  1593. }
  1594. type XInfoGroup struct {
  1595. Name string
  1596. Consumers int64
  1597. Pending int64
  1598. LastDeliveredID string
  1599. }
  1600. var _ Cmder = (*XInfoGroupsCmd)(nil)
  1601. func NewXInfoGroupsCmd(ctx context.Context, stream string) *XInfoGroupsCmd {
  1602. return &XInfoGroupsCmd{
  1603. baseCmd: baseCmd{
  1604. ctx: ctx,
  1605. args: []interface{}{"xinfo", "groups", stream},
  1606. },
  1607. }
  1608. }
  1609. func (cmd *XInfoGroupsCmd) SetVal(val []XInfoGroup) {
  1610. cmd.val = val
  1611. }
  1612. func (cmd *XInfoGroupsCmd) Val() []XInfoGroup {
  1613. return cmd.val
  1614. }
  1615. func (cmd *XInfoGroupsCmd) Result() ([]XInfoGroup, error) {
  1616. return cmd.val, cmd.err
  1617. }
  1618. func (cmd *XInfoGroupsCmd) String() string {
  1619. return cmdString(cmd, cmd.val)
  1620. }
  1621. func (cmd *XInfoGroupsCmd) readReply(rd *proto.Reader) error {
  1622. n, err := rd.ReadArrayLen()
  1623. if err != nil {
  1624. return err
  1625. }
  1626. cmd.val = make([]XInfoGroup, n)
  1627. for i := 0; i < n; i++ {
  1628. cmd.val[i], err = readXGroupInfo(rd)
  1629. if err != nil {
  1630. return err
  1631. }
  1632. }
  1633. return nil
  1634. }
  1635. func readXGroupInfo(rd *proto.Reader) (XInfoGroup, error) {
  1636. var group XInfoGroup
  1637. n, err := rd.ReadArrayLen()
  1638. if err != nil {
  1639. return group, err
  1640. }
  1641. if n != 8 {
  1642. return group, fmt.Errorf("redis: got %d elements in XINFO GROUPS reply, wanted 8", n)
  1643. }
  1644. for i := 0; i < 4; i++ {
  1645. key, err := rd.ReadString()
  1646. if err != nil {
  1647. return group, err
  1648. }
  1649. val, err := rd.ReadString()
  1650. if err != nil {
  1651. return group, err
  1652. }
  1653. switch key {
  1654. case "name":
  1655. group.Name = val
  1656. case "consumers":
  1657. group.Consumers, err = strconv.ParseInt(val, 0, 64)
  1658. if err != nil {
  1659. return group, err
  1660. }
  1661. case "pending":
  1662. group.Pending, err = strconv.ParseInt(val, 0, 64)
  1663. if err != nil {
  1664. return group, err
  1665. }
  1666. case "last-delivered-id":
  1667. group.LastDeliveredID = val
  1668. default:
  1669. return group, fmt.Errorf("redis: unexpected content %s in XINFO GROUPS reply", key)
  1670. }
  1671. }
  1672. return group, nil
  1673. }
  1674. //------------------------------------------------------------------------------
  1675. type XInfoStreamCmd struct {
  1676. baseCmd
  1677. val *XInfoStream
  1678. }
  1679. type XInfoStream struct {
  1680. Length int64
  1681. RadixTreeKeys int64
  1682. RadixTreeNodes int64
  1683. Groups int64
  1684. LastGeneratedID string
  1685. FirstEntry XMessage
  1686. LastEntry XMessage
  1687. }
  1688. var _ Cmder = (*XInfoStreamCmd)(nil)
  1689. func NewXInfoStreamCmd(ctx context.Context, stream string) *XInfoStreamCmd {
  1690. return &XInfoStreamCmd{
  1691. baseCmd: baseCmd{
  1692. ctx: ctx,
  1693. args: []interface{}{"xinfo", "stream", stream},
  1694. },
  1695. }
  1696. }
  1697. func (cmd *XInfoStreamCmd) SetVal(val *XInfoStream) {
  1698. cmd.val = val
  1699. }
  1700. func (cmd *XInfoStreamCmd) Val() *XInfoStream {
  1701. return cmd.val
  1702. }
  1703. func (cmd *XInfoStreamCmd) Result() (*XInfoStream, error) {
  1704. return cmd.val, cmd.err
  1705. }
  1706. func (cmd *XInfoStreamCmd) String() string {
  1707. return cmdString(cmd, cmd.val)
  1708. }
  1709. func (cmd *XInfoStreamCmd) readReply(rd *proto.Reader) error {
  1710. v, err := rd.ReadReply(xStreamInfoParser)
  1711. if err != nil {
  1712. return err
  1713. }
  1714. cmd.val = v.(*XInfoStream)
  1715. return nil
  1716. }
  1717. func xStreamInfoParser(rd *proto.Reader, n int64) (interface{}, error) {
  1718. if n != 14 {
  1719. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM reply,"+
  1720. "wanted 14", n)
  1721. }
  1722. var info XInfoStream
  1723. for i := 0; i < 7; i++ {
  1724. key, err := rd.ReadString()
  1725. if err != nil {
  1726. return nil, err
  1727. }
  1728. switch key {
  1729. case "length":
  1730. info.Length, err = rd.ReadIntReply()
  1731. case "radix-tree-keys":
  1732. info.RadixTreeKeys, err = rd.ReadIntReply()
  1733. case "radix-tree-nodes":
  1734. info.RadixTreeNodes, err = rd.ReadIntReply()
  1735. case "groups":
  1736. info.Groups, err = rd.ReadIntReply()
  1737. case "last-generated-id":
  1738. info.LastGeneratedID, err = rd.ReadString()
  1739. case "first-entry":
  1740. info.FirstEntry, err = readXMessage(rd)
  1741. if err == Nil {
  1742. err = nil
  1743. }
  1744. case "last-entry":
  1745. info.LastEntry, err = readXMessage(rd)
  1746. if err == Nil {
  1747. err = nil
  1748. }
  1749. default:
  1750. return nil, fmt.Errorf("redis: unexpected content %s "+
  1751. "in XINFO STREAM reply", key)
  1752. }
  1753. if err != nil {
  1754. return nil, err
  1755. }
  1756. }
  1757. return &info, nil
  1758. }
  1759. //------------------------------------------------------------------------------
  1760. type XInfoStreamFullCmd struct {
  1761. baseCmd
  1762. val *XInfoStreamFull
  1763. }
  1764. type XInfoStreamFull struct {
  1765. Length int64
  1766. RadixTreeKeys int64
  1767. RadixTreeNodes int64
  1768. LastGeneratedID string
  1769. Entries []XMessage
  1770. Groups []XInfoStreamGroup
  1771. }
  1772. type XInfoStreamGroup struct {
  1773. Name string
  1774. LastDeliveredID string
  1775. PelCount int64
  1776. Pending []XInfoStreamGroupPending
  1777. Consumers []XInfoStreamConsumer
  1778. }
  1779. type XInfoStreamGroupPending struct {
  1780. ID string
  1781. Consumer string
  1782. DeliveryTime time.Time
  1783. DeliveryCount int64
  1784. }
  1785. type XInfoStreamConsumer struct {
  1786. Name string
  1787. SeenTime time.Time
  1788. PelCount int64
  1789. Pending []XInfoStreamConsumerPending
  1790. }
  1791. type XInfoStreamConsumerPending struct {
  1792. ID string
  1793. DeliveryTime time.Time
  1794. DeliveryCount int64
  1795. }
  1796. var _ Cmder = (*XInfoStreamFullCmd)(nil)
  1797. func NewXInfoStreamFullCmd(ctx context.Context, args ...interface{}) *XInfoStreamFullCmd {
  1798. return &XInfoStreamFullCmd{
  1799. baseCmd: baseCmd{
  1800. ctx: ctx,
  1801. args: args,
  1802. },
  1803. }
  1804. }
  1805. func (cmd *XInfoStreamFullCmd) SetVal(val *XInfoStreamFull) {
  1806. cmd.val = val
  1807. }
  1808. func (cmd *XInfoStreamFullCmd) Val() *XInfoStreamFull {
  1809. return cmd.val
  1810. }
  1811. func (cmd *XInfoStreamFullCmd) Result() (*XInfoStreamFull, error) {
  1812. return cmd.val, cmd.err
  1813. }
  1814. func (cmd *XInfoStreamFullCmd) String() string {
  1815. return cmdString(cmd, cmd.val)
  1816. }
  1817. func (cmd *XInfoStreamFullCmd) readReply(rd *proto.Reader) error {
  1818. n, err := rd.ReadArrayLen()
  1819. if err != nil {
  1820. return err
  1821. }
  1822. if n != 12 {
  1823. return fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1824. "wanted 12", n)
  1825. }
  1826. cmd.val = &XInfoStreamFull{}
  1827. for i := 0; i < 6; i++ {
  1828. key, err := rd.ReadString()
  1829. if err != nil {
  1830. return err
  1831. }
  1832. switch key {
  1833. case "length":
  1834. cmd.val.Length, err = rd.ReadIntReply()
  1835. case "radix-tree-keys":
  1836. cmd.val.RadixTreeKeys, err = rd.ReadIntReply()
  1837. case "radix-tree-nodes":
  1838. cmd.val.RadixTreeNodes, err = rd.ReadIntReply()
  1839. case "last-generated-id":
  1840. cmd.val.LastGeneratedID, err = rd.ReadString()
  1841. case "entries":
  1842. cmd.val.Entries, err = readXMessageSlice(rd)
  1843. case "groups":
  1844. cmd.val.Groups, err = readStreamGroups(rd)
  1845. default:
  1846. return fmt.Errorf("redis: unexpected content %s "+
  1847. "in XINFO STREAM reply", key)
  1848. }
  1849. if err != nil {
  1850. return err
  1851. }
  1852. }
  1853. return nil
  1854. }
  1855. func readStreamGroups(rd *proto.Reader) ([]XInfoStreamGroup, error) {
  1856. n, err := rd.ReadArrayLen()
  1857. if err != nil {
  1858. return nil, err
  1859. }
  1860. groups := make([]XInfoStreamGroup, 0, n)
  1861. for i := 0; i < n; i++ {
  1862. nn, err := rd.ReadArrayLen()
  1863. if err != nil {
  1864. return nil, err
  1865. }
  1866. if nn != 10 {
  1867. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1868. "wanted 10", nn)
  1869. }
  1870. group := XInfoStreamGroup{}
  1871. for f := 0; f < 5; f++ {
  1872. key, err := rd.ReadString()
  1873. if err != nil {
  1874. return nil, err
  1875. }
  1876. switch key {
  1877. case "name":
  1878. group.Name, err = rd.ReadString()
  1879. case "last-delivered-id":
  1880. group.LastDeliveredID, err = rd.ReadString()
  1881. case "pel-count":
  1882. group.PelCount, err = rd.ReadIntReply()
  1883. case "pending":
  1884. group.Pending, err = readXInfoStreamGroupPending(rd)
  1885. case "consumers":
  1886. group.Consumers, err = readXInfoStreamConsumers(rd)
  1887. default:
  1888. return nil, fmt.Errorf("redis: unexpected content %s "+
  1889. "in XINFO STREAM reply", key)
  1890. }
  1891. if err != nil {
  1892. return nil, err
  1893. }
  1894. }
  1895. groups = append(groups, group)
  1896. }
  1897. return groups, nil
  1898. }
  1899. func readXInfoStreamGroupPending(rd *proto.Reader) ([]XInfoStreamGroupPending, error) {
  1900. n, err := rd.ReadArrayLen()
  1901. if err != nil {
  1902. return nil, err
  1903. }
  1904. pending := make([]XInfoStreamGroupPending, 0, n)
  1905. for i := 0; i < n; i++ {
  1906. nn, err := rd.ReadArrayLen()
  1907. if err != nil {
  1908. return nil, err
  1909. }
  1910. if nn != 4 {
  1911. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1912. "wanted 4", nn)
  1913. }
  1914. p := XInfoStreamGroupPending{}
  1915. p.ID, err = rd.ReadString()
  1916. if err != nil {
  1917. return nil, err
  1918. }
  1919. p.Consumer, err = rd.ReadString()
  1920. if err != nil {
  1921. return nil, err
  1922. }
  1923. delivery, err := rd.ReadIntReply()
  1924. if err != nil {
  1925. return nil, err
  1926. }
  1927. p.DeliveryTime = time.Unix(delivery/1000, delivery%1000*int64(time.Millisecond))
  1928. p.DeliveryCount, err = rd.ReadIntReply()
  1929. if err != nil {
  1930. return nil, err
  1931. }
  1932. pending = append(pending, p)
  1933. }
  1934. return pending, nil
  1935. }
  1936. func readXInfoStreamConsumers(rd *proto.Reader) ([]XInfoStreamConsumer, error) {
  1937. n, err := rd.ReadArrayLen()
  1938. if err != nil {
  1939. return nil, err
  1940. }
  1941. consumers := make([]XInfoStreamConsumer, 0, n)
  1942. for i := 0; i < n; i++ {
  1943. nn, err := rd.ReadArrayLen()
  1944. if err != nil {
  1945. return nil, err
  1946. }
  1947. if nn != 8 {
  1948. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM FULL reply,"+
  1949. "wanted 8", nn)
  1950. }
  1951. c := XInfoStreamConsumer{}
  1952. for f := 0; f < 4; f++ {
  1953. cKey, err := rd.ReadString()
  1954. if err != nil {
  1955. return nil, err
  1956. }
  1957. switch cKey {
  1958. case "name":
  1959. c.Name, err = rd.ReadString()
  1960. case "seen-time":
  1961. seen, err := rd.ReadIntReply()
  1962. if err != nil {
  1963. return nil, err
  1964. }
  1965. c.SeenTime = time.Unix(seen/1000, seen%1000*int64(time.Millisecond))
  1966. case "pel-count":
  1967. c.PelCount, err = rd.ReadIntReply()
  1968. case "pending":
  1969. pendingNumber, err := rd.ReadArrayLen()
  1970. if err != nil {
  1971. return nil, err
  1972. }
  1973. c.Pending = make([]XInfoStreamConsumerPending, 0, pendingNumber)
  1974. for pn := 0; pn < pendingNumber; pn++ {
  1975. nn, err := rd.ReadArrayLen()
  1976. if err != nil {
  1977. return nil, err
  1978. }
  1979. if nn != 3 {
  1980. return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM reply,"+
  1981. "wanted 3", nn)
  1982. }
  1983. p := XInfoStreamConsumerPending{}
  1984. p.ID, err = rd.ReadString()
  1985. if err != nil {
  1986. return nil, err
  1987. }
  1988. delivery, err := rd.ReadIntReply()
  1989. if err != nil {
  1990. return nil, err
  1991. }
  1992. p.DeliveryTime = time.Unix(delivery/1000, delivery%1000*int64(time.Millisecond))
  1993. p.DeliveryCount, err = rd.ReadIntReply()
  1994. if err != nil {
  1995. return nil, err
  1996. }
  1997. c.Pending = append(c.Pending, p)
  1998. }
  1999. default:
  2000. return nil, fmt.Errorf("redis: unexpected content %s "+
  2001. "in XINFO STREAM reply", cKey)
  2002. }
  2003. if err != nil {
  2004. return nil, err
  2005. }
  2006. }
  2007. consumers = append(consumers, c)
  2008. }
  2009. return consumers, nil
  2010. }
  2011. //------------------------------------------------------------------------------
  2012. type ZSliceCmd struct {
  2013. baseCmd
  2014. val []Z
  2015. }
  2016. var _ Cmder = (*ZSliceCmd)(nil)
  2017. func NewZSliceCmd(ctx context.Context, args ...interface{}) *ZSliceCmd {
  2018. return &ZSliceCmd{
  2019. baseCmd: baseCmd{
  2020. ctx: ctx,
  2021. args: args,
  2022. },
  2023. }
  2024. }
  2025. func (cmd *ZSliceCmd) SetVal(val []Z) {
  2026. cmd.val = val
  2027. }
  2028. func (cmd *ZSliceCmd) Val() []Z {
  2029. return cmd.val
  2030. }
  2031. func (cmd *ZSliceCmd) Result() ([]Z, error) {
  2032. return cmd.val, cmd.err
  2033. }
  2034. func (cmd *ZSliceCmd) String() string {
  2035. return cmdString(cmd, cmd.val)
  2036. }
  2037. func (cmd *ZSliceCmd) readReply(rd *proto.Reader) error {
  2038. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2039. cmd.val = make([]Z, n/2)
  2040. for i := 0; i < len(cmd.val); i++ {
  2041. member, err := rd.ReadString()
  2042. if err != nil {
  2043. return nil, err
  2044. }
  2045. score, err := rd.ReadFloatReply()
  2046. if err != nil {
  2047. return nil, err
  2048. }
  2049. cmd.val[i] = Z{
  2050. Member: member,
  2051. Score: score,
  2052. }
  2053. }
  2054. return nil, nil
  2055. })
  2056. return err
  2057. }
  2058. //------------------------------------------------------------------------------
  2059. type ZWithKeyCmd struct {
  2060. baseCmd
  2061. val *ZWithKey
  2062. }
  2063. var _ Cmder = (*ZWithKeyCmd)(nil)
  2064. func NewZWithKeyCmd(ctx context.Context, args ...interface{}) *ZWithKeyCmd {
  2065. return &ZWithKeyCmd{
  2066. baseCmd: baseCmd{
  2067. ctx: ctx,
  2068. args: args,
  2069. },
  2070. }
  2071. }
  2072. func (cmd *ZWithKeyCmd) SetVal(val *ZWithKey) {
  2073. cmd.val = val
  2074. }
  2075. func (cmd *ZWithKeyCmd) Val() *ZWithKey {
  2076. return cmd.val
  2077. }
  2078. func (cmd *ZWithKeyCmd) Result() (*ZWithKey, error) {
  2079. return cmd.Val(), cmd.Err()
  2080. }
  2081. func (cmd *ZWithKeyCmd) String() string {
  2082. return cmdString(cmd, cmd.val)
  2083. }
  2084. func (cmd *ZWithKeyCmd) readReply(rd *proto.Reader) error {
  2085. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2086. if n != 3 {
  2087. return nil, fmt.Errorf("got %d elements, expected 3", n)
  2088. }
  2089. cmd.val = &ZWithKey{}
  2090. var err error
  2091. cmd.val.Key, err = rd.ReadString()
  2092. if err != nil {
  2093. return nil, err
  2094. }
  2095. cmd.val.Member, err = rd.ReadString()
  2096. if err != nil {
  2097. return nil, err
  2098. }
  2099. cmd.val.Score, err = rd.ReadFloatReply()
  2100. if err != nil {
  2101. return nil, err
  2102. }
  2103. return nil, nil
  2104. })
  2105. return err
  2106. }
  2107. //------------------------------------------------------------------------------
  2108. type ScanCmd struct {
  2109. baseCmd
  2110. page []string
  2111. cursor uint64
  2112. process cmdable
  2113. }
  2114. var _ Cmder = (*ScanCmd)(nil)
  2115. func NewScanCmd(ctx context.Context, process cmdable, args ...interface{}) *ScanCmd {
  2116. return &ScanCmd{
  2117. baseCmd: baseCmd{
  2118. ctx: ctx,
  2119. args: args,
  2120. },
  2121. process: process,
  2122. }
  2123. }
  2124. func (cmd *ScanCmd) SetVal(page []string, cursor uint64) {
  2125. cmd.page = page
  2126. cmd.cursor = cursor
  2127. }
  2128. func (cmd *ScanCmd) Val() (keys []string, cursor uint64) {
  2129. return cmd.page, cmd.cursor
  2130. }
  2131. func (cmd *ScanCmd) Result() (keys []string, cursor uint64, err error) {
  2132. return cmd.page, cmd.cursor, cmd.err
  2133. }
  2134. func (cmd *ScanCmd) String() string {
  2135. return cmdString(cmd, cmd.page)
  2136. }
  2137. func (cmd *ScanCmd) readReply(rd *proto.Reader) (err error) {
  2138. cmd.page, cmd.cursor, err = rd.ReadScanReply()
  2139. return err
  2140. }
  2141. // Iterator creates a new ScanIterator.
  2142. func (cmd *ScanCmd) Iterator() *ScanIterator {
  2143. return &ScanIterator{
  2144. cmd: cmd,
  2145. }
  2146. }
  2147. //------------------------------------------------------------------------------
  2148. type ClusterNode struct {
  2149. ID string
  2150. Addr string
  2151. }
  2152. type ClusterSlot struct {
  2153. Start int
  2154. End int
  2155. Nodes []ClusterNode
  2156. }
  2157. type ClusterSlotsCmd struct {
  2158. baseCmd
  2159. val []ClusterSlot
  2160. }
  2161. var _ Cmder = (*ClusterSlotsCmd)(nil)
  2162. func NewClusterSlotsCmd(ctx context.Context, args ...interface{}) *ClusterSlotsCmd {
  2163. return &ClusterSlotsCmd{
  2164. baseCmd: baseCmd{
  2165. ctx: ctx,
  2166. args: args,
  2167. },
  2168. }
  2169. }
  2170. func (cmd *ClusterSlotsCmd) SetVal(val []ClusterSlot) {
  2171. cmd.val = val
  2172. }
  2173. func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
  2174. return cmd.val
  2175. }
  2176. func (cmd *ClusterSlotsCmd) Result() ([]ClusterSlot, error) {
  2177. return cmd.Val(), cmd.Err()
  2178. }
  2179. func (cmd *ClusterSlotsCmd) String() string {
  2180. return cmdString(cmd, cmd.val)
  2181. }
  2182. func (cmd *ClusterSlotsCmd) readReply(rd *proto.Reader) error {
  2183. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2184. cmd.val = make([]ClusterSlot, n)
  2185. for i := 0; i < len(cmd.val); i++ {
  2186. n, err := rd.ReadArrayLen()
  2187. if err != nil {
  2188. return nil, err
  2189. }
  2190. if n < 2 {
  2191. err := fmt.Errorf("redis: got %d elements in cluster info, expected at least 2", n)
  2192. return nil, err
  2193. }
  2194. start, err := rd.ReadIntReply()
  2195. if err != nil {
  2196. return nil, err
  2197. }
  2198. end, err := rd.ReadIntReply()
  2199. if err != nil {
  2200. return nil, err
  2201. }
  2202. nodes := make([]ClusterNode, n-2)
  2203. for j := 0; j < len(nodes); j++ {
  2204. n, err := rd.ReadArrayLen()
  2205. if err != nil {
  2206. return nil, err
  2207. }
  2208. if n != 2 && n != 3 {
  2209. err := fmt.Errorf("got %d elements in cluster info address, expected 2 or 3", n)
  2210. return nil, err
  2211. }
  2212. ip, err := rd.ReadString()
  2213. if err != nil {
  2214. return nil, err
  2215. }
  2216. port, err := rd.ReadString()
  2217. if err != nil {
  2218. return nil, err
  2219. }
  2220. nodes[j].Addr = net.JoinHostPort(ip, port)
  2221. if n == 3 {
  2222. id, err := rd.ReadString()
  2223. if err != nil {
  2224. return nil, err
  2225. }
  2226. nodes[j].ID = id
  2227. }
  2228. }
  2229. cmd.val[i] = ClusterSlot{
  2230. Start: int(start),
  2231. End: int(end),
  2232. Nodes: nodes,
  2233. }
  2234. }
  2235. return nil, nil
  2236. })
  2237. return err
  2238. }
  2239. //------------------------------------------------------------------------------
  2240. // GeoLocation is used with GeoAdd to add geospatial location.
  2241. type GeoLocation struct {
  2242. Name string
  2243. Longitude, Latitude, Dist float64
  2244. GeoHash int64
  2245. }
  2246. // GeoRadiusQuery is used with GeoRadius to query geospatial index.
  2247. type GeoRadiusQuery struct {
  2248. Radius float64
  2249. // Can be m, km, ft, or mi. Default is km.
  2250. Unit string
  2251. WithCoord bool
  2252. WithDist bool
  2253. WithGeoHash bool
  2254. Count int
  2255. // Can be ASC or DESC. Default is no sort order.
  2256. Sort string
  2257. Store string
  2258. StoreDist string
  2259. }
  2260. type GeoLocationCmd struct {
  2261. baseCmd
  2262. q *GeoRadiusQuery
  2263. locations []GeoLocation
  2264. }
  2265. var _ Cmder = (*GeoLocationCmd)(nil)
  2266. func NewGeoLocationCmd(ctx context.Context, q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
  2267. return &GeoLocationCmd{
  2268. baseCmd: baseCmd{
  2269. ctx: ctx,
  2270. args: geoLocationArgs(q, args...),
  2271. },
  2272. q: q,
  2273. }
  2274. }
  2275. func geoLocationArgs(q *GeoRadiusQuery, args ...interface{}) []interface{} {
  2276. args = append(args, q.Radius)
  2277. if q.Unit != "" {
  2278. args = append(args, q.Unit)
  2279. } else {
  2280. args = append(args, "km")
  2281. }
  2282. if q.WithCoord {
  2283. args = append(args, "withcoord")
  2284. }
  2285. if q.WithDist {
  2286. args = append(args, "withdist")
  2287. }
  2288. if q.WithGeoHash {
  2289. args = append(args, "withhash")
  2290. }
  2291. if q.Count > 0 {
  2292. args = append(args, "count", q.Count)
  2293. }
  2294. if q.Sort != "" {
  2295. args = append(args, q.Sort)
  2296. }
  2297. if q.Store != "" {
  2298. args = append(args, "store")
  2299. args = append(args, q.Store)
  2300. }
  2301. if q.StoreDist != "" {
  2302. args = append(args, "storedist")
  2303. args = append(args, q.StoreDist)
  2304. }
  2305. return args
  2306. }
  2307. func (cmd *GeoLocationCmd) SetVal(locations []GeoLocation) {
  2308. cmd.locations = locations
  2309. }
  2310. func (cmd *GeoLocationCmd) Val() []GeoLocation {
  2311. return cmd.locations
  2312. }
  2313. func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) {
  2314. return cmd.locations, cmd.err
  2315. }
  2316. func (cmd *GeoLocationCmd) String() string {
  2317. return cmdString(cmd, cmd.locations)
  2318. }
  2319. func (cmd *GeoLocationCmd) readReply(rd *proto.Reader) error {
  2320. v, err := rd.ReadArrayReply(newGeoLocationSliceParser(cmd.q))
  2321. if err != nil {
  2322. return err
  2323. }
  2324. cmd.locations = v.([]GeoLocation)
  2325. return nil
  2326. }
  2327. func newGeoLocationSliceParser(q *GeoRadiusQuery) proto.MultiBulkParse {
  2328. return func(rd *proto.Reader, n int64) (interface{}, error) {
  2329. locs := make([]GeoLocation, 0, n)
  2330. for i := int64(0); i < n; i++ {
  2331. v, err := rd.ReadReply(newGeoLocationParser(q))
  2332. if err != nil {
  2333. return nil, err
  2334. }
  2335. switch vv := v.(type) {
  2336. case string:
  2337. locs = append(locs, GeoLocation{
  2338. Name: vv,
  2339. })
  2340. case *GeoLocation:
  2341. // TODO: avoid copying
  2342. locs = append(locs, *vv)
  2343. default:
  2344. return nil, fmt.Errorf("got %T, expected string or *GeoLocation", v)
  2345. }
  2346. }
  2347. return locs, nil
  2348. }
  2349. }
  2350. func newGeoLocationParser(q *GeoRadiusQuery) proto.MultiBulkParse {
  2351. return func(rd *proto.Reader, n int64) (interface{}, error) {
  2352. var loc GeoLocation
  2353. var err error
  2354. loc.Name, err = rd.ReadString()
  2355. if err != nil {
  2356. return nil, err
  2357. }
  2358. if q.WithDist {
  2359. loc.Dist, err = rd.ReadFloatReply()
  2360. if err != nil {
  2361. return nil, err
  2362. }
  2363. }
  2364. if q.WithGeoHash {
  2365. loc.GeoHash, err = rd.ReadIntReply()
  2366. if err != nil {
  2367. return nil, err
  2368. }
  2369. }
  2370. if q.WithCoord {
  2371. n, err := rd.ReadArrayLen()
  2372. if err != nil {
  2373. return nil, err
  2374. }
  2375. if n != 2 {
  2376. return nil, fmt.Errorf("got %d coordinates, expected 2", n)
  2377. }
  2378. loc.Longitude, err = rd.ReadFloatReply()
  2379. if err != nil {
  2380. return nil, err
  2381. }
  2382. loc.Latitude, err = rd.ReadFloatReply()
  2383. if err != nil {
  2384. return nil, err
  2385. }
  2386. }
  2387. return &loc, nil
  2388. }
  2389. }
  2390. //------------------------------------------------------------------------------
  2391. // GeoSearchQuery is used for GEOSearch/GEOSearchStore command query.
  2392. type GeoSearchQuery struct {
  2393. Member string
  2394. // Latitude and Longitude when using FromLonLat option.
  2395. Longitude float64
  2396. Latitude float64
  2397. // Distance and unit when using ByRadius option.
  2398. // Can use m, km, ft, or mi. Default is km.
  2399. Radius float64
  2400. RadiusUnit string
  2401. // Height, width and unit when using ByBox option.
  2402. // Can be m, km, ft, or mi. Default is km.
  2403. BoxWidth float64
  2404. BoxHeight float64
  2405. BoxUnit string
  2406. // Can be ASC or DESC. Default is no sort order.
  2407. Sort string
  2408. Count int
  2409. CountAny bool
  2410. }
  2411. type GeoSearchLocationQuery struct {
  2412. GeoSearchQuery
  2413. WithCoord bool
  2414. WithDist bool
  2415. WithHash bool
  2416. }
  2417. type GeoSearchStoreQuery struct {
  2418. GeoSearchQuery
  2419. // When using the StoreDist option, the command stores the items in a
  2420. // sorted set populated with their distance from the center of the circle or box,
  2421. // as a floating-point number, in the same unit specified for that shape.
  2422. StoreDist bool
  2423. }
  2424. func geoSearchLocationArgs(q *GeoSearchLocationQuery, args []interface{}) []interface{} {
  2425. args = geoSearchArgs(&q.GeoSearchQuery, args)
  2426. if q.WithCoord {
  2427. args = append(args, "withcoord")
  2428. }
  2429. if q.WithDist {
  2430. args = append(args, "withdist")
  2431. }
  2432. if q.WithHash {
  2433. args = append(args, "withhash")
  2434. }
  2435. return args
  2436. }
  2437. func geoSearchArgs(q *GeoSearchQuery, args []interface{}) []interface{} {
  2438. if q.Member != "" {
  2439. args = append(args, "frommember", q.Member)
  2440. } else {
  2441. args = append(args, "fromlonlat", q.Longitude, q.Latitude)
  2442. }
  2443. if q.Radius > 0 {
  2444. if q.RadiusUnit == "" {
  2445. q.RadiusUnit = "km"
  2446. }
  2447. args = append(args, "byradius", q.Radius, q.RadiusUnit)
  2448. } else {
  2449. if q.BoxUnit == "" {
  2450. q.BoxUnit = "km"
  2451. }
  2452. args = append(args, "bybox", q.BoxWidth, q.BoxHeight, q.BoxUnit)
  2453. }
  2454. if q.Sort != "" {
  2455. args = append(args, q.Sort)
  2456. }
  2457. if q.Count > 0 {
  2458. args = append(args, "count", q.Count)
  2459. if q.CountAny {
  2460. args = append(args, "any")
  2461. }
  2462. }
  2463. return args
  2464. }
  2465. type GeoSearchLocationCmd struct {
  2466. baseCmd
  2467. opt *GeoSearchLocationQuery
  2468. val []GeoLocation
  2469. }
  2470. var _ Cmder = (*GeoSearchLocationCmd)(nil)
  2471. func NewGeoSearchLocationCmd(
  2472. ctx context.Context, opt *GeoSearchLocationQuery, args ...interface{},
  2473. ) *GeoSearchLocationCmd {
  2474. return &GeoSearchLocationCmd{
  2475. baseCmd: baseCmd{
  2476. ctx: ctx,
  2477. args: args,
  2478. },
  2479. opt: opt,
  2480. }
  2481. }
  2482. func (cmd *GeoSearchLocationCmd) SetVal(val []GeoLocation) {
  2483. cmd.val = val
  2484. }
  2485. func (cmd *GeoSearchLocationCmd) Val() []GeoLocation {
  2486. return cmd.val
  2487. }
  2488. func (cmd *GeoSearchLocationCmd) Result() ([]GeoLocation, error) {
  2489. return cmd.val, cmd.err
  2490. }
  2491. func (cmd *GeoSearchLocationCmd) String() string {
  2492. return cmdString(cmd, cmd.val)
  2493. }
  2494. func (cmd *GeoSearchLocationCmd) readReply(rd *proto.Reader) error {
  2495. n, err := rd.ReadArrayLen()
  2496. if err != nil {
  2497. return err
  2498. }
  2499. cmd.val = make([]GeoLocation, n)
  2500. for i := 0; i < n; i++ {
  2501. _, err = rd.ReadArrayLen()
  2502. if err != nil {
  2503. return err
  2504. }
  2505. var loc GeoLocation
  2506. loc.Name, err = rd.ReadString()
  2507. if err != nil {
  2508. return err
  2509. }
  2510. if cmd.opt.WithDist {
  2511. loc.Dist, err = rd.ReadFloatReply()
  2512. if err != nil {
  2513. return err
  2514. }
  2515. }
  2516. if cmd.opt.WithHash {
  2517. loc.GeoHash, err = rd.ReadIntReply()
  2518. if err != nil {
  2519. return err
  2520. }
  2521. }
  2522. if cmd.opt.WithCoord {
  2523. nn, err := rd.ReadArrayLen()
  2524. if err != nil {
  2525. return err
  2526. }
  2527. if nn != 2 {
  2528. return fmt.Errorf("got %d coordinates, expected 2", nn)
  2529. }
  2530. loc.Longitude, err = rd.ReadFloatReply()
  2531. if err != nil {
  2532. return err
  2533. }
  2534. loc.Latitude, err = rd.ReadFloatReply()
  2535. if err != nil {
  2536. return err
  2537. }
  2538. }
  2539. cmd.val[i] = loc
  2540. }
  2541. return nil
  2542. }
  2543. //------------------------------------------------------------------------------
  2544. type GeoPos struct {
  2545. Longitude, Latitude float64
  2546. }
  2547. type GeoPosCmd struct {
  2548. baseCmd
  2549. val []*GeoPos
  2550. }
  2551. var _ Cmder = (*GeoPosCmd)(nil)
  2552. func NewGeoPosCmd(ctx context.Context, args ...interface{}) *GeoPosCmd {
  2553. return &GeoPosCmd{
  2554. baseCmd: baseCmd{
  2555. ctx: ctx,
  2556. args: args,
  2557. },
  2558. }
  2559. }
  2560. func (cmd *GeoPosCmd) SetVal(val []*GeoPos) {
  2561. cmd.val = val
  2562. }
  2563. func (cmd *GeoPosCmd) Val() []*GeoPos {
  2564. return cmd.val
  2565. }
  2566. func (cmd *GeoPosCmd) Result() ([]*GeoPos, error) {
  2567. return cmd.Val(), cmd.Err()
  2568. }
  2569. func (cmd *GeoPosCmd) String() string {
  2570. return cmdString(cmd, cmd.val)
  2571. }
  2572. func (cmd *GeoPosCmd) readReply(rd *proto.Reader) error {
  2573. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2574. cmd.val = make([]*GeoPos, n)
  2575. for i := 0; i < len(cmd.val); i++ {
  2576. i := i
  2577. _, err := rd.ReadReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2578. longitude, err := rd.ReadFloatReply()
  2579. if err != nil {
  2580. return nil, err
  2581. }
  2582. latitude, err := rd.ReadFloatReply()
  2583. if err != nil {
  2584. return nil, err
  2585. }
  2586. cmd.val[i] = &GeoPos{
  2587. Longitude: longitude,
  2588. Latitude: latitude,
  2589. }
  2590. return nil, nil
  2591. })
  2592. if err != nil {
  2593. if err == Nil {
  2594. cmd.val[i] = nil
  2595. continue
  2596. }
  2597. return nil, err
  2598. }
  2599. }
  2600. return nil, nil
  2601. })
  2602. return err
  2603. }
  2604. //------------------------------------------------------------------------------
  2605. type CommandInfo struct {
  2606. Name string
  2607. Arity int8
  2608. Flags []string
  2609. ACLFlags []string
  2610. FirstKeyPos int8
  2611. LastKeyPos int8
  2612. StepCount int8
  2613. ReadOnly bool
  2614. }
  2615. type CommandsInfoCmd struct {
  2616. baseCmd
  2617. val map[string]*CommandInfo
  2618. }
  2619. var _ Cmder = (*CommandsInfoCmd)(nil)
  2620. func NewCommandsInfoCmd(ctx context.Context, args ...interface{}) *CommandsInfoCmd {
  2621. return &CommandsInfoCmd{
  2622. baseCmd: baseCmd{
  2623. ctx: ctx,
  2624. args: args,
  2625. },
  2626. }
  2627. }
  2628. func (cmd *CommandsInfoCmd) SetVal(val map[string]*CommandInfo) {
  2629. cmd.val = val
  2630. }
  2631. func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
  2632. return cmd.val
  2633. }
  2634. func (cmd *CommandsInfoCmd) Result() (map[string]*CommandInfo, error) {
  2635. return cmd.Val(), cmd.Err()
  2636. }
  2637. func (cmd *CommandsInfoCmd) String() string {
  2638. return cmdString(cmd, cmd.val)
  2639. }
  2640. func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
  2641. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2642. cmd.val = make(map[string]*CommandInfo, n)
  2643. for i := int64(0); i < n; i++ {
  2644. v, err := rd.ReadReply(commandInfoParser)
  2645. if err != nil {
  2646. return nil, err
  2647. }
  2648. vv := v.(*CommandInfo)
  2649. cmd.val[vv.Name] = vv
  2650. }
  2651. return nil, nil
  2652. })
  2653. return err
  2654. }
  2655. func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) {
  2656. const numArgRedis5 = 6
  2657. const numArgRedis6 = 7
  2658. switch n {
  2659. case numArgRedis5, numArgRedis6:
  2660. // continue
  2661. default:
  2662. return nil, fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 7", n)
  2663. }
  2664. var cmd CommandInfo
  2665. var err error
  2666. cmd.Name, err = rd.ReadString()
  2667. if err != nil {
  2668. return nil, err
  2669. }
  2670. arity, err := rd.ReadIntReply()
  2671. if err != nil {
  2672. return nil, err
  2673. }
  2674. cmd.Arity = int8(arity)
  2675. _, err = rd.ReadReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2676. cmd.Flags = make([]string, n)
  2677. for i := 0; i < len(cmd.Flags); i++ {
  2678. switch s, err := rd.ReadString(); {
  2679. case err == Nil:
  2680. cmd.Flags[i] = ""
  2681. case err != nil:
  2682. return nil, err
  2683. default:
  2684. cmd.Flags[i] = s
  2685. }
  2686. }
  2687. return nil, nil
  2688. })
  2689. if err != nil {
  2690. return nil, err
  2691. }
  2692. firstKeyPos, err := rd.ReadIntReply()
  2693. if err != nil {
  2694. return nil, err
  2695. }
  2696. cmd.FirstKeyPos = int8(firstKeyPos)
  2697. lastKeyPos, err := rd.ReadIntReply()
  2698. if err != nil {
  2699. return nil, err
  2700. }
  2701. cmd.LastKeyPos = int8(lastKeyPos)
  2702. stepCount, err := rd.ReadIntReply()
  2703. if err != nil {
  2704. return nil, err
  2705. }
  2706. cmd.StepCount = int8(stepCount)
  2707. for _, flag := range cmd.Flags {
  2708. if flag == "readonly" {
  2709. cmd.ReadOnly = true
  2710. break
  2711. }
  2712. }
  2713. if n == numArgRedis5 {
  2714. return &cmd, nil
  2715. }
  2716. _, err = rd.ReadReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2717. cmd.ACLFlags = make([]string, n)
  2718. for i := 0; i < len(cmd.ACLFlags); i++ {
  2719. switch s, err := rd.ReadString(); {
  2720. case err == Nil:
  2721. cmd.ACLFlags[i] = ""
  2722. case err != nil:
  2723. return nil, err
  2724. default:
  2725. cmd.ACLFlags[i] = s
  2726. }
  2727. }
  2728. return nil, nil
  2729. })
  2730. if err != nil {
  2731. return nil, err
  2732. }
  2733. return &cmd, nil
  2734. }
  2735. //------------------------------------------------------------------------------
  2736. type cmdsInfoCache struct {
  2737. fn func(ctx context.Context) (map[string]*CommandInfo, error)
  2738. once internal.Once
  2739. cmds map[string]*CommandInfo
  2740. }
  2741. func newCmdsInfoCache(fn func(ctx context.Context) (map[string]*CommandInfo, error)) *cmdsInfoCache {
  2742. return &cmdsInfoCache{
  2743. fn: fn,
  2744. }
  2745. }
  2746. func (c *cmdsInfoCache) Get(ctx context.Context) (map[string]*CommandInfo, error) {
  2747. err := c.once.Do(func() error {
  2748. cmds, err := c.fn(ctx)
  2749. if err != nil {
  2750. return err
  2751. }
  2752. // Extensions have cmd names in upper case. Convert them to lower case.
  2753. for k, v := range cmds {
  2754. lower := internal.ToLower(k)
  2755. if lower != k {
  2756. cmds[lower] = v
  2757. }
  2758. }
  2759. c.cmds = cmds
  2760. return nil
  2761. })
  2762. return c.cmds, err
  2763. }
  2764. //------------------------------------------------------------------------------
  2765. type SlowLog struct {
  2766. ID int64
  2767. Time time.Time
  2768. Duration time.Duration
  2769. Args []string
  2770. // These are also optional fields emitted only by Redis 4.0 or greater:
  2771. // https://redis.io/commands/slowlog#output-format
  2772. ClientAddr string
  2773. ClientName string
  2774. }
  2775. type SlowLogCmd struct {
  2776. baseCmd
  2777. val []SlowLog
  2778. }
  2779. var _ Cmder = (*SlowLogCmd)(nil)
  2780. func NewSlowLogCmd(ctx context.Context, args ...interface{}) *SlowLogCmd {
  2781. return &SlowLogCmd{
  2782. baseCmd: baseCmd{
  2783. ctx: ctx,
  2784. args: args,
  2785. },
  2786. }
  2787. }
  2788. func (cmd *SlowLogCmd) SetVal(val []SlowLog) {
  2789. cmd.val = val
  2790. }
  2791. func (cmd *SlowLogCmd) Val() []SlowLog {
  2792. return cmd.val
  2793. }
  2794. func (cmd *SlowLogCmd) Result() ([]SlowLog, error) {
  2795. return cmd.Val(), cmd.Err()
  2796. }
  2797. func (cmd *SlowLogCmd) String() string {
  2798. return cmdString(cmd, cmd.val)
  2799. }
  2800. func (cmd *SlowLogCmd) readReply(rd *proto.Reader) error {
  2801. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  2802. cmd.val = make([]SlowLog, n)
  2803. for i := 0; i < len(cmd.val); i++ {
  2804. n, err := rd.ReadArrayLen()
  2805. if err != nil {
  2806. return nil, err
  2807. }
  2808. if n < 4 {
  2809. err := fmt.Errorf("redis: got %d elements in slowlog get, expected at least 4", n)
  2810. return nil, err
  2811. }
  2812. id, err := rd.ReadIntReply()
  2813. if err != nil {
  2814. return nil, err
  2815. }
  2816. createdAt, err := rd.ReadIntReply()
  2817. if err != nil {
  2818. return nil, err
  2819. }
  2820. createdAtTime := time.Unix(createdAt, 0)
  2821. costs, err := rd.ReadIntReply()
  2822. if err != nil {
  2823. return nil, err
  2824. }
  2825. costsDuration := time.Duration(costs) * time.Microsecond
  2826. cmdLen, err := rd.ReadArrayLen()
  2827. if err != nil {
  2828. return nil, err
  2829. }
  2830. if cmdLen < 1 {
  2831. err := fmt.Errorf("redis: got %d elements commands reply in slowlog get, expected at least 1", cmdLen)
  2832. return nil, err
  2833. }
  2834. cmdString := make([]string, cmdLen)
  2835. for i := 0; i < cmdLen; i++ {
  2836. cmdString[i], err = rd.ReadString()
  2837. if err != nil {
  2838. return nil, err
  2839. }
  2840. }
  2841. var address, name string
  2842. for i := 4; i < n; i++ {
  2843. str, err := rd.ReadString()
  2844. if err != nil {
  2845. return nil, err
  2846. }
  2847. if i == 4 {
  2848. address = str
  2849. } else if i == 5 {
  2850. name = str
  2851. }
  2852. }
  2853. cmd.val[i] = SlowLog{
  2854. ID: id,
  2855. Time: createdAtTime,
  2856. Duration: costsDuration,
  2857. Args: cmdString,
  2858. ClientAddr: address,
  2859. ClientName: name,
  2860. }
  2861. }
  2862. return nil, nil
  2863. })
  2864. return err
  2865. }