|
|
@@ -0,0 +1,116 @@
|
|
|
+// Package reply 实现了Redis序列化协议(RESP)的回复处理功能。
|
|
|
+//
|
|
|
+// 本包包含构建符合Redis RESP协议的各种响应格式的实现,支持以下类型:
|
|
|
+// - 简单字符串(Simple Strings): StatusReply
|
|
|
+// - 错误类型(Errors): StandardErrReply 及其子类型
|
|
|
+// - 整型(Integers): IntReply
|
|
|
+// - 批量字符串(Bulk Strings): BulkReply
|
|
|
+// - 数组(Arrays): MultiBulkReply
|
|
|
+//
|
|
|
+// 所有回复类型都实现了 `resp.Reply` 接口,通过 `ToBytes()` 方法生成符合RESP协议格式的字节数据。
|
|
|
+//
|
|
|
+// 示例用法:
|
|
|
+//
|
|
|
+// // 创建整数回复
|
|
|
+// reply := NewIntReply(42)
|
|
|
+// output := reply.ToBytes() // 输出 ":42\r\n"
|
|
|
+//
|
|
|
+// // 创建批量字符串回复
|
|
|
+// bulk := NewBulkReply([]byte("hello"))
|
|
|
+// output := bulk.ToBytes() // 输出 "$5\r\nhello\r\n"
|
|
|
+package reply
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "strconv"
|
|
|
+
|
|
|
+ "github.com/runningwater/go-redis/interface/resp"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ nullBulkReplyBytes = []byte("$-1")
|
|
|
+ CRLF = "\r\n"
|
|
|
+)
|
|
|
+
|
|
|
+type BulkReply struct {
|
|
|
+ Arg []byte // "test" => "$4\r\ntest\r\n"
|
|
|
+}
|
|
|
+
|
|
|
+func (b *BulkReply) ToBytes() []byte {
|
|
|
+ if len(b.Arg) == 0 {
|
|
|
+ return nullBulkReplyBytes
|
|
|
+ }
|
|
|
+ return []byte("$" + strconv.Itoa(len(b.Arg)) + CRLF + string(b.Arg) + CRLF)
|
|
|
+}
|
|
|
+
|
|
|
+func NewBulkReply(arg []byte) *BulkReply {
|
|
|
+ return &BulkReply{Arg: arg}
|
|
|
+}
|
|
|
+
|
|
|
+type MultiBulkReply struct {
|
|
|
+ Args [][]byte
|
|
|
+}
|
|
|
+
|
|
|
+func (m *MultiBulkReply) ToBytes() []byte {
|
|
|
+ argLen := len(m.Args)
|
|
|
+ var buf bytes.Buffer
|
|
|
+ buf.WriteString("*" + strconv.Itoa(argLen) + CRLF)
|
|
|
+ for _, arg := range m.Args {
|
|
|
+ if arg == nil {
|
|
|
+ buf.WriteString(string(nullBulkReplyBytes) + CRLF)
|
|
|
+ } else {
|
|
|
+ buf.WriteString("$" + strconv.Itoa(len(arg)) + CRLF + string(arg) + CRLF)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return buf.Bytes()
|
|
|
+}
|
|
|
+
|
|
|
+func NewMultiBulkReply(args [][]byte) *MultiBulkReply {
|
|
|
+ return &MultiBulkReply{Args: args}
|
|
|
+}
|
|
|
+
|
|
|
+type StatusReply struct {
|
|
|
+ Status string
|
|
|
+}
|
|
|
+
|
|
|
+func (s *StatusReply) ToBytes() []byte {
|
|
|
+ return []byte("+" + s.Status + CRLF)
|
|
|
+}
|
|
|
+
|
|
|
+func NewStatusReply(status string) *StatusReply {
|
|
|
+ return &StatusReply{Status: status}
|
|
|
+}
|
|
|
+
|
|
|
+type IntReply struct {
|
|
|
+ Code int64
|
|
|
+}
|
|
|
+
|
|
|
+func (i *IntReply) ToBytes() []byte {
|
|
|
+ return []byte(":" + strconv.FormatInt(i.Code, 10) + CRLF)
|
|
|
+}
|
|
|
+
|
|
|
+type ErrorReply interface {
|
|
|
+ Error() string
|
|
|
+ ToBytes() []byte
|
|
|
+}
|
|
|
+
|
|
|
+type StandardErrReply struct {
|
|
|
+ Status string
|
|
|
+}
|
|
|
+
|
|
|
+func (s *StandardErrReply) Error() string {
|
|
|
+ return s.Status
|
|
|
+}
|
|
|
+
|
|
|
+func (s *StandardErrReply) ToBytes() []byte {
|
|
|
+ return []byte("-" + s.Status + CRLF)
|
|
|
+}
|
|
|
+
|
|
|
+func NewStandardErrReply(status string) *StandardErrReply {
|
|
|
+ return &StandardErrReply{Status: status}
|
|
|
+}
|
|
|
+
|
|
|
+func IsErrReply(reply resp.Reply) bool {
|
|
|
+ return reply.ToBytes()[0] == '-'
|
|
|
+}
|