本站源代码
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

1937 行
37KB

  1. package redis
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "github.com/go-redis/redis/internal"
  9. "github.com/go-redis/redis/internal/proto"
  10. )
  11. type Cmder interface {
  12. Name() string
  13. Args() []interface{}
  14. stringArg(int) string
  15. readReply(rd *proto.Reader) error
  16. setErr(error)
  17. readTimeout() *time.Duration
  18. Err() error
  19. }
  20. func setCmdsErr(cmds []Cmder, e error) {
  21. for _, cmd := range cmds {
  22. if cmd.Err() == nil {
  23. cmd.setErr(e)
  24. }
  25. }
  26. }
  27. func cmdsFirstErr(cmds []Cmder) error {
  28. for _, cmd := range cmds {
  29. if err := cmd.Err(); err != nil {
  30. return err
  31. }
  32. }
  33. return nil
  34. }
  35. func writeCmd(wr *proto.Writer, cmds ...Cmder) error {
  36. for _, cmd := range cmds {
  37. err := wr.WriteArgs(cmd.Args())
  38. if err != nil {
  39. return err
  40. }
  41. }
  42. return nil
  43. }
  44. func cmdString(cmd Cmder, val interface{}) string {
  45. var ss []string
  46. for _, arg := range cmd.Args() {
  47. ss = append(ss, fmt.Sprint(arg))
  48. }
  49. s := strings.Join(ss, " ")
  50. if err := cmd.Err(); err != nil {
  51. return s + ": " + err.Error()
  52. }
  53. if val != nil {
  54. switch vv := val.(type) {
  55. case []byte:
  56. return s + ": " + string(vv)
  57. default:
  58. return s + ": " + fmt.Sprint(val)
  59. }
  60. }
  61. return s
  62. }
  63. func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
  64. switch cmd.Name() {
  65. case "eval", "evalsha":
  66. if cmd.stringArg(2) != "0" {
  67. return 3
  68. }
  69. return 0
  70. case "publish":
  71. return 1
  72. }
  73. if info == nil {
  74. return 0
  75. }
  76. return int(info.FirstKeyPos)
  77. }
  78. //------------------------------------------------------------------------------
  79. type baseCmd struct {
  80. _args []interface{}
  81. err error
  82. _readTimeout *time.Duration
  83. }
  84. var _ Cmder = (*Cmd)(nil)
  85. func (cmd *baseCmd) Err() error {
  86. return cmd.err
  87. }
  88. func (cmd *baseCmd) Args() []interface{} {
  89. return cmd._args
  90. }
  91. func (cmd *baseCmd) stringArg(pos int) string {
  92. if pos < 0 || pos >= len(cmd._args) {
  93. return ""
  94. }
  95. s, _ := cmd._args[pos].(string)
  96. return s
  97. }
  98. func (cmd *baseCmd) Name() string {
  99. if len(cmd._args) > 0 {
  100. // Cmd name must be lower cased.
  101. s := internal.ToLower(cmd.stringArg(0))
  102. cmd._args[0] = s
  103. return s
  104. }
  105. return ""
  106. }
  107. func (cmd *baseCmd) readTimeout() *time.Duration {
  108. return cmd._readTimeout
  109. }
  110. func (cmd *baseCmd) setReadTimeout(d time.Duration) {
  111. cmd._readTimeout = &d
  112. }
  113. func (cmd *baseCmd) setErr(e error) {
  114. cmd.err = e
  115. }
  116. //------------------------------------------------------------------------------
  117. type Cmd struct {
  118. baseCmd
  119. val interface{}
  120. }
  121. func NewCmd(args ...interface{}) *Cmd {
  122. return &Cmd{
  123. baseCmd: baseCmd{_args: args},
  124. }
  125. }
  126. func (cmd *Cmd) Val() interface{} {
  127. return cmd.val
  128. }
  129. func (cmd *Cmd) Result() (interface{}, error) {
  130. return cmd.val, cmd.err
  131. }
  132. func (cmd *Cmd) String() (string, error) {
  133. if cmd.err != nil {
  134. return "", cmd.err
  135. }
  136. switch val := cmd.val.(type) {
  137. case string:
  138. return val, nil
  139. default:
  140. err := fmt.Errorf("redis: unexpected type=%T for String", val)
  141. return "", err
  142. }
  143. }
  144. func (cmd *Cmd) Int() (int, error) {
  145. if cmd.err != nil {
  146. return 0, cmd.err
  147. }
  148. switch val := cmd.val.(type) {
  149. case int64:
  150. return int(val), nil
  151. case string:
  152. return strconv.Atoi(val)
  153. default:
  154. err := fmt.Errorf("redis: unexpected type=%T for Int", val)
  155. return 0, err
  156. }
  157. }
  158. func (cmd *Cmd) Int64() (int64, error) {
  159. if cmd.err != nil {
  160. return 0, cmd.err
  161. }
  162. switch val := cmd.val.(type) {
  163. case int64:
  164. return val, nil
  165. case string:
  166. return strconv.ParseInt(val, 10, 64)
  167. default:
  168. err := fmt.Errorf("redis: unexpected type=%T for Int64", val)
  169. return 0, err
  170. }
  171. }
  172. func (cmd *Cmd) Uint64() (uint64, error) {
  173. if cmd.err != nil {
  174. return 0, cmd.err
  175. }
  176. switch val := cmd.val.(type) {
  177. case int64:
  178. return uint64(val), nil
  179. case string:
  180. return strconv.ParseUint(val, 10, 64)
  181. default:
  182. err := fmt.Errorf("redis: unexpected type=%T for Uint64", val)
  183. return 0, err
  184. }
  185. }
  186. func (cmd *Cmd) Float64() (float64, error) {
  187. if cmd.err != nil {
  188. return 0, cmd.err
  189. }
  190. switch val := cmd.val.(type) {
  191. case int64:
  192. return float64(val), nil
  193. case string:
  194. return strconv.ParseFloat(val, 64)
  195. default:
  196. err := fmt.Errorf("redis: unexpected type=%T for Float64", val)
  197. return 0, err
  198. }
  199. }
  200. func (cmd *Cmd) Bool() (bool, error) {
  201. if cmd.err != nil {
  202. return false, cmd.err
  203. }
  204. switch val := cmd.val.(type) {
  205. case int64:
  206. return val != 0, nil
  207. case string:
  208. return strconv.ParseBool(val)
  209. default:
  210. err := fmt.Errorf("redis: unexpected type=%T for Bool", val)
  211. return false, err
  212. }
  213. }
  214. func (cmd *Cmd) readReply(rd *proto.Reader) error {
  215. cmd.val, cmd.err = rd.ReadReply(sliceParser)
  216. return cmd.err
  217. }
  218. // Implements proto.MultiBulkParse
  219. func sliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  220. vals := make([]interface{}, 0, n)
  221. for i := int64(0); i < n; i++ {
  222. v, err := rd.ReadReply(sliceParser)
  223. if err != nil {
  224. if err == Nil {
  225. vals = append(vals, nil)
  226. continue
  227. }
  228. if err, ok := err.(proto.RedisError); ok {
  229. vals = append(vals, err)
  230. continue
  231. }
  232. return nil, err
  233. }
  234. switch v := v.(type) {
  235. case string:
  236. vals = append(vals, v)
  237. default:
  238. vals = append(vals, v)
  239. }
  240. }
  241. return vals, nil
  242. }
  243. //------------------------------------------------------------------------------
  244. type SliceCmd struct {
  245. baseCmd
  246. val []interface{}
  247. }
  248. var _ Cmder = (*SliceCmd)(nil)
  249. func NewSliceCmd(args ...interface{}) *SliceCmd {
  250. return &SliceCmd{
  251. baseCmd: baseCmd{_args: args},
  252. }
  253. }
  254. func (cmd *SliceCmd) Val() []interface{} {
  255. return cmd.val
  256. }
  257. func (cmd *SliceCmd) Result() ([]interface{}, error) {
  258. return cmd.val, cmd.err
  259. }
  260. func (cmd *SliceCmd) String() string {
  261. return cmdString(cmd, cmd.val)
  262. }
  263. func (cmd *SliceCmd) readReply(rd *proto.Reader) error {
  264. var v interface{}
  265. v, cmd.err = rd.ReadArrayReply(sliceParser)
  266. if cmd.err != nil {
  267. return cmd.err
  268. }
  269. cmd.val = v.([]interface{})
  270. return nil
  271. }
  272. //------------------------------------------------------------------------------
  273. type StatusCmd struct {
  274. baseCmd
  275. val string
  276. }
  277. var _ Cmder = (*StatusCmd)(nil)
  278. func NewStatusCmd(args ...interface{}) *StatusCmd {
  279. return &StatusCmd{
  280. baseCmd: baseCmd{_args: args},
  281. }
  282. }
  283. func (cmd *StatusCmd) Val() string {
  284. return cmd.val
  285. }
  286. func (cmd *StatusCmd) Result() (string, error) {
  287. return cmd.val, cmd.err
  288. }
  289. func (cmd *StatusCmd) String() string {
  290. return cmdString(cmd, cmd.val)
  291. }
  292. func (cmd *StatusCmd) readReply(rd *proto.Reader) error {
  293. cmd.val, cmd.err = rd.ReadString()
  294. return cmd.err
  295. }
  296. //------------------------------------------------------------------------------
  297. type IntCmd struct {
  298. baseCmd
  299. val int64
  300. }
  301. var _ Cmder = (*IntCmd)(nil)
  302. func NewIntCmd(args ...interface{}) *IntCmd {
  303. return &IntCmd{
  304. baseCmd: baseCmd{_args: args},
  305. }
  306. }
  307. func (cmd *IntCmd) Val() int64 {
  308. return cmd.val
  309. }
  310. func (cmd *IntCmd) Result() (int64, error) {
  311. return cmd.val, cmd.err
  312. }
  313. func (cmd *IntCmd) String() string {
  314. return cmdString(cmd, cmd.val)
  315. }
  316. func (cmd *IntCmd) readReply(rd *proto.Reader) error {
  317. cmd.val, cmd.err = rd.ReadIntReply()
  318. return cmd.err
  319. }
  320. //------------------------------------------------------------------------------
  321. type DurationCmd struct {
  322. baseCmd
  323. val time.Duration
  324. precision time.Duration
  325. }
  326. var _ Cmder = (*DurationCmd)(nil)
  327. func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd {
  328. return &DurationCmd{
  329. baseCmd: baseCmd{_args: args},
  330. precision: precision,
  331. }
  332. }
  333. func (cmd *DurationCmd) Val() time.Duration {
  334. return cmd.val
  335. }
  336. func (cmd *DurationCmd) Result() (time.Duration, error) {
  337. return cmd.val, cmd.err
  338. }
  339. func (cmd *DurationCmd) String() string {
  340. return cmdString(cmd, cmd.val)
  341. }
  342. func (cmd *DurationCmd) readReply(rd *proto.Reader) error {
  343. var n int64
  344. n, cmd.err = rd.ReadIntReply()
  345. if cmd.err != nil {
  346. return cmd.err
  347. }
  348. cmd.val = time.Duration(n) * cmd.precision
  349. return nil
  350. }
  351. //------------------------------------------------------------------------------
  352. type TimeCmd struct {
  353. baseCmd
  354. val time.Time
  355. }
  356. var _ Cmder = (*TimeCmd)(nil)
  357. func NewTimeCmd(args ...interface{}) *TimeCmd {
  358. return &TimeCmd{
  359. baseCmd: baseCmd{_args: args},
  360. }
  361. }
  362. func (cmd *TimeCmd) Val() time.Time {
  363. return cmd.val
  364. }
  365. func (cmd *TimeCmd) Result() (time.Time, error) {
  366. return cmd.val, cmd.err
  367. }
  368. func (cmd *TimeCmd) String() string {
  369. return cmdString(cmd, cmd.val)
  370. }
  371. func (cmd *TimeCmd) readReply(rd *proto.Reader) error {
  372. var v interface{}
  373. v, cmd.err = rd.ReadArrayReply(timeParser)
  374. if cmd.err != nil {
  375. return cmd.err
  376. }
  377. cmd.val = v.(time.Time)
  378. return nil
  379. }
  380. // Implements proto.MultiBulkParse
  381. func timeParser(rd *proto.Reader, n int64) (interface{}, error) {
  382. if n != 2 {
  383. return nil, fmt.Errorf("got %d elements, expected 2", n)
  384. }
  385. sec, err := rd.ReadInt()
  386. if err != nil {
  387. return nil, err
  388. }
  389. microsec, err := rd.ReadInt()
  390. if err != nil {
  391. return nil, err
  392. }
  393. return time.Unix(sec, microsec*1000), nil
  394. }
  395. //------------------------------------------------------------------------------
  396. type BoolCmd struct {
  397. baseCmd
  398. val bool
  399. }
  400. var _ Cmder = (*BoolCmd)(nil)
  401. func NewBoolCmd(args ...interface{}) *BoolCmd {
  402. return &BoolCmd{
  403. baseCmd: baseCmd{_args: args},
  404. }
  405. }
  406. func (cmd *BoolCmd) Val() bool {
  407. return cmd.val
  408. }
  409. func (cmd *BoolCmd) Result() (bool, error) {
  410. return cmd.val, cmd.err
  411. }
  412. func (cmd *BoolCmd) String() string {
  413. return cmdString(cmd, cmd.val)
  414. }
  415. func (cmd *BoolCmd) readReply(rd *proto.Reader) error {
  416. var v interface{}
  417. v, cmd.err = rd.ReadReply(nil)
  418. // `SET key value NX` returns nil when key already exists. But
  419. // `SETNX key value` returns bool (0/1). So convert nil to bool.
  420. // TODO: is this okay?
  421. if cmd.err == Nil {
  422. cmd.val = false
  423. cmd.err = nil
  424. return nil
  425. }
  426. if cmd.err != nil {
  427. return cmd.err
  428. }
  429. switch v := v.(type) {
  430. case int64:
  431. cmd.val = v == 1
  432. return nil
  433. case string:
  434. cmd.val = v == "OK"
  435. return nil
  436. default:
  437. cmd.err = fmt.Errorf("got %T, wanted int64 or string", v)
  438. return cmd.err
  439. }
  440. }
  441. //------------------------------------------------------------------------------
  442. type StringCmd struct {
  443. baseCmd
  444. val string
  445. }
  446. var _ Cmder = (*StringCmd)(nil)
  447. func NewStringCmd(args ...interface{}) *StringCmd {
  448. return &StringCmd{
  449. baseCmd: baseCmd{_args: args},
  450. }
  451. }
  452. func (cmd *StringCmd) Val() string {
  453. return cmd.val
  454. }
  455. func (cmd *StringCmd) Result() (string, error) {
  456. return cmd.Val(), cmd.err
  457. }
  458. func (cmd *StringCmd) Bytes() ([]byte, error) {
  459. return []byte(cmd.val), cmd.err
  460. }
  461. func (cmd *StringCmd) Int() (int, error) {
  462. if cmd.err != nil {
  463. return 0, cmd.err
  464. }
  465. return strconv.Atoi(cmd.Val())
  466. }
  467. func (cmd *StringCmd) Int64() (int64, error) {
  468. if cmd.err != nil {
  469. return 0, cmd.err
  470. }
  471. return strconv.ParseInt(cmd.Val(), 10, 64)
  472. }
  473. func (cmd *StringCmd) Uint64() (uint64, error) {
  474. if cmd.err != nil {
  475. return 0, cmd.err
  476. }
  477. return strconv.ParseUint(cmd.Val(), 10, 64)
  478. }
  479. func (cmd *StringCmd) Float64() (float64, error) {
  480. if cmd.err != nil {
  481. return 0, cmd.err
  482. }
  483. return strconv.ParseFloat(cmd.Val(), 64)
  484. }
  485. func (cmd *StringCmd) Scan(val interface{}) error {
  486. if cmd.err != nil {
  487. return cmd.err
  488. }
  489. return proto.Scan([]byte(cmd.val), val)
  490. }
  491. func (cmd *StringCmd) String() string {
  492. return cmdString(cmd, cmd.val)
  493. }
  494. func (cmd *StringCmd) readReply(rd *proto.Reader) error {
  495. cmd.val, cmd.err = rd.ReadString()
  496. return cmd.err
  497. }
  498. //------------------------------------------------------------------------------
  499. type FloatCmd struct {
  500. baseCmd
  501. val float64
  502. }
  503. var _ Cmder = (*FloatCmd)(nil)
  504. func NewFloatCmd(args ...interface{}) *FloatCmd {
  505. return &FloatCmd{
  506. baseCmd: baseCmd{_args: args},
  507. }
  508. }
  509. func (cmd *FloatCmd) Val() float64 {
  510. return cmd.val
  511. }
  512. func (cmd *FloatCmd) Result() (float64, error) {
  513. return cmd.Val(), cmd.Err()
  514. }
  515. func (cmd *FloatCmd) String() string {
  516. return cmdString(cmd, cmd.val)
  517. }
  518. func (cmd *FloatCmd) readReply(rd *proto.Reader) error {
  519. cmd.val, cmd.err = rd.ReadFloatReply()
  520. return cmd.err
  521. }
  522. //------------------------------------------------------------------------------
  523. type StringSliceCmd struct {
  524. baseCmd
  525. val []string
  526. }
  527. var _ Cmder = (*StringSliceCmd)(nil)
  528. func NewStringSliceCmd(args ...interface{}) *StringSliceCmd {
  529. return &StringSliceCmd{
  530. baseCmd: baseCmd{_args: args},
  531. }
  532. }
  533. func (cmd *StringSliceCmd) Val() []string {
  534. return cmd.val
  535. }
  536. func (cmd *StringSliceCmd) Result() ([]string, error) {
  537. return cmd.Val(), cmd.Err()
  538. }
  539. func (cmd *StringSliceCmd) String() string {
  540. return cmdString(cmd, cmd.val)
  541. }
  542. func (cmd *StringSliceCmd) ScanSlice(container interface{}) error {
  543. return proto.ScanSlice(cmd.Val(), container)
  544. }
  545. func (cmd *StringSliceCmd) readReply(rd *proto.Reader) error {
  546. var v interface{}
  547. v, cmd.err = rd.ReadArrayReply(stringSliceParser)
  548. if cmd.err != nil {
  549. return cmd.err
  550. }
  551. cmd.val = v.([]string)
  552. return nil
  553. }
  554. // Implements proto.MultiBulkParse
  555. func stringSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  556. ss := make([]string, 0, n)
  557. for i := int64(0); i < n; i++ {
  558. s, err := rd.ReadString()
  559. if err == Nil {
  560. ss = append(ss, "")
  561. } else if err != nil {
  562. return nil, err
  563. } else {
  564. ss = append(ss, s)
  565. }
  566. }
  567. return ss, nil
  568. }
  569. //------------------------------------------------------------------------------
  570. type BoolSliceCmd struct {
  571. baseCmd
  572. val []bool
  573. }
  574. var _ Cmder = (*BoolSliceCmd)(nil)
  575. func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd {
  576. return &BoolSliceCmd{
  577. baseCmd: baseCmd{_args: args},
  578. }
  579. }
  580. func (cmd *BoolSliceCmd) Val() []bool {
  581. return cmd.val
  582. }
  583. func (cmd *BoolSliceCmd) Result() ([]bool, error) {
  584. return cmd.val, cmd.err
  585. }
  586. func (cmd *BoolSliceCmd) String() string {
  587. return cmdString(cmd, cmd.val)
  588. }
  589. func (cmd *BoolSliceCmd) readReply(rd *proto.Reader) error {
  590. var v interface{}
  591. v, cmd.err = rd.ReadArrayReply(boolSliceParser)
  592. if cmd.err != nil {
  593. return cmd.err
  594. }
  595. cmd.val = v.([]bool)
  596. return nil
  597. }
  598. // Implements proto.MultiBulkParse
  599. func boolSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  600. bools := make([]bool, 0, n)
  601. for i := int64(0); i < n; i++ {
  602. n, err := rd.ReadIntReply()
  603. if err != nil {
  604. return nil, err
  605. }
  606. bools = append(bools, n == 1)
  607. }
  608. return bools, nil
  609. }
  610. //------------------------------------------------------------------------------
  611. type StringStringMapCmd struct {
  612. baseCmd
  613. val map[string]string
  614. }
  615. var _ Cmder = (*StringStringMapCmd)(nil)
  616. func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd {
  617. return &StringStringMapCmd{
  618. baseCmd: baseCmd{_args: args},
  619. }
  620. }
  621. func (cmd *StringStringMapCmd) Val() map[string]string {
  622. return cmd.val
  623. }
  624. func (cmd *StringStringMapCmd) Result() (map[string]string, error) {
  625. return cmd.val, cmd.err
  626. }
  627. func (cmd *StringStringMapCmd) String() string {
  628. return cmdString(cmd, cmd.val)
  629. }
  630. func (cmd *StringStringMapCmd) readReply(rd *proto.Reader) error {
  631. var v interface{}
  632. v, cmd.err = rd.ReadArrayReply(stringStringMapParser)
  633. if cmd.err != nil {
  634. return cmd.err
  635. }
  636. cmd.val = v.(map[string]string)
  637. return nil
  638. }
  639. // Implements proto.MultiBulkParse
  640. func stringStringMapParser(rd *proto.Reader, n int64) (interface{}, error) {
  641. m := make(map[string]string, n/2)
  642. for i := int64(0); i < n; i += 2 {
  643. key, err := rd.ReadString()
  644. if err != nil {
  645. return nil, err
  646. }
  647. value, err := rd.ReadString()
  648. if err != nil {
  649. return nil, err
  650. }
  651. m[key] = value
  652. }
  653. return m, nil
  654. }
  655. //------------------------------------------------------------------------------
  656. type StringIntMapCmd struct {
  657. baseCmd
  658. val map[string]int64
  659. }
  660. var _ Cmder = (*StringIntMapCmd)(nil)
  661. func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd {
  662. return &StringIntMapCmd{
  663. baseCmd: baseCmd{_args: args},
  664. }
  665. }
  666. func (cmd *StringIntMapCmd) Val() map[string]int64 {
  667. return cmd.val
  668. }
  669. func (cmd *StringIntMapCmd) Result() (map[string]int64, error) {
  670. return cmd.val, cmd.err
  671. }
  672. func (cmd *StringIntMapCmd) String() string {
  673. return cmdString(cmd, cmd.val)
  674. }
  675. func (cmd *StringIntMapCmd) readReply(rd *proto.Reader) error {
  676. var v interface{}
  677. v, cmd.err = rd.ReadArrayReply(stringIntMapParser)
  678. if cmd.err != nil {
  679. return cmd.err
  680. }
  681. cmd.val = v.(map[string]int64)
  682. return nil
  683. }
  684. // Implements proto.MultiBulkParse
  685. func stringIntMapParser(rd *proto.Reader, n int64) (interface{}, error) {
  686. m := make(map[string]int64, n/2)
  687. for i := int64(0); i < n; i += 2 {
  688. key, err := rd.ReadString()
  689. if err != nil {
  690. return nil, err
  691. }
  692. n, err := rd.ReadIntReply()
  693. if err != nil {
  694. return nil, err
  695. }
  696. m[key] = n
  697. }
  698. return m, nil
  699. }
  700. //------------------------------------------------------------------------------
  701. type StringStructMapCmd struct {
  702. baseCmd
  703. val map[string]struct{}
  704. }
  705. var _ Cmder = (*StringStructMapCmd)(nil)
  706. func NewStringStructMapCmd(args ...interface{}) *StringStructMapCmd {
  707. return &StringStructMapCmd{
  708. baseCmd: baseCmd{_args: args},
  709. }
  710. }
  711. func (cmd *StringStructMapCmd) Val() map[string]struct{} {
  712. return cmd.val
  713. }
  714. func (cmd *StringStructMapCmd) Result() (map[string]struct{}, error) {
  715. return cmd.val, cmd.err
  716. }
  717. func (cmd *StringStructMapCmd) String() string {
  718. return cmdString(cmd, cmd.val)
  719. }
  720. func (cmd *StringStructMapCmd) readReply(rd *proto.Reader) error {
  721. var v interface{}
  722. v, cmd.err = rd.ReadArrayReply(stringStructMapParser)
  723. if cmd.err != nil {
  724. return cmd.err
  725. }
  726. cmd.val = v.(map[string]struct{})
  727. return nil
  728. }
  729. // Implements proto.MultiBulkParse
  730. func stringStructMapParser(rd *proto.Reader, n int64) (interface{}, error) {
  731. m := make(map[string]struct{}, n)
  732. for i := int64(0); i < n; i++ {
  733. key, err := rd.ReadString()
  734. if err != nil {
  735. return nil, err
  736. }
  737. m[key] = struct{}{}
  738. }
  739. return m, nil
  740. }
  741. //------------------------------------------------------------------------------
  742. type XMessage struct {
  743. ID string
  744. Values map[string]interface{}
  745. }
  746. type XMessageSliceCmd struct {
  747. baseCmd
  748. val []XMessage
  749. }
  750. var _ Cmder = (*XMessageSliceCmd)(nil)
  751. func NewXMessageSliceCmd(args ...interface{}) *XMessageSliceCmd {
  752. return &XMessageSliceCmd{
  753. baseCmd: baseCmd{_args: args},
  754. }
  755. }
  756. func (cmd *XMessageSliceCmd) Val() []XMessage {
  757. return cmd.val
  758. }
  759. func (cmd *XMessageSliceCmd) Result() ([]XMessage, error) {
  760. return cmd.val, cmd.err
  761. }
  762. func (cmd *XMessageSliceCmd) String() string {
  763. return cmdString(cmd, cmd.val)
  764. }
  765. func (cmd *XMessageSliceCmd) readReply(rd *proto.Reader) error {
  766. var v interface{}
  767. v, cmd.err = rd.ReadArrayReply(xMessageSliceParser)
  768. if cmd.err != nil {
  769. return cmd.err
  770. }
  771. cmd.val = v.([]XMessage)
  772. return nil
  773. }
  774. // Implements proto.MultiBulkParse
  775. func xMessageSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  776. msgs := make([]XMessage, 0, n)
  777. for i := int64(0); i < n; i++ {
  778. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  779. id, err := rd.ReadString()
  780. if err != nil {
  781. return nil, err
  782. }
  783. v, err := rd.ReadArrayReply(stringInterfaceMapParser)
  784. if err != nil {
  785. return nil, err
  786. }
  787. msgs = append(msgs, XMessage{
  788. ID: id,
  789. Values: v.(map[string]interface{}),
  790. })
  791. return nil, nil
  792. })
  793. if err != nil {
  794. return nil, err
  795. }
  796. }
  797. return msgs, nil
  798. }
  799. // Implements proto.MultiBulkParse
  800. func stringInterfaceMapParser(rd *proto.Reader, n int64) (interface{}, error) {
  801. m := make(map[string]interface{}, n/2)
  802. for i := int64(0); i < n; i += 2 {
  803. key, err := rd.ReadString()
  804. if err != nil {
  805. return nil, err
  806. }
  807. value, err := rd.ReadString()
  808. if err != nil {
  809. return nil, err
  810. }
  811. m[key] = value
  812. }
  813. return m, nil
  814. }
  815. //------------------------------------------------------------------------------
  816. type XStream struct {
  817. Stream string
  818. Messages []XMessage
  819. }
  820. type XStreamSliceCmd struct {
  821. baseCmd
  822. val []XStream
  823. }
  824. var _ Cmder = (*XStreamSliceCmd)(nil)
  825. func NewXStreamSliceCmd(args ...interface{}) *XStreamSliceCmd {
  826. return &XStreamSliceCmd{
  827. baseCmd: baseCmd{_args: args},
  828. }
  829. }
  830. func (cmd *XStreamSliceCmd) Val() []XStream {
  831. return cmd.val
  832. }
  833. func (cmd *XStreamSliceCmd) Result() ([]XStream, error) {
  834. return cmd.val, cmd.err
  835. }
  836. func (cmd *XStreamSliceCmd) String() string {
  837. return cmdString(cmd, cmd.val)
  838. }
  839. func (cmd *XStreamSliceCmd) readReply(rd *proto.Reader) error {
  840. var v interface{}
  841. v, cmd.err = rd.ReadArrayReply(xStreamSliceParser)
  842. if cmd.err != nil {
  843. return cmd.err
  844. }
  845. cmd.val = v.([]XStream)
  846. return nil
  847. }
  848. // Implements proto.MultiBulkParse
  849. func xStreamSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  850. ret := make([]XStream, 0, n)
  851. for i := int64(0); i < n; i++ {
  852. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  853. if n != 2 {
  854. return nil, fmt.Errorf("got %d, wanted 2", n)
  855. }
  856. stream, err := rd.ReadString()
  857. if err != nil {
  858. return nil, err
  859. }
  860. v, err := rd.ReadArrayReply(xMessageSliceParser)
  861. if err != nil {
  862. return nil, err
  863. }
  864. ret = append(ret, XStream{
  865. Stream: stream,
  866. Messages: v.([]XMessage),
  867. })
  868. return nil, nil
  869. })
  870. if err != nil {
  871. return nil, err
  872. }
  873. }
  874. return ret, nil
  875. }
  876. //------------------------------------------------------------------------------
  877. type XPending struct {
  878. Count int64
  879. Lower string
  880. Higher string
  881. Consumers map[string]int64
  882. }
  883. type XPendingCmd struct {
  884. baseCmd
  885. val *XPending
  886. }
  887. var _ Cmder = (*XPendingCmd)(nil)
  888. func NewXPendingCmd(args ...interface{}) *XPendingCmd {
  889. return &XPendingCmd{
  890. baseCmd: baseCmd{_args: args},
  891. }
  892. }
  893. func (cmd *XPendingCmd) Val() *XPending {
  894. return cmd.val
  895. }
  896. func (cmd *XPendingCmd) Result() (*XPending, error) {
  897. return cmd.val, cmd.err
  898. }
  899. func (cmd *XPendingCmd) String() string {
  900. return cmdString(cmd, cmd.val)
  901. }
  902. func (cmd *XPendingCmd) readReply(rd *proto.Reader) error {
  903. var info interface{}
  904. info, cmd.err = rd.ReadArrayReply(xPendingParser)
  905. if cmd.err != nil {
  906. return cmd.err
  907. }
  908. cmd.val = info.(*XPending)
  909. return nil
  910. }
  911. func xPendingParser(rd *proto.Reader, n int64) (interface{}, error) {
  912. if n != 4 {
  913. return nil, fmt.Errorf("got %d, wanted 4", n)
  914. }
  915. count, err := rd.ReadIntReply()
  916. if err != nil {
  917. return nil, err
  918. }
  919. lower, err := rd.ReadString()
  920. if err != nil && err != Nil {
  921. return nil, err
  922. }
  923. higher, err := rd.ReadString()
  924. if err != nil && err != Nil {
  925. return nil, err
  926. }
  927. pending := &XPending{
  928. Count: count,
  929. Lower: lower,
  930. Higher: higher,
  931. }
  932. _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  933. for i := int64(0); i < n; i++ {
  934. _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  935. if n != 2 {
  936. return nil, fmt.Errorf("got %d, wanted 2", n)
  937. }
  938. consumerName, err := rd.ReadString()
  939. if err != nil {
  940. return nil, err
  941. }
  942. consumerPending, err := rd.ReadInt()
  943. if err != nil {
  944. return nil, err
  945. }
  946. if pending.Consumers == nil {
  947. pending.Consumers = make(map[string]int64)
  948. }
  949. pending.Consumers[consumerName] = consumerPending
  950. return nil, nil
  951. })
  952. if err != nil {
  953. return nil, err
  954. }
  955. }
  956. return nil, nil
  957. })
  958. if err != nil && err != Nil {
  959. return nil, err
  960. }
  961. return pending, nil
  962. }
  963. //------------------------------------------------------------------------------
  964. type XPendingExt struct {
  965. Id string
  966. Consumer string
  967. Idle time.Duration
  968. RetryCount int64
  969. }
  970. type XPendingExtCmd struct {
  971. baseCmd
  972. val []XPendingExt
  973. }
  974. var _ Cmder = (*XPendingExtCmd)(nil)
  975. func NewXPendingExtCmd(args ...interface{}) *XPendingExtCmd {
  976. return &XPendingExtCmd{
  977. baseCmd: baseCmd{_args: args},
  978. }
  979. }
  980. func (cmd *XPendingExtCmd) Val() []XPendingExt {
  981. return cmd.val
  982. }
  983. func (cmd *XPendingExtCmd) Result() ([]XPendingExt, error) {
  984. return cmd.val, cmd.err
  985. }
  986. func (cmd *XPendingExtCmd) String() string {
  987. return cmdString(cmd, cmd.val)
  988. }
  989. func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error {
  990. var info interface{}
  991. info, cmd.err = rd.ReadArrayReply(xPendingExtSliceParser)
  992. if cmd.err != nil {
  993. return cmd.err
  994. }
  995. cmd.val = info.([]XPendingExt)
  996. return nil
  997. }
  998. func xPendingExtSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  999. ret := make([]XPendingExt, 0, n)
  1000. for i := int64(0); i < n; i++ {
  1001. _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
  1002. if n != 4 {
  1003. return nil, fmt.Errorf("got %d, wanted 4", n)
  1004. }
  1005. id, err := rd.ReadString()
  1006. if err != nil {
  1007. return nil, err
  1008. }
  1009. consumer, err := rd.ReadString()
  1010. if err != nil && err != Nil {
  1011. return nil, err
  1012. }
  1013. idle, err := rd.ReadIntReply()
  1014. if err != nil && err != Nil {
  1015. return nil, err
  1016. }
  1017. retryCount, err := rd.ReadIntReply()
  1018. if err != nil && err != Nil {
  1019. return nil, err
  1020. }
  1021. ret = append(ret, XPendingExt{
  1022. Id: id,
  1023. Consumer: consumer,
  1024. Idle: time.Duration(idle) * time.Millisecond,
  1025. RetryCount: retryCount,
  1026. })
  1027. return nil, nil
  1028. })
  1029. if err != nil {
  1030. return nil, err
  1031. }
  1032. }
  1033. return ret, nil
  1034. }
  1035. //------------------------------------------------------------------------------
  1036. //------------------------------------------------------------------------------
  1037. type ZSliceCmd struct {
  1038. baseCmd
  1039. val []Z
  1040. }
  1041. var _ Cmder = (*ZSliceCmd)(nil)
  1042. func NewZSliceCmd(args ...interface{}) *ZSliceCmd {
  1043. return &ZSliceCmd{
  1044. baseCmd: baseCmd{_args: args},
  1045. }
  1046. }
  1047. func (cmd *ZSliceCmd) Val() []Z {
  1048. return cmd.val
  1049. }
  1050. func (cmd *ZSliceCmd) Result() ([]Z, error) {
  1051. return cmd.val, cmd.err
  1052. }
  1053. func (cmd *ZSliceCmd) String() string {
  1054. return cmdString(cmd, cmd.val)
  1055. }
  1056. func (cmd *ZSliceCmd) readReply(rd *proto.Reader) error {
  1057. var v interface{}
  1058. v, cmd.err = rd.ReadArrayReply(zSliceParser)
  1059. if cmd.err != nil {
  1060. return cmd.err
  1061. }
  1062. cmd.val = v.([]Z)
  1063. return nil
  1064. }
  1065. // Implements proto.MultiBulkParse
  1066. func zSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  1067. zz := make([]Z, n/2)
  1068. for i := int64(0); i < n; i += 2 {
  1069. var err error
  1070. z := &zz[i/2]
  1071. z.Member, err = rd.ReadString()
  1072. if err != nil {
  1073. return nil, err
  1074. }
  1075. z.Score, err = rd.ReadFloatReply()
  1076. if err != nil {
  1077. return nil, err
  1078. }
  1079. }
  1080. return zz, nil
  1081. }
  1082. //------------------------------------------------------------------------------
  1083. type ZWithKeyCmd struct {
  1084. baseCmd
  1085. val ZWithKey
  1086. }
  1087. var _ Cmder = (*ZWithKeyCmd)(nil)
  1088. func NewZWithKeyCmd(args ...interface{}) *ZWithKeyCmd {
  1089. return &ZWithKeyCmd{
  1090. baseCmd: baseCmd{_args: args},
  1091. }
  1092. }
  1093. func (cmd *ZWithKeyCmd) Val() ZWithKey {
  1094. return cmd.val
  1095. }
  1096. func (cmd *ZWithKeyCmd) Result() (ZWithKey, error) {
  1097. return cmd.Val(), cmd.Err()
  1098. }
  1099. func (cmd *ZWithKeyCmd) String() string {
  1100. return cmdString(cmd, cmd.val)
  1101. }
  1102. func (cmd *ZWithKeyCmd) readReply(rd *proto.Reader) error {
  1103. var v interface{}
  1104. v, cmd.err = rd.ReadArrayReply(zWithKeyParser)
  1105. if cmd.err != nil {
  1106. return cmd.err
  1107. }
  1108. cmd.val = v.(ZWithKey)
  1109. return nil
  1110. }
  1111. // Implements proto.MultiBulkParse
  1112. func zWithKeyParser(rd *proto.Reader, n int64) (interface{}, error) {
  1113. if n != 3 {
  1114. return nil, fmt.Errorf("got %d elements, expected 3", n)
  1115. }
  1116. var z ZWithKey
  1117. var err error
  1118. z.Key, err = rd.ReadString()
  1119. if err != nil {
  1120. return nil, err
  1121. }
  1122. z.Member, err = rd.ReadString()
  1123. if err != nil {
  1124. return nil, err
  1125. }
  1126. z.Score, err = rd.ReadFloatReply()
  1127. if err != nil {
  1128. return nil, err
  1129. }
  1130. return z, nil
  1131. }
  1132. //------------------------------------------------------------------------------
  1133. type ScanCmd struct {
  1134. baseCmd
  1135. page []string
  1136. cursor uint64
  1137. process func(cmd Cmder) error
  1138. }
  1139. var _ Cmder = (*ScanCmd)(nil)
  1140. func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
  1141. return &ScanCmd{
  1142. baseCmd: baseCmd{_args: args},
  1143. process: process,
  1144. }
  1145. }
  1146. func (cmd *ScanCmd) Val() (keys []string, cursor uint64) {
  1147. return cmd.page, cmd.cursor
  1148. }
  1149. func (cmd *ScanCmd) Result() (keys []string, cursor uint64, err error) {
  1150. return cmd.page, cmd.cursor, cmd.err
  1151. }
  1152. func (cmd *ScanCmd) String() string {
  1153. return cmdString(cmd, cmd.page)
  1154. }
  1155. func (cmd *ScanCmd) readReply(rd *proto.Reader) error {
  1156. cmd.page, cmd.cursor, cmd.err = rd.ReadScanReply()
  1157. return cmd.err
  1158. }
  1159. // Iterator creates a new ScanIterator.
  1160. func (cmd *ScanCmd) Iterator() *ScanIterator {
  1161. return &ScanIterator{
  1162. cmd: cmd,
  1163. }
  1164. }
  1165. //------------------------------------------------------------------------------
  1166. type ClusterNode struct {
  1167. Id string
  1168. Addr string
  1169. }
  1170. type ClusterSlot struct {
  1171. Start int
  1172. End int
  1173. Nodes []ClusterNode
  1174. }
  1175. type ClusterSlotsCmd struct {
  1176. baseCmd
  1177. val []ClusterSlot
  1178. }
  1179. var _ Cmder = (*ClusterSlotsCmd)(nil)
  1180. func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd {
  1181. return &ClusterSlotsCmd{
  1182. baseCmd: baseCmd{_args: args},
  1183. }
  1184. }
  1185. func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
  1186. return cmd.val
  1187. }
  1188. func (cmd *ClusterSlotsCmd) Result() ([]ClusterSlot, error) {
  1189. return cmd.Val(), cmd.Err()
  1190. }
  1191. func (cmd *ClusterSlotsCmd) String() string {
  1192. return cmdString(cmd, cmd.val)
  1193. }
  1194. func (cmd *ClusterSlotsCmd) readReply(rd *proto.Reader) error {
  1195. var v interface{}
  1196. v, cmd.err = rd.ReadArrayReply(clusterSlotsParser)
  1197. if cmd.err != nil {
  1198. return cmd.err
  1199. }
  1200. cmd.val = v.([]ClusterSlot)
  1201. return nil
  1202. }
  1203. // Implements proto.MultiBulkParse
  1204. func clusterSlotsParser(rd *proto.Reader, n int64) (interface{}, error) {
  1205. slots := make([]ClusterSlot, n)
  1206. for i := 0; i < len(slots); i++ {
  1207. n, err := rd.ReadArrayLen()
  1208. if err != nil {
  1209. return nil, err
  1210. }
  1211. if n < 2 {
  1212. err := fmt.Errorf("redis: got %d elements in cluster info, expected at least 2", n)
  1213. return nil, err
  1214. }
  1215. start, err := rd.ReadIntReply()
  1216. if err != nil {
  1217. return nil, err
  1218. }
  1219. end, err := rd.ReadIntReply()
  1220. if err != nil {
  1221. return nil, err
  1222. }
  1223. nodes := make([]ClusterNode, n-2)
  1224. for j := 0; j < len(nodes); j++ {
  1225. n, err := rd.ReadArrayLen()
  1226. if err != nil {
  1227. return nil, err
  1228. }
  1229. if n != 2 && n != 3 {
  1230. err := fmt.Errorf("got %d elements in cluster info address, expected 2 or 3", n)
  1231. return nil, err
  1232. }
  1233. ip, err := rd.ReadString()
  1234. if err != nil {
  1235. return nil, err
  1236. }
  1237. port, err := rd.ReadString()
  1238. if err != nil {
  1239. return nil, err
  1240. }
  1241. nodes[j].Addr = net.JoinHostPort(ip, port)
  1242. if n == 3 {
  1243. id, err := rd.ReadString()
  1244. if err != nil {
  1245. return nil, err
  1246. }
  1247. nodes[j].Id = id
  1248. }
  1249. }
  1250. slots[i] = ClusterSlot{
  1251. Start: int(start),
  1252. End: int(end),
  1253. Nodes: nodes,
  1254. }
  1255. }
  1256. return slots, nil
  1257. }
  1258. //------------------------------------------------------------------------------
  1259. // GeoLocation is used with GeoAdd to add geospatial location.
  1260. type GeoLocation struct {
  1261. Name string
  1262. Longitude, Latitude, Dist float64
  1263. GeoHash int64
  1264. }
  1265. // GeoRadiusQuery is used with GeoRadius to query geospatial index.
  1266. type GeoRadiusQuery struct {
  1267. Radius float64
  1268. // Can be m, km, ft, or mi. Default is km.
  1269. Unit string
  1270. WithCoord bool
  1271. WithDist bool
  1272. WithGeoHash bool
  1273. Count int
  1274. // Can be ASC or DESC. Default is no sort order.
  1275. Sort string
  1276. Store string
  1277. StoreDist string
  1278. }
  1279. type GeoLocationCmd struct {
  1280. baseCmd
  1281. q *GeoRadiusQuery
  1282. locations []GeoLocation
  1283. }
  1284. var _ Cmder = (*GeoLocationCmd)(nil)
  1285. func NewGeoLocationCmd(q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
  1286. args = append(args, q.Radius)
  1287. if q.Unit != "" {
  1288. args = append(args, q.Unit)
  1289. } else {
  1290. args = append(args, "km")
  1291. }
  1292. if q.WithCoord {
  1293. args = append(args, "withcoord")
  1294. }
  1295. if q.WithDist {
  1296. args = append(args, "withdist")
  1297. }
  1298. if q.WithGeoHash {
  1299. args = append(args, "withhash")
  1300. }
  1301. if q.Count > 0 {
  1302. args = append(args, "count", q.Count)
  1303. }
  1304. if q.Sort != "" {
  1305. args = append(args, q.Sort)
  1306. }
  1307. if q.Store != "" {
  1308. args = append(args, "store")
  1309. args = append(args, q.Store)
  1310. }
  1311. if q.StoreDist != "" {
  1312. args = append(args, "storedist")
  1313. args = append(args, q.StoreDist)
  1314. }
  1315. return &GeoLocationCmd{
  1316. baseCmd: baseCmd{_args: args},
  1317. q: q,
  1318. }
  1319. }
  1320. func (cmd *GeoLocationCmd) Val() []GeoLocation {
  1321. return cmd.locations
  1322. }
  1323. func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) {
  1324. return cmd.locations, cmd.err
  1325. }
  1326. func (cmd *GeoLocationCmd) String() string {
  1327. return cmdString(cmd, cmd.locations)
  1328. }
  1329. func (cmd *GeoLocationCmd) readReply(rd *proto.Reader) error {
  1330. var v interface{}
  1331. v, cmd.err = rd.ReadArrayReply(newGeoLocationSliceParser(cmd.q))
  1332. if cmd.err != nil {
  1333. return cmd.err
  1334. }
  1335. cmd.locations = v.([]GeoLocation)
  1336. return nil
  1337. }
  1338. func newGeoLocationParser(q *GeoRadiusQuery) proto.MultiBulkParse {
  1339. return func(rd *proto.Reader, n int64) (interface{}, error) {
  1340. var loc GeoLocation
  1341. var err error
  1342. loc.Name, err = rd.ReadString()
  1343. if err != nil {
  1344. return nil, err
  1345. }
  1346. if q.WithDist {
  1347. loc.Dist, err = rd.ReadFloatReply()
  1348. if err != nil {
  1349. return nil, err
  1350. }
  1351. }
  1352. if q.WithGeoHash {
  1353. loc.GeoHash, err = rd.ReadIntReply()
  1354. if err != nil {
  1355. return nil, err
  1356. }
  1357. }
  1358. if q.WithCoord {
  1359. n, err := rd.ReadArrayLen()
  1360. if err != nil {
  1361. return nil, err
  1362. }
  1363. if n != 2 {
  1364. return nil, fmt.Errorf("got %d coordinates, expected 2", n)
  1365. }
  1366. loc.Longitude, err = rd.ReadFloatReply()
  1367. if err != nil {
  1368. return nil, err
  1369. }
  1370. loc.Latitude, err = rd.ReadFloatReply()
  1371. if err != nil {
  1372. return nil, err
  1373. }
  1374. }
  1375. return &loc, nil
  1376. }
  1377. }
  1378. func newGeoLocationSliceParser(q *GeoRadiusQuery) proto.MultiBulkParse {
  1379. return func(rd *proto.Reader, n int64) (interface{}, error) {
  1380. locs := make([]GeoLocation, 0, n)
  1381. for i := int64(0); i < n; i++ {
  1382. v, err := rd.ReadReply(newGeoLocationParser(q))
  1383. if err != nil {
  1384. return nil, err
  1385. }
  1386. switch vv := v.(type) {
  1387. case string:
  1388. locs = append(locs, GeoLocation{
  1389. Name: vv,
  1390. })
  1391. case *GeoLocation:
  1392. locs = append(locs, *vv)
  1393. default:
  1394. return nil, fmt.Errorf("got %T, expected string or *GeoLocation", v)
  1395. }
  1396. }
  1397. return locs, nil
  1398. }
  1399. }
  1400. //------------------------------------------------------------------------------
  1401. type GeoPos struct {
  1402. Longitude, Latitude float64
  1403. }
  1404. type GeoPosCmd struct {
  1405. baseCmd
  1406. positions []*GeoPos
  1407. }
  1408. var _ Cmder = (*GeoPosCmd)(nil)
  1409. func NewGeoPosCmd(args ...interface{}) *GeoPosCmd {
  1410. return &GeoPosCmd{
  1411. baseCmd: baseCmd{_args: args},
  1412. }
  1413. }
  1414. func (cmd *GeoPosCmd) Val() []*GeoPos {
  1415. return cmd.positions
  1416. }
  1417. func (cmd *GeoPosCmd) Result() ([]*GeoPos, error) {
  1418. return cmd.Val(), cmd.Err()
  1419. }
  1420. func (cmd *GeoPosCmd) String() string {
  1421. return cmdString(cmd, cmd.positions)
  1422. }
  1423. func (cmd *GeoPosCmd) readReply(rd *proto.Reader) error {
  1424. var v interface{}
  1425. v, cmd.err = rd.ReadArrayReply(geoPosSliceParser)
  1426. if cmd.err != nil {
  1427. return cmd.err
  1428. }
  1429. cmd.positions = v.([]*GeoPos)
  1430. return nil
  1431. }
  1432. func geoPosSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  1433. positions := make([]*GeoPos, 0, n)
  1434. for i := int64(0); i < n; i++ {
  1435. v, err := rd.ReadReply(geoPosParser)
  1436. if err != nil {
  1437. if err == Nil {
  1438. positions = append(positions, nil)
  1439. continue
  1440. }
  1441. return nil, err
  1442. }
  1443. switch v := v.(type) {
  1444. case *GeoPos:
  1445. positions = append(positions, v)
  1446. default:
  1447. return nil, fmt.Errorf("got %T, expected *GeoPos", v)
  1448. }
  1449. }
  1450. return positions, nil
  1451. }
  1452. func geoPosParser(rd *proto.Reader, n int64) (interface{}, error) {
  1453. var pos GeoPos
  1454. var err error
  1455. pos.Longitude, err = rd.ReadFloatReply()
  1456. if err != nil {
  1457. return nil, err
  1458. }
  1459. pos.Latitude, err = rd.ReadFloatReply()
  1460. if err != nil {
  1461. return nil, err
  1462. }
  1463. return &pos, nil
  1464. }
  1465. //------------------------------------------------------------------------------
  1466. type CommandInfo struct {
  1467. Name string
  1468. Arity int8
  1469. Flags []string
  1470. FirstKeyPos int8
  1471. LastKeyPos int8
  1472. StepCount int8
  1473. ReadOnly bool
  1474. }
  1475. type CommandsInfoCmd struct {
  1476. baseCmd
  1477. val map[string]*CommandInfo
  1478. }
  1479. var _ Cmder = (*CommandsInfoCmd)(nil)
  1480. func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd {
  1481. return &CommandsInfoCmd{
  1482. baseCmd: baseCmd{_args: args},
  1483. }
  1484. }
  1485. func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
  1486. return cmd.val
  1487. }
  1488. func (cmd *CommandsInfoCmd) Result() (map[string]*CommandInfo, error) {
  1489. return cmd.Val(), cmd.Err()
  1490. }
  1491. func (cmd *CommandsInfoCmd) String() string {
  1492. return cmdString(cmd, cmd.val)
  1493. }
  1494. func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
  1495. var v interface{}
  1496. v, cmd.err = rd.ReadArrayReply(commandInfoSliceParser)
  1497. if cmd.err != nil {
  1498. return cmd.err
  1499. }
  1500. cmd.val = v.(map[string]*CommandInfo)
  1501. return nil
  1502. }
  1503. // Implements proto.MultiBulkParse
  1504. func commandInfoSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
  1505. m := make(map[string]*CommandInfo, n)
  1506. for i := int64(0); i < n; i++ {
  1507. v, err := rd.ReadReply(commandInfoParser)
  1508. if err != nil {
  1509. return nil, err
  1510. }
  1511. vv := v.(*CommandInfo)
  1512. m[vv.Name] = vv
  1513. }
  1514. return m, nil
  1515. }
  1516. func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) {
  1517. var cmd CommandInfo
  1518. var err error
  1519. if n != 6 {
  1520. return nil, fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 6", n)
  1521. }
  1522. cmd.Name, err = rd.ReadString()
  1523. if err != nil {
  1524. return nil, err
  1525. }
  1526. arity, err := rd.ReadIntReply()
  1527. if err != nil {
  1528. return nil, err
  1529. }
  1530. cmd.Arity = int8(arity)
  1531. flags, err := rd.ReadReply(stringSliceParser)
  1532. if err != nil {
  1533. return nil, err
  1534. }
  1535. cmd.Flags = flags.([]string)
  1536. firstKeyPos, err := rd.ReadIntReply()
  1537. if err != nil {
  1538. return nil, err
  1539. }
  1540. cmd.FirstKeyPos = int8(firstKeyPos)
  1541. lastKeyPos, err := rd.ReadIntReply()
  1542. if err != nil {
  1543. return nil, err
  1544. }
  1545. cmd.LastKeyPos = int8(lastKeyPos)
  1546. stepCount, err := rd.ReadIntReply()
  1547. if err != nil {
  1548. return nil, err
  1549. }
  1550. cmd.StepCount = int8(stepCount)
  1551. for _, flag := range cmd.Flags {
  1552. if flag == "readonly" {
  1553. cmd.ReadOnly = true
  1554. break
  1555. }
  1556. }
  1557. return &cmd, nil
  1558. }
  1559. //------------------------------------------------------------------------------
  1560. type cmdsInfoCache struct {
  1561. fn func() (map[string]*CommandInfo, error)
  1562. once internal.Once
  1563. cmds map[string]*CommandInfo
  1564. }
  1565. func newCmdsInfoCache(fn func() (map[string]*CommandInfo, error)) *cmdsInfoCache {
  1566. return &cmdsInfoCache{
  1567. fn: fn,
  1568. }
  1569. }
  1570. func (c *cmdsInfoCache) Get() (map[string]*CommandInfo, error) {
  1571. err := c.once.Do(func() error {
  1572. cmds, err := c.fn()
  1573. if err != nil {
  1574. return err
  1575. }
  1576. c.cmds = cmds
  1577. return nil
  1578. })
  1579. return c.cmds, err
  1580. }
上海开阖软件有限公司 沪ICP备12045867号-1