Documentation ¶
Overview ¶
Package resp implements low-level primitives for dealing with RESP (REdis Serialization Protocol). It provides client and server side readers and writers.
Example (Client) ¶
package main import ( "fmt" "net" "github.com/markusleevip/taodb/resp" ) func main() { cn, _ := net.Dial("tcp", "127.0.0.1:9736") defer cn.Close() // Wrap connection w := resp.NewRequestWriter(cn) r := resp.NewResponseReader(cn) // Write pipeline w.WriteCmdString("PING") w.WriteCmdString("ECHO", "HEllO") w.WriteCmdString("GET", "key") w.WriteCmdString("SET", "key", "value") w.WriteCmdString("DEL", "key") // Flush pipeline if err := w.Flush(); err != nil { panic(err) } // Consume responses for i := 0; i < 5; i++ { t, err := r.PeekType() if err != nil { return } switch t { case resp.TypeInline: s, _ := r.ReadInlineString() fmt.Println(s) case resp.TypeBulk: s, _ := r.ReadBulkString() fmt.Println(s) case resp.TypeInt: n, _ := r.ReadInt() fmt.Println(n) case resp.TypeNil: _ = r.ReadNil() fmt.Println(nil) default: panic("unexpected response type") } } }
Output: PONG HEllO <nil> OK 1
Index ¶
- Constants
- func IsProtocolError(err error) bool
- type Command
- type CommandArgument
- type CommandStream
- type CustomResponse
- type NullString
- type RequestReader
- func (r *RequestReader) Buffered() int
- func (r *RequestReader) PeekCmd() (string, error)
- func (r *RequestReader) ReadCmd(cmd *Command) (*Command, error)
- func (r *RequestReader) Reset(rd io.Reader)
- func (r *RequestReader) SkipCmd() error
- func (r *RequestReader) StreamCmd(cmd *CommandStream) (*CommandStream, error)
- type RequestWriter
- func (w *RequestWriter) Buffered() int
- func (w *RequestWriter) CopyBulk(r io.Reader, n int64) error
- func (w *RequestWriter) Flush() error
- func (w *RequestWriter) Reset(wr io.Writer)
- func (w *RequestWriter) WriteBulk(b []byte)
- func (w *RequestWriter) WriteBulkString(s string)
- func (w *RequestWriter) WriteCmd(cmd string, args ...[]byte)
- func (w *RequestWriter) WriteCmdString(cmd string, args ...string)
- func (w *RequestWriter) WriteMultiBulkSize(n int) error
- type ResponseParser
- type ResponseReader
- type ResponseType
- type ResponseWriter
- type Scannable
Examples ¶
Constants ¶
const MaxBufferSize = 64 * 1024
MaxBufferSize is the max request/response buffer size
Variables ¶
This section is empty.
Functions ¶
func IsProtocolError ¶
IsProtocolError returns true if the error is a protocol error
Types ¶
type Command ¶
type Command struct { // Name refers to the command name Name string // Args returns arguments Args []CommandArgument // contains filtered or unexported fields }
Command instances are parsed by a RequestReader
func NewCommand ¶
func NewCommand(name string, args ...CommandArgument) *Command
NewCommand returns a new command instance; useful for tests
func (*Command) SetContext ¶
SetContext sets the request context.
type CommandArgument ¶
type CommandArgument []byte
CommandArgument is an argument of a command
func (CommandArgument) Bytes ¶
func (c CommandArgument) Bytes() []byte
Bytes returns the argument as bytes
func (CommandArgument) Float ¶
func (c CommandArgument) Float() (float64, error)
Float returns the argument as a float64.
func (CommandArgument) Int ¶
func (c CommandArgument) Int() (int64, error)
Int returns the argument as an int64.
func (CommandArgument) String ¶
func (c CommandArgument) String() string
String returns the argument converted to a string
type CommandStream ¶
type CommandStream struct { // Name refers to the command name Name string // contains filtered or unexported fields }
CommandStream instances are created by a RequestReader
func (*CommandStream) ArgN ¶
func (c *CommandStream) ArgN() int
ArgN returns the number of arguments
func (*CommandStream) Context ¶
func (c *CommandStream) Context() context.Context
Context returns the context
func (*CommandStream) Discard ¶
func (c *CommandStream) Discard() error
Discard discards the (remaining) arguments
func (*CommandStream) More ¶
func (c *CommandStream) More() bool
More returns true if there are unread arguments
func (*CommandStream) Next ¶
func (c *CommandStream) Next() (io.Reader, error)
Next returns the next argument as an io.Reader
func (*CommandStream) Reset ¶
func (c *CommandStream) Reset()
Reset discards all data and resets all state
func (*CommandStream) SetContext ¶
func (c *CommandStream) SetContext(ctx context.Context)
SetContext sets the request context.
type CustomResponse ¶
type CustomResponse interface { // AppendTo must be implemented by custom response types AppendTo(w ResponseWriter) }
CustomResponse values implement custom serialization and can be passed to ResponseWriter.Append.
type NullString ¶
NullString is a scannable that can deal with nil values
func (*NullString) ScanResponse ¶
func (s *NullString) ScanResponse(t ResponseType, r ResponseReader) error
ScanResponse implements Scannable
type RequestReader ¶
type RequestReader struct {
// contains filtered or unexported fields
}
RequestReader is used by servers to wrap a client connection and convert requests into commands.
Example ¶
package main import ( "fmt" "strings" "github.com/markusleevip/taodb/resp" ) func main() { cn := strings.NewReader("*1\r\n$4\r\nPING\r\n*2\r\n$4\r\nEcHO\r\n$5\r\nHeLLO\r\n") r := resp.NewRequestReader(cn) // read command cmd, _ := r.ReadCmd(nil) fmt.Println(cmd.Name) for i := 0; i < len(cmd.Args); i++ { fmt.Println(i, cmd.Args[i]) } // read command, recycle previous instance cmd, _ = r.ReadCmd(cmd) fmt.Println(cmd.Name) for i := 0; i < len(cmd.Args); i++ { fmt.Println(i, cmd.Args[i]) } }
Output: PING EcHO 0 HeLLO
func NewRequestReader ¶
func NewRequestReader(rd io.Reader) *RequestReader
NewRequestReader wraps any reader interface
func (*RequestReader) Buffered ¶
func (r *RequestReader) Buffered() int
Buffered returns the number of unread bytes.
func (*RequestReader) PeekCmd ¶
func (r *RequestReader) PeekCmd() (string, error)
PeekCmd peeks the next command name.
func (*RequestReader) ReadCmd ¶
func (r *RequestReader) ReadCmd(cmd *Command) (*Command, error)
ReadCmd reads the next command. It optionally recycles the cmd passed.
func (*RequestReader) Reset ¶
func (r *RequestReader) Reset(rd io.Reader)
Reset resets the reader to a new reader and recycles internal buffers.
func (*RequestReader) SkipCmd ¶
func (r *RequestReader) SkipCmd() error
SkipCmd skips the next command.
func (*RequestReader) StreamCmd ¶
func (r *RequestReader) StreamCmd(cmd *CommandStream) (*CommandStream, error)
StreamCmd reads the next command as a stream.
type RequestWriter ¶
type RequestWriter struct {
// contains filtered or unexported fields
}
RequestWriter is used by clients to send commands to servers.
func NewRequestWriter ¶
func NewRequestWriter(wr io.Writer) *RequestWriter
NewRequestWriter wraps any Writer interface
func (*RequestWriter) Buffered ¶
func (w *RequestWriter) Buffered() int
Buffered returns the number of buffered bytes
func (*RequestWriter) CopyBulk ¶
func (w *RequestWriter) CopyBulk(r io.Reader, n int64) error
CopyBulk is a low-level method to copy a large bulk of data directly to the writer. For normal operation, use WriteCmd or WriteCmdString.
func (*RequestWriter) Flush ¶
func (w *RequestWriter) Flush() error
Flush flushes the output buffer. Call this after you have completed your pipeline
func (*RequestWriter) Reset ¶
func (w *RequestWriter) Reset(wr io.Writer)
Reset resets the writer with an new interface
func (*RequestWriter) WriteBulk ¶
func (w *RequestWriter) WriteBulk(b []byte)
WriteBulk is a low-level method to write a bulk. For normal operation, use WriteCmd or WriteCmdString.
func (*RequestWriter) WriteBulkString ¶
func (w *RequestWriter) WriteBulkString(s string)
WriteBulkString is a low-level method to write a bulk. For normal operation, use WriteCmd or WriteCmdString.
func (*RequestWriter) WriteCmd ¶
func (w *RequestWriter) WriteCmd(cmd string, args ...[]byte)
WriteCmd writes a full command as part of a pipeline. To execute the pipeline, you must call Flush.
func (*RequestWriter) WriteCmdString ¶
func (w *RequestWriter) WriteCmdString(cmd string, args ...string)
WriteCmdString writes a full command as part of a pipeline. To execute the pipeline, you must call Flush.
func (*RequestWriter) WriteMultiBulkSize ¶
func (w *RequestWriter) WriteMultiBulkSize(n int) error
WriteMultiBulkSize is a low-level method to write a multibulk size. For normal operation, use WriteCmd or WriteCmdString.
type ResponseParser ¶
type ResponseParser interface { // PeekType returns the type of the next response block PeekType() (ResponseType, error) // ReadNil reads a nil value ReadNil() error // ReadBulkString reads a bulk and returns a string ReadBulkString() (string, error) // ReadBulk reads a bulk and returns bytes (optionally appending to a passed p buffer) ReadBulk(p []byte) ([]byte, error) // StreamBulk parses a bulk responses and returns a streaming reader object // Returned responses must be closed. StreamBulk() (io.ReadCloser, error) // ReadInt reads an int value ReadInt() (int64, error) // ReadArrayLen reads the array length ReadArrayLen() (int, error) // ReadError reads an error string ReadError() (string, error) // ReadInlineString reads a status string ReadInlineString() (string, error) // Scan scans results into the given values. Scan(vv ...interface{}) error }
ResponseParser is a basic response parser
type ResponseReader ¶
type ResponseReader interface { ResponseParser // Buffered returns the number of buffered (unread) bytes. Buffered() int // Reset resets the reader to a new reader and recycles internal buffers. Reset(r io.Reader) }
ResponseReader is used by clients to wrap a server connection and parse responses.
func NewResponseReader ¶
func NewResponseReader(rd io.Reader) ResponseReader
NewResponseReader returns ResponseReader, which wraps any reader interface, but normally a net.Conn.
type ResponseType ¶
type ResponseType uint8
ResponseType represents the reply type
const ( TypeUnknown ResponseType = iota TypeArray TypeBulk TypeInline TypeError TypeInt TypeNil )
response type iota
func (ResponseType) String ¶
func (t ResponseType) String() string
String returns the response type description
type ResponseWriter ¶
type ResponseWriter interface { io.Writer // AppendArrayLen appends an array header to the output buffer. AppendArrayLen(n int) // AppendBulk appends bulk bytes to the output buffer. AppendBulk(p []byte) // AppendBulkString appends a bulk string to the output buffer. AppendBulkString(s string) // AppendInline appends inline bytes to the output buffer. AppendInline(p []byte) // AppendInlineString appends an inline string to the output buffer. AppendInlineString(s string) // AppendError appends an error message to the output buffer. AppendError(msg string) // AppendErrorf appends an error message to the output buffer. AppendErrorf(pattern string, args ...interface{}) // AppendInt appends a numeric response to the output buffer. AppendInt(n int64) // AppendNil appends a nil-value to the output buffer. AppendNil() // AppendOK appends "OK" to the output buffer. AppendOK() // Append automatically serialized given values and appends them to the output buffer. // Supported values include: // * nil // * error // * string // * []byte // * bool // * float32, float64 // * int, int8, int16, int32, int64 // * uint, uint8, uint16, uint32, uint64 // * CustomResponse instances // * slices and maps of any of the above Append(v interface{}) error // CopyBulk copies n bytes from a reader. // This call may flush pending buffer to prevent overflows. CopyBulk(src io.Reader, n int64) error // Buffered returns the number of pending bytes. Buffered() int // Flush flushes pending buffer. Flush() error // Reset resets the writer to a new writer and recycles internal buffers. Reset(w io.Writer) }
ResponseWriter is used by servers to wrap a client connection and send protocol-compatible responses in buffered pipelines.
Example ¶
package main import ( "bytes" "fmt" "github.com/markusleevip/taodb/resp" ) func main() { buf := new(bytes.Buffer) w := resp.NewResponseWriter(buf) // Append OK response w.AppendOK() // Append a number w.AppendInt(33) // Append an array w.AppendArrayLen(3) w.AppendBulkString("Adam") w.AppendBulkString("Had'em") w.AppendNil() // Writer data must be flushed manually fmt.Println(buf.Len(), w.Buffered()) if err := w.Flush(); err != nil { panic(err) } // Once flushed, it will be sent to the underlying writer // as a bulk fmt.Println(buf.Len(), w.Buffered()) fmt.Printf("%q\n", buf.String()) }
Output: 0 41 41 0 "+OK\r\n:33\r\n*3\r\n$4\r\nAdam\r\n$6\r\nHad'em\r\n$-1\r\n"
func NewResponseWriter ¶
func NewResponseWriter(wr io.Writer) ResponseWriter
NewResponseWriter wraps any writer interface, but normally a net.Conn.
type Scannable ¶
type Scannable interface { // ScanResponse scans theresponse from the reader ScanResponse(t ResponseType, r ResponseReader) error }
Scannable interfaces may implement custom Scan behaviour