resp3

package
v4.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2023 License: MIT Imports: 16 Imported by: 8

Documentation

Overview

Package resp3 implements the upgraded redis RESP3 protocol, a plaintext protocol which is also binary safe and backwards compatible with the original RESP2 protocol.

Redis uses the RESP protocol to communicate with its clients, but there's nothing about the protocol which ties it to redis, it could be used for almost anything.

See https://github.com/antirez/RESP3 for more details on the protocol.

In general attribute messages are transarently discarded in this package. The user can read them manually prior to the message they are attached to if they are expected and desired.

Example (StreamedAggregatedType)
buf := new(bytes.Buffer)
opts := resp.NewOpts()

// First write a streamed array to the buffer. The array will have 3 number
// elements (remember to check the errors).
_ = (ArrayHeader{StreamedArrayHeader: true}).MarshalRESP(buf, opts)
_ = (Number{N: 1}).MarshalRESP(buf, opts)
_ = (Number{N: 2}).MarshalRESP(buf, opts)
_ = (Number{N: 3}).MarshalRESP(buf, opts)
_ = (StreamedAggregatedTypeEnd{}).MarshalRESP(buf, opts)

// Now create a reader which will read from the buffer, and use it to read
// the streamed array.
br := bufio.NewReader(buf)

// The type of the next message can be checked by peeking at the next byte.
if prefixB, _ := br.Peek(1); Prefix(prefixB[0]) != ArrayHeaderPrefix {
	panic("expected array header")
}

var head ArrayHeader
if err := head.UnmarshalRESP(br, opts); err != nil {
	panic(err)
} else if !head.StreamedArrayHeader {
	panic("expected streamed array header")
}
fmt.Println("streamed array begun")

for {
	var el Number
	aggEl := StreamedAggregatedElement{Receiver: &el}
	if err := aggEl.UnmarshalRESP(br, opts); err != nil {
		panic(err)

	} else if aggEl.End {
		fmt.Println("streamed array ended")
		return
	}
	fmt.Printf("read element with value %d\n", el.N)
}
Output:

streamed array begun
read element with value 1
read element with value 2
read element with value 3
streamed array ended

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func DiscardAttribute

func DiscardAttribute(br resp.BufferedReader, o *resp.Opts) error

DiscardAttribute discards the next RESP3 message if it is an attribute message. If the next message is not an attribute message then DiscardAttribute does nothing..

func Flatten

func Flatten(i interface{}, o *resp.Opts) ([]string, error)

Flatten accepts any type accepted by Marshal, except a resp.Marshaler, and converts it into a flattened array of strings. For example:

Flatten(5) -> {"5"}
Flatten(nil) -> {""}
Flatten([]string{"a","b"}) -> {"a", "b"}
Flatten(map[string]int{"a":5,"b":10}) -> {"a","5","b","10"}
Flatten([]map[int]float64{{1:2, 3:4},{5:6},{}}) -> {"1","2","3","4","5","6"})

func Marshal

func Marshal(w io.Writer, i interface{}, o *resp.Opts) error

Marshal writes an arbitrary go value as a RESP3 message onto an io.Writer. The mappings from go types to RESP types are as follows (T denotes a go type, RT denotes the corresponding RESP type for T):

resp.Marshaler -> marshaled as-is

[]byte, string, []rune, resp.LenReader -> blob string
encoding.TextMarshaler                 -> blob string
encoding.BinaryMarshaler               -> blob string
io.Reader                              -> streamed string

nil, []T(nil), map[T]struct{}(nil), map[T]T'(nil) -> null
error                                             -> blob error

bool                                    -> boolean
float32, float64, big.Float             -> double
int, int8, int16, int32, int64, big.Int -> number
uint, uint8, uint16, uint32, uint64     -> number

*T             -> RT
[]T            -> array of RT
map[T]struct{} -> set of RT
map[T]T'       -> map with RT keys and RT' values

Structs will be marshaled as a map, where each of the struct's field names will be marshaled as a simple string, and each of the struct's values will be marshaled as the RESP type corresponding to that value's type. Each field can be tagged with `redis:"fieldName"` to specify the field name manually, or `redis:"-"` to omit the field.

func NextMessageIs

func NextMessageIs(br resp.BufferedReader, p Prefix) (bool, error)

NextMessageIs returns true if the next value in the given reader has the given prefix.

If there is an error reading from br, NextMessageIs will return false and the error.

func Unmarshal

func Unmarshal(br resp.BufferedReader, rcv interface{}, o *resp.Opts) error

Unmarshal reads a RESP3 message off a bufio.Reader and unmarshals it into the given pointer receiver. The receiver must be a pointer or nil. If the receiver is nil then the RESP3 message will be read and discarded.

Unmarshal supports all go types supported by MarshalRESP, but has more flexibility. For example a RESP number message can be unmarshaled into a go string, and a RESP array with an even number of elements can be unmarshaled into a go map.

If the receiver is a resp.Unmarshaler then the resp.Unmarshaler will be unmarshaled into. If any element type of an aggregated type (e.g. array) is a resp.Unmarshaler then the same applies for each element being unmarshaled.

resp.SimpleError or resp.BlobError will be returned as the error from Unmarshal when either message type is read. The receiver will not be touched in this case.

RESP2 null bulk string and null bulk array messages are supported and are treated as null messages.

If the receiver is an io.Writer then the RESP message's value will be written into it, encoded as if I were a []byte.

Streamed aggregated RESP messages will be treated as if they were their non-streamed counterpart, e.g. streamed arrays will be treated as arrays.

Types

type ArrayHeader

type ArrayHeader struct {
	NumElems int

	// StreamedArrayHeader indicates that this message is the header message of
	// a streamed array. It is mutually exclusive with NumElems.
	StreamedArrayHeader bool
}

ArrayHeader represents the header sent preceding array elements in the RESP protocol. ArrayHeader only declares how many elements are in the array message.

ArrayHeader can also be used as the header of a streamed array, whose size is not known in advance, by setting StreamedArrayHeader instead of NumElems.

ArrayHeader will unmarshal a RESP2 nil array as an array of length zero.

func (ArrayHeader) MarshalRESP

func (h ArrayHeader) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*ArrayHeader) UnmarshalRESP

func (h *ArrayHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type AttributeHeader

type AttributeHeader struct {
	NumPairs int
}

AttributeHeader represents the header sent preceding attribute elements in the RESP protocol. AttributeHeader only declares how many elements are in the attribute message.

func (AttributeHeader) MarshalRESP

func (h AttributeHeader) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*AttributeHeader) UnmarshalRESP

func (h *AttributeHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type BigNumber

type BigNumber struct {
	I *big.Int
}

BigNumber represents the big number type in the RESP protocol. Marshaling a nil I value will cause a panic.

func (BigNumber) MarshalRESP

func (b BigNumber) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*BigNumber) UnmarshalRESP

func (b *BigNumber) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type BlobError

type BlobError struct {
	B []byte
}

BlobError represents the blob error type in the RESP protocol.

BlobError only represents an actual error message being read/written on the wire, it is separate from network or parsing errors.

func (BlobError) Error

func (e BlobError) Error() string

func (BlobError) MarshalRESP

func (e BlobError) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*BlobError) UnmarshalRESP

func (e *BlobError) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type BlobString

type BlobString struct {
	S string

	// StreamedStringHeader indicates that this message is the header message of
	// a streamed string. It is mutually exclusive with S.
	StreamedStringHeader bool
}

BlobString represents the blob string type in the RESP protocol using a go string.

BlobString can also be used as the header message of a streamed string. When used in that way it will be followed by one or more BlobStringChunk messages, ending in a BlobStringChunk with a zero length.

BlobStringBytes will unmarshal a nil RESP2 bulk string as an empty S value.

func (BlobString) MarshalRESP

func (b BlobString) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*BlobString) UnmarshalRESP

func (b *BlobString) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type BlobStringBytes

type BlobStringBytes struct {
	B []byte

	// StreamedStringHeader indicates that this message is the header message of
	// a streamed string. It is mutually exclusive with B.
	StreamedStringHeader bool
}

BlobStringBytes represents the blob string type in the RESP protocol using a go byte slice. A B value of nil is an empty string.

BlobStringBytes can also be used as the header message of a streamed string. When used in that way it will be followed by one or more BlobStringChunk messages, ending in a BlobStringChunk with a zero length.

BlobStringBytes will unmarshal a nil RESP2 bulk string as an empty B value.

func (BlobStringBytes) MarshalRESP

func (b BlobStringBytes) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*BlobStringBytes) UnmarshalRESP

func (b *BlobStringBytes) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type BlobStringWriter

type BlobStringWriter struct {
	LR resp.LenReader
}

BlobStringWriter represents a blob string in the RESP protocol.

BlobStringWriter only supports marshalling and will use the given LenReader to do so.

func (BlobStringWriter) MarshalRESP

func (b BlobStringWriter) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

type Boolean

type Boolean struct {
	B bool
}

Boolean represents the boolean type in the RESP protocol.

func (Boolean) MarshalRESP

func (b Boolean) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*Boolean) UnmarshalRESP

func (b *Boolean) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type Double

type Double struct {
	F float64
}

Double represents the double type in the RESP protocol.

func (Double) MarshalRESP

func (d Double) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*Double) UnmarshalRESP

func (d *Double) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type MapHeader

type MapHeader struct {
	NumPairs int

	// StreamedMapHeader indicates that this message is the header message of
	// a streamed map. It is mutually exclusive with NumPairs.
	StreamedMapHeader bool
}

MapHeader represents the header sent preceding map elements in the RESP protocol. MapHeader only declares how many elements are in the map message.

MapHeader can also be used as the header of a streamed array, whose size is not known in advance, by setting StreamedMapHeader instead of NumElems.

func (MapHeader) MarshalRESP

func (h MapHeader) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*MapHeader) UnmarshalRESP

func (h *MapHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type Null

type Null struct{}

Null represents the null type in the RESP protocol.

Null will always marshal to the RESP3 null type, but for convenience is also capable of unmarshaling the RESP2 null bulk string and null array values.

func (Null) MarshalRESP

func (Null) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*Null) UnmarshalRESP

func (*Null) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type Number

type Number struct {
	N int64
}

Number represents the number type in the RESP protocol.

func (Number) MarshalRESP

func (n Number) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*Number) UnmarshalRESP

func (n *Number) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type Prefix

type Prefix byte

Prefix enumerates the possible RESP3 types by enumerating the different prefix bytes a RESP3 message might start with.

var (
	// Simple type prefices.
	BlobStringPrefix     Prefix = '$'
	SimpleStringPrefix   Prefix = '+'
	SimpleErrorPrefix    Prefix = '-'
	NumberPrefix         Prefix = ':'
	NullPrefix           Prefix = '_'
	DoublePrefix         Prefix = ','
	BooleanPrefix        Prefix = '#'
	BlobErrorPrefix      Prefix = '!'
	VerbatimStringPrefix Prefix = '='
	BigNumberPrefix      Prefix = '('

	// Aggregated type prefices.
	ArrayHeaderPrefix     Prefix = '*'
	MapHeaderPrefix       Prefix = '%'
	SetHeaderPrefix       Prefix = '~'
	AttributeHeaderPrefix Prefix = '|'
	PushHeaderPrefix      Prefix = '>'

	// Streamed type prefices.
	StreamedAggregatedTypeEndPrefix Prefix = '.'
	StreamedStringChunkPrefix       Prefix = ';'
)

Enumeration of each of RESP3 prefices.

func (Prefix) String

func (p Prefix) String() string

type PushHeader

type PushHeader struct {
	NumElems int
}

PushHeader represents the header sent preceding push elements in the RESP protocol. PushHeader only declares how many elements are in the push message.

func (PushHeader) MarshalRESP

func (h PushHeader) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*PushHeader) UnmarshalRESP

func (h *PushHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type RawMessage

type RawMessage []byte

RawMessage is a raw encoded RESP message. When marshaling the exact bytes of the RawMessage will be written as-is. When unmarshaling the bytes of a single RESP message will be read into the RawMessage's bytes.

func (RawMessage) IsEmpty

func (rm RawMessage) IsEmpty() bool

IsEmpty returns true if the RawMessage is an aggregated type with zero elements.

func (RawMessage) IsNull

func (rm RawMessage) IsNull() bool

IsNull returns true if the contents of the RawMessage is a null RESP3 message, or a RESP2 bulk/array null message.

func (RawMessage) IsStreamedHeader

func (rm RawMessage) IsStreamedHeader() bool

IsStreamedHeader returns true if the RawMessage is the header of a streamed aggregated type or a streamed string.

func (RawMessage) MarshalRESP

func (rm RawMessage) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (RawMessage) UnmarshalInto

func (rm RawMessage) UnmarshalInto(rcv interface{}, o *resp.Opts) error

UnmarshalInto is a shortcut for wrapping this RawMessage in a resp.BufferedReader and unmarshaling that into the given receiver (which will be wrapped in an Any).

func (*RawMessage) UnmarshalRESP

func (rm *RawMessage) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type SetHeader

type SetHeader struct {
	NumElems int

	// StreamedSetHeader indicates that this message is the header message of
	// a streamed set. It is mutually exclusive with NumElems.
	StreamedSetHeader bool
}

SetHeader represents the header sent preceding set elements in the RESP protocol. SetHeader only declares how many elements are in the set message.

SetHeader can also be used as the header of a streamed array, whose size is not known in advance, by setting StreamedSetHeader instead of NumElems.

func (SetHeader) MarshalRESP

func (h SetHeader) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*SetHeader) UnmarshalRESP

func (h *SetHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type SimpleError

type SimpleError struct {
	S string
}

SimpleError represents the simple error type in the RESP protocol.

SimpleError represents an actual error message being read/written on the wire, it is separate from network or parsing errors.

func (SimpleError) Error

func (e SimpleError) Error() string

func (SimpleError) MarshalRESP

func (e SimpleError) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*SimpleError) UnmarshalRESP

func (e *SimpleError) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type SimpleString

type SimpleString struct {
	S string
}

SimpleString represents the simple string type in the RESP protocol.

func (SimpleString) MarshalRESP

func (ss SimpleString) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*SimpleString) UnmarshalRESP

func (ss *SimpleString) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type StreamedAggregatedElement

type StreamedAggregatedElement struct {
	// Receiver is unmarshaled into (see Unmarshal) when the message being read
	// isn't the streamed aggregated end type.
	Receiver interface{}

	// End is set to true when the message read isn't the streamed aggregated
	// type end message. If End is true then the Unmarshaler was not touched.
	End bool
}

StreamedAggregatedElement is a helper type used to unmarshal the elements of a streamed aggregated type (e.g. a streamed array) such that it is possible to check if the end of the stream has been reached.

func (*StreamedAggregatedElement) UnmarshalRESP

func (s *StreamedAggregatedElement) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type StreamedAggregatedTypeEnd

type StreamedAggregatedTypeEnd struct{}

StreamedAggregatedTypeEnd represents a streamed aggregated end type message in the RESP protocol.

func (StreamedAggregatedTypeEnd) MarshalRESP

func (s StreamedAggregatedTypeEnd) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*StreamedAggregatedTypeEnd) UnmarshalRESP

func (s *StreamedAggregatedTypeEnd) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type StreamedStringChunk

type StreamedStringChunk struct {
	S string
}

StreamedStringChunk represents a streamed string chunk message in the RESP protocol using a go string. An empty string indicates the end of the streamed string.

func (StreamedStringChunk) MarshalRESP

func (b StreamedStringChunk) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*StreamedStringChunk) UnmarshalRESP

func (b *StreamedStringChunk) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type StreamedStringChunkBytes

type StreamedStringChunkBytes struct {
	B []byte
}

StreamedStringChunkBytes represents a streamed string chunk message in the RESP protocol using a byte slice. A slice with length zero indicates the end of the streamed string.

func (StreamedStringChunkBytes) MarshalRESP

func (b StreamedStringChunkBytes) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*StreamedStringChunkBytes) UnmarshalRESP

func (b *StreamedStringChunkBytes) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type StreamedStringReader

type StreamedStringReader struct {
	W io.Writer
}

StreamedStringReader implements reading a streamed string RESP message off the wire and writing the string being streamed onto the given io.Writer.

UnmarshalRESP will block until the entire streamed string has been copied onto the given io.Writer.

func (*StreamedStringReader) UnmarshalRESP

func (r *StreamedStringReader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type StreamedStringWriter

type StreamedStringWriter struct {
	R io.Reader
}

StreamedStringWriter implements reading off of a given io.Reader and writing that data as a RESP streamed string message.

MarshalRESP will block until the given io.Reader has returned io.EOF or some other error.

func (StreamedStringWriter) MarshalRESP

func (sw StreamedStringWriter) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

type VerbatimString

type VerbatimString struct {
	S string

	// Format is a 3 character string describing the format that the verbatim
	// string is encoded in, e.g. "txt" or "mkd". If Format is not exactly 3
	// characters then MarshalRESP will error without writing anything.
	Format string
}

VerbatimString represents the verbatim string type in the RESP protocol using a go string.

func (VerbatimString) MarshalRESP

func (b VerbatimString) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*VerbatimString) UnmarshalRESP

func (b *VerbatimString) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

type VerbatimStringBytes

type VerbatimStringBytes struct {
	B []byte

	// Format is a 3 character string describing the format that the verbatim
	// string is encoded in, e.g. "txt" or "mkd". If Format is not exactly 3
	// characters then MarshalRESP will error without writing anything.
	Format []byte
}

VerbatimStringBytes represents the verbatim string type in the RESP protocol using a go byte slice. A B value of nil is an empty string.

func (VerbatimStringBytes) MarshalRESP

func (b VerbatimStringBytes) MarshalRESP(w io.Writer, o *resp.Opts) error

MarshalRESP implements the method for resp.Marshaler.

func (*VerbatimStringBytes) UnmarshalRESP

func (b *VerbatimStringBytes) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error

UnmarshalRESP implements the method for resp.Unmarshaler.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL