Skip to content

Commit

Permalink
Reapply: Fix an issue status type (+) is not read/write properly (#37)
Browse files Browse the repository at this point in the history
* Fix an issue status type (+) is not read/write properly (#22)

* add an option for using StatusString vs string
  • Loading branch information
greedy52 authored Mar 8, 2023
1 parent 0e65059 commit 47d561e
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 4 deletions.
27 changes: 24 additions & 3 deletions internal/proto/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const (
RespPush = '>' // ><len>\r\n... (same as Array)
)

// StatusString is the read golang type of the RespStatus.
type StatusString string

// Not used temporarily.
// Redis has not used these two data types for the time being, and will implement them later.
// Streamed = "EOF:"
Expand All @@ -52,13 +55,28 @@ func ParseErrorReply(line []byte) error {

//------------------------------------------------------------------------------

type readerOpt struct {
// useStatusStringType uses `StatusString` type instead of string for RespStatus.
useStatusStringType bool
}

func ReaderOptUseStatusStringType(o *readerOpt) {
o.useStatusStringType = true
}

type Reader struct {
rd *bufio.Reader
rd *bufio.Reader
opt readerOpt
}

func NewReader(rd io.Reader) *Reader {
func NewReader(rd io.Reader, opts ...func(o *readerOpt)) *Reader {
opt := readerOpt{}
for _, applyOpt := range opts {
applyOpt(&opt)
}
return &Reader{
rd: bufio.NewReader(rd),
rd: bufio.NewReader(rd),
opt: opt,
}
}

Expand Down Expand Up @@ -159,6 +177,9 @@ func (r *Reader) ReadReply() (interface{}, error) {

switch line[0] {
case RespStatus:
if r.opt.useStatusStringType {
return StatusString(line[1:]), nil
}
return string(line[1:]), nil
case RespInt:
return util.ParseInt(line[1:], 10, 64)
Expand Down
14 changes: 14 additions & 0 deletions internal/proto/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ func (w *Writer) WriteArg(v interface{}) error {
return w.string("")
case string:
return w.string(v)
case StatusString:
return w.status(v)
case []byte:
return w.bytes(v)
case int:
Expand Down Expand Up @@ -135,6 +137,18 @@ func (w *Writer) bytes(b []byte) error {
return w.crlf()
}

func (w *Writer) status(s StatusString) error {
if err := w.WriteByte(RespStatus); err != nil {
return err
}

if _, err := w.Write([]byte(s)); err != nil {
return err
}

return w.crlf()
}

func (w *Writer) string(s string) error {
return w.bytes(util.StringToBytes(s))
}
Expand Down
27 changes: 27 additions & 0 deletions internal/proto/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,30 @@ func BenchmarkWriteBuffer_Append(b *testing.B) {
}
}
}

func TestWriteStatus(t *testing.T) {
inputStatusBytes := []byte("+status\r\n")

// Read it.
reader := proto.NewReader(bytes.NewReader(inputStatusBytes), proto.ReaderOptUseStatusStringType)
readStatus, err := reader.ReadReply()
if err != nil {
t.Errorf("Failed to ReadReply: %v", err)
}

if readStatus != proto.StatusString("status") {
t.Errorf("expect read %v but got %v", "status", readStatus)
}

// Write it.
outputStatusBytes := new(bytes.Buffer)
writer := proto.NewWriter(outputStatusBytes)
err = writer.WriteArg(readStatus)
if err != nil {
t.Errorf("Failed to WriteArg: %v", err)
}

if string(inputStatusBytes) != outputStatusBytes.String() {
t.Errorf("expect written %v but got %v", string(inputStatusBytes), outputStatusBytes.String())
}
}
2 changes: 1 addition & 1 deletion proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const RespArray = proto.RespArray
const RespInt = proto.RespInt

func NewReader(rd io.Reader) *Reader {
return proto.NewReader(rd)
return proto.NewReader(rd, proto.ReaderOptUseStatusStringType)
}

func NewWriter(wr *bytes.Buffer) *Writer {
Expand Down

0 comments on commit 47d561e

Please sign in to comment.