mirror of
https://github.com/redis/go-redis.git
synced 2025-07-22 10:01:50 +03:00
Initial commit.
This commit is contained in:
334
request.go
Normal file
334
request.go
Normal file
@ -0,0 +1,334 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/togoio/redisgoproxy/bufreader"
|
||||
)
|
||||
|
||||
var Nil = errors.New("(nil)")
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func ParseReq(rd *bufreader.Reader) ([]string, error) {
|
||||
line, err := rd.ReadLine('\n')
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if line[0] != '*' {
|
||||
return []string{string(line)}, nil
|
||||
}
|
||||
|
||||
args := make([]string, 0)
|
||||
for {
|
||||
line, err = rd.ReadLine('\n')
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if line[0] != '$' {
|
||||
return nil, fmt.Errorf("Expected '$', but got %q of %q.", line, rd.Bytes())
|
||||
}
|
||||
|
||||
line, err = rd.ReadLine('\n')
|
||||
args = append(args, string(line))
|
||||
}
|
||||
return args, nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func PackReq(args []string) []byte {
|
||||
buf := make([]byte, 0, 1024)
|
||||
buf = append(buf, '*')
|
||||
buf = strconv.AppendUint(buf, uint64(len(args)), 10)
|
||||
buf = append(buf, '\r', '\n')
|
||||
for _, arg := range args {
|
||||
buf = append(buf, '$')
|
||||
buf = strconv.AppendUint(buf, uint64(len(arg)), 10)
|
||||
buf = append(buf, '\r', '\n')
|
||||
buf = append(buf, []byte(arg)...)
|
||||
buf = append(buf, '\r', '\n')
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type Req interface {
|
||||
Req() []byte
|
||||
ParseReply(*bufreader.Reader)
|
||||
SetErr(error)
|
||||
Err() error
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type BaseReq struct {
|
||||
args []string
|
||||
err error
|
||||
}
|
||||
|
||||
func NewBaseReq(args ...string) *BaseReq {
|
||||
return &BaseReq{
|
||||
args: args,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *BaseReq) Req() []byte {
|
||||
return PackReq(r.args)
|
||||
}
|
||||
|
||||
func (r *BaseReq) SetErr(err error) {
|
||||
r.err = err
|
||||
}
|
||||
|
||||
func (r *BaseReq) Err() error {
|
||||
return r.err
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type StatusReq struct {
|
||||
*BaseReq
|
||||
val string
|
||||
}
|
||||
|
||||
func NewStatusReq(args ...string) *StatusReq {
|
||||
return &StatusReq{
|
||||
BaseReq: NewBaseReq(args...),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *StatusReq) ParseReply(rd *bufreader.Reader) {
|
||||
var line []byte
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if line[0] == '-' {
|
||||
r.err = errors.New(string(line[1:]))
|
||||
return
|
||||
} else if line[0] != '+' {
|
||||
r.err = fmt.Errorf("Expected '+', but got %q of %q.", line, rd.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
r.val = string(line[1:])
|
||||
}
|
||||
|
||||
func (r *StatusReq) Reply() (string, error) {
|
||||
return r.val, r.err
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type IntReq struct {
|
||||
*BaseReq
|
||||
val int64
|
||||
}
|
||||
|
||||
func NewIntReq(args ...string) *IntReq {
|
||||
return &IntReq{
|
||||
BaseReq: NewBaseReq(args...),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *IntReq) ParseReply(rd *bufreader.Reader) {
|
||||
var line []byte
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if line[0] == '-' {
|
||||
r.err = errors.New(string(line[1:]))
|
||||
return
|
||||
} else if line[0] != ':' {
|
||||
r.err = fmt.Errorf("Expected ':', but got %q of %q.", line, rd.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
r.val, r.err = strconv.ParseInt(string(line[1:]), 10, 64)
|
||||
}
|
||||
|
||||
func (r *IntReq) Reply() (int64, error) {
|
||||
return r.val, r.err
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type BoolReq struct {
|
||||
*BaseReq
|
||||
val bool
|
||||
}
|
||||
|
||||
func NewBoolReq(args ...string) *BoolReq {
|
||||
return &BoolReq{
|
||||
BaseReq: NewBaseReq(args...),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *BoolReq) ParseReply(rd *bufreader.Reader) {
|
||||
var line []byte
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if line[0] == '-' {
|
||||
r.err = errors.New(string(line[1:]))
|
||||
return
|
||||
} else if line[0] != ':' {
|
||||
r.err = fmt.Errorf("Expected ':', but got %q of %q.", line, rd.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
r.val = line[1] == '1'
|
||||
}
|
||||
|
||||
func (r *BoolReq) Reply() (bool, error) {
|
||||
return r.val, r.err
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type BulkReq struct {
|
||||
*BaseReq
|
||||
val string
|
||||
}
|
||||
|
||||
func NewBulkReq(args ...string) *BulkReq {
|
||||
return &BulkReq{
|
||||
BaseReq: NewBaseReq(args...),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *BulkReq) ParseReply(rd *bufreader.Reader) {
|
||||
var line []byte
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if line[0] == '-' {
|
||||
r.err = errors.New(string(line[1:]))
|
||||
return
|
||||
} else if line[0] != '$' {
|
||||
r.err = fmt.Errorf("Expected '$', but got %q of %q.", line, rd.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
if len(line) >= 3 && line[1] == '-' && line[2] == '1' {
|
||||
r.err = Nil
|
||||
return
|
||||
}
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
r.val = string(line)
|
||||
}
|
||||
|
||||
func (r *BulkReq) Reply() (string, error) {
|
||||
return r.val, r.err
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type MultiBulkReq struct {
|
||||
*BaseReq
|
||||
val []interface{}
|
||||
}
|
||||
|
||||
func NewMultiBulkReq(args ...string) *MultiBulkReq {
|
||||
return &MultiBulkReq{
|
||||
BaseReq: NewBaseReq(args...),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MultiBulkReq) ParseReply(rd *bufreader.Reader) {
|
||||
var line []byte
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if line[0] == '-' {
|
||||
r.err = errors.New(string(line[1:]))
|
||||
return
|
||||
} else if line[0] != '*' {
|
||||
r.err = fmt.Errorf("Expected '*', but got line %q of %q.", line, rd.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
val := make([]interface{}, 0)
|
||||
|
||||
if len(line) >= 2 && line[1] == '0' {
|
||||
r.val = val
|
||||
return
|
||||
} else if len(line) >= 3 && line[1] == '-' && line[2] == '1' {
|
||||
r.err = Nil
|
||||
return
|
||||
}
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
for {
|
||||
if line[0] == ':' {
|
||||
var n int64
|
||||
n, r.err = strconv.ParseInt(string(line[1:]), 10, 64)
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
val = append(val, n)
|
||||
} else if line[0] == '$' {
|
||||
if len(line) >= 2 && line[1] == '0' {
|
||||
val = append(val, "")
|
||||
} else if len(line) >= 3 && line[1] == '-' && line[2] == '1' {
|
||||
val = append(val, nil)
|
||||
} else {
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err != nil {
|
||||
return
|
||||
}
|
||||
val = append(val, string(line))
|
||||
}
|
||||
} else {
|
||||
r.err = fmt.Errorf("Expected '$', but got line %q of %q.", line, rd.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
line, r.err = rd.ReadLine('\n')
|
||||
if r.err == io.EOF {
|
||||
r.err = nil
|
||||
break
|
||||
}
|
||||
// Check for start of another reply.
|
||||
if line[0] == '*' {
|
||||
rd.UnreadLine('\n')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
r.val = val
|
||||
}
|
||||
|
||||
func (r *MultiBulkReq) Reply() ([]interface{}, error) {
|
||||
return r.val, r.err
|
||||
}
|
Reference in New Issue
Block a user