import "github.com/mediocregopher/radix/v4/resp/resp3"
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.
Code:
{ 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 }
Output:
streamed array begun read element with value 1 read element with value 2 read element with value 3 streamed array ended
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(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(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
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(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(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.
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 (h ArrayHeader) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (h *ArrayHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 (h AttributeHeader) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (h *AttributeHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 (b BigNumber) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (b *BigNumber) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 (e BlobError) Error() string
func (e BlobError) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (e *BlobError) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 (b BlobString) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (b *BlobString) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 (b BlobStringBytes) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (b *BlobStringBytes) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 (b BlobStringWriter) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
type Boolean struct { B bool }
Boolean represents the boolean type in the RESP protocol.
func (b Boolean) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (b *Boolean) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
type Double struct { F float64 }
Double represents the double type in the RESP protocol.
func (d Double) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (d *Double) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 (h MapHeader) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (h *MapHeader) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (*Null) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
type Number struct { N int64 }
Number represents the number type in the RESP protocol.
func (n Number) MarshalRESP(w io.Writer, o *resp.Opts) error
MarshalRESP implements the method for resp.Marshaler.
func (n *Number) UnmarshalRESP(br resp.BufferedReader, o *resp.Opts) error
UnmarshalRESP implements the method for resp.Unmarshaler.
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 = '