Documentation
¶
Overview ¶
Package protocol implements the RESP2 and RESP3 wire protocol framing used by the celeris native Redis driver.
The parser is allocation-frugal: simple strings, errors, and bulk strings are returned as slices that alias the Reader's internal input buffer. Callers that need to retain bytes past the next Reader.Feed or Reader.Next call must copy them. The aggregate types (Array, Set, Push, Map, Attr) draw their backing slices from small sync.Pools — call Reader.Release on a top-level Value to return those slices to the pool.
RESP2 types: +, -, :, $, *. RESP3 types add: _ (null), # (bool), , (double), ( (bignum), ! (blob error), = (verbatim), ~ (set), % (map), | (attribute), > (push).
Incremental parsing ¶
Reader.Next returns ErrIncomplete when the buffered input does not yet hold a full frame. The read cursor is not advanced in this case, so the caller should feed more bytes and retry.
Large bulk strings ¶
Bulk strings longer than [maxInlineBulk] are returned in a freshly allocated heap buffer rather than kept in the Reader's own buffer. This prevents pathological growth of the Reader buffer on occasional large values.
Index ¶
- Constants
- Variables
- func ClearPooledFlags(v *Value)
- type KV
- type Reader
- type Type
- type Value
- type Writer
- func (w *Writer) AppendCommand(args ...string) []byte
- func (w *Writer) AppendCommand1(a0 string) []byte
- func (w *Writer) AppendCommand2(a0, a1 string) []byte
- func (w *Writer) AppendCommand3(a0, a1, a2 string) []byte
- func (w *Writer) AppendCommand4(a0, a1, a2, a3 string) []byte
- func (w *Writer) AppendCommand5(a0, a1, a2, a3, a4 string) []byte
- func (w *Writer) AppendCommandBytes(args [][]byte) []byte
- func (w *Writer) Bytes() []byte
- func (w *Writer) Grow(n int)
- func (w *Writer) Reset()
- func (w *Writer) WriteCommand(args ...string) []byte
- func (w *Writer) WriteCommandBytes(args [][]byte) []byte
Constants ¶
const ( // MaxBulkLen caps the advertised length of a single bulk/verbatim/blob // error frame. 512 MiB matches Redis's own proto-max-bulk-len ceiling. MaxBulkLen = 512 * 1024 * 1024 // MaxArrayLen caps the advertised element count of an aggregate // (array/set/push/map/attr). Chosen generously — 128M elements would // already represent gigabytes of pointers. MaxArrayLen = 128 * 1024 * 1024 )
Variables ¶
var ErrIncomplete = errors.New("celeris-redis-protocol: incomplete frame")
ErrIncomplete indicates the buffered input does not yet contain a full RESP frame. The Reader's cursor is not advanced.
var ErrProtocol = errors.New("celeris-redis-protocol: protocol error")
ErrProtocol indicates malformed RESP input.
var ErrProtocolOversizedArray = errors.New("celeris-redis-protocol: aggregate length exceeds maximum")
ErrProtocolOversizedArray indicates an aggregate header (array / set / push / map / attr) exceeds MaxArrayLen.
var ErrProtocolOversizedBulk = errors.New("celeris-redis-protocol: bulk length exceeds maximum")
ErrProtocolOversizedBulk indicates a bulk string length header exceeds MaxBulkLen. Hostile or corrupt servers can otherwise force the Reader buffer to grow without bound while waiting for payload bytes.
Functions ¶
func ClearPooledFlags ¶
func ClearPooledFlags(v *Value)
ClearPooledFlags marks v (and its nested Array/Map entries) as non-pooled. Callers that deep-copy a Value into heap-allocated slices must invoke this so a later Reader.Release cannot return heap slices into the Reader's sync.Pools (which would corrupt later parses).
Types ¶
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader is a streaming RESP decoder. It owns an append-only buffer that callers extend via Reader.Feed. The zero value is ready for use.
func (*Reader) Compact ¶
func (r *Reader) Compact()
Compact discards already-parsed bytes. Aliased slices from previously returned Values become invalid after Compact.
func (*Reader) Next ¶
Next parses one complete RESP value. On ErrIncomplete, the read cursor is left unchanged; the caller should Feed more bytes and retry.
type Type ¶
type Type uint8
Type tags a RESP value.
const ( // TySimple is a RESP2/RESP3 simple string prefixed by '+'. TySimple Type = iota // TyError is a RESP2/RESP3 simple error prefixed by '-'. TyError // TyInt is a RESP2/RESP3 integer prefixed by ':'. TyInt // TyBulk is a RESP2/RESP3 bulk string prefixed by '$'. TyBulk // TyArray is a RESP2/RESP3 array prefixed by '*'. TyArray // TyNull is a RESP3 null ('_') or a RESP2 null-bulk/null-array ($-1/*-1). TyNull // TyBool is a RESP3 boolean prefixed by '#'. TyBool // TyDouble is a RESP3 double prefixed by ','. TyDouble // TyBigInt is a RESP3 big number prefixed by '('. TyBigInt // TyBlobErr is a RESP3 blob error prefixed by '!'. TyBlobErr // TyVerbatim is a RESP3 verbatim string prefixed by '='. TyVerbatim // TySet is a RESP3 set prefixed by '~'. TySet // TyMap is a RESP3 map prefixed by '%'. TyMap // TyAttr is a RESP3 attribute map prefixed by '|'. TyAttr // TyPush is a RESP3 push frame prefixed by '>'. TyPush )
type Value ¶
type Value struct {
Type Type
Str []byte
Int int64
Float float64
Bool bool
BigN []byte
Array []Value
Map []KV
// contains filtered or unexported fields
}
Value is one decoded RESP value. Depending on Type, different fields are populated.
- Simple / Error / Bulk / Verbatim / BlobErr → Str (may alias the Reader's buffer; copy before next Feed/Next).
- Int → Int.
- Double → Float.
- Bool → Bool.
- BigInt → BigN (raw ASCII, alias of buffer).
- Array / Set / Push → Array.
- Map / Attr → Map.
- Null → no field set.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer serializes RESP2 command arrays suitable for any Redis server. Only the RESP2 array-of-bulk-strings "inline command" form is emitted — servers accept this even when negotiated to RESP3 for responses.
func NewWriter ¶
func NewWriter() *Writer
NewWriter returns a Writer with a small pre-allocated buffer.
func NewWriterSize ¶
NewWriterSize returns a Writer with a pre-allocated buffer of at least size bytes. Use this for pipeline workloads where the total encoded size is known or estimable, to avoid repeated grow-copies.
func (*Writer) AppendCommand ¶
AppendCommand appends one command to the buffer without resetting.
func (*Writer) AppendCommand1 ¶
AppendCommand1 appends a 1-arg command without allocating a []string slice.
func (*Writer) AppendCommand2 ¶
AppendCommand2 appends a 2-arg command without allocating a []string slice.
func (*Writer) AppendCommand3 ¶
AppendCommand3 appends a 3-arg command without allocating a []string slice.
func (*Writer) AppendCommand4 ¶
AppendCommand4 appends a 4-arg command without allocating a []string slice.
func (*Writer) AppendCommand5 ¶
AppendCommand5 appends a 5-arg command without allocating a []string slice.
func (*Writer) AppendCommandBytes ¶
AppendCommandBytes appends one []byte command.
func (*Writer) Grow ¶
Grow ensures the Writer's internal buffer has at least n bytes of unused capacity. If the buffer already has sufficient capacity, this is a no-op.
func (*Writer) Reset ¶
func (w *Writer) Reset()
Reset empties the internal buffer without freeing it.
func (*Writer) WriteCommand ¶
WriteCommand appends *N\r\n$len\r\nARG\r\n... for the given string args and returns the full internal buffer slice. Callers that issue several commands before flushing should call Writer.Reset between commands — or use Writer.AppendCommand to append a second command after the first.
func (*Writer) WriteCommandBytes ¶
WriteCommandBytes is the []byte variant, avoiding the string conversion.