github.com/redis/go-redis/v9/internal/proto
No package summary is available.
Package
Files: 3. Third party imports: 0. Imports from organisation: 0. Tests: 0. Benchmarks: 0.
Constants
const Nil = RedisError("redis: nil") // nolint:errname
// redis resp protocol data type.
const (
RespStatus = '+' // +<string>\r\n
RespError = '-' // -<string>\r\n
RespString = '$' // $<length>\r\n<bytes>\r\n
RespInt = ':' // :<number>\r\n
RespNil = '_' // _\r\n
RespFloat = ',' // ,<floating-point-number>\r\n (golang float)
RespBool = '#' // true: #t\r\n false: #f\r\n
RespBlobError = '!' // !<length>\r\n<bytes>\r\n
RespVerbatim = '=' // =<length>\r\nFORMAT:<bytes>\r\n
RespBigInt = '(' // (<big number>\r\n
RespArray = '*' // *<len>\r\n... (same as resp2)
RespMap = '%' // %<len>\r\n(key)\r\n(value)\r\n... (golang map)
RespSet = '~' // ~<len>\r\n... (same as Array)
RespAttr = '|' // |<len>\r\n(key)\r\n(value)\r\n... + command reply
RespPush = '>' // ><len>\r\n... (same as Array)
)
Types
Reader
This type doesn't have documentation.
type Reader struct {
rd *bufio.Reader
}
RedisError
This type doesn't have documentation.
type RedisError string
Writer
This type doesn't have documentation.
type Writer struct {
writer
lenBuf []byte
numBuf []byte
}
writer
This type doesn't have documentation.
type writer interface {
io.Writer
io.ByteWriter
// WriteString implement io.StringWriter.
WriteString(s string) (n int, err error)
}
Functions
func IsNilReply
IsNilReply detects redis.Nil of RESP2.
func IsNilReply(line []byte) bool {
return len(line) == 3 &&
(line[0] == RespString || line[0] == RespArray) &&
line[1] == '-' && line[2] == '1'
}
Cognitive complexity: 0
, Cyclomatic complexity: 5
func NewReader
func NewReader(rd io.Reader) *Reader {
return &Reader{
rd: bufio.NewReader(rd),
}
}
Cognitive complexity: 1
, Cyclomatic complexity: 1
func NewWriter
func NewWriter(wr writer) *Writer {
return &Writer{
writer: wr,
lenBuf: make([]byte, 64),
numBuf: make([]byte, 64),
}
}
Cognitive complexity: 1
, Cyclomatic complexity: 1
func ParseErrorReply
func ParseErrorReply(line []byte) error {
return RedisError(line[1:])
}
Cognitive complexity: 0
, Cyclomatic complexity: 1
func Scan
Scan parses bytes b
to v
with appropriate type.
func Scan(b []byte, v interface{}) error {
switch v := v.(type) {
case nil:
return fmt.Errorf("redis: Scan(nil)")
case *string:
*v = util.BytesToString(b)
return nil
case *[]byte:
*v = b
return nil
case *int:
var err error
*v, err = util.Atoi(b)
return err
case *int8:
n, err := util.ParseInt(b, 10, 8)
if err != nil {
return err
}
*v = int8(n)
return nil
case *int16:
n, err := util.ParseInt(b, 10, 16)
if err != nil {
return err
}
*v = int16(n)
return nil
case *int32:
n, err := util.ParseInt(b, 10, 32)
if err != nil {
return err
}
*v = int32(n)
return nil
case *int64:
n, err := util.ParseInt(b, 10, 64)
if err != nil {
return err
}
*v = n
return nil
case *uint:
n, err := util.ParseUint(b, 10, 64)
if err != nil {
return err
}
*v = uint(n)
return nil
case *uint8:
n, err := util.ParseUint(b, 10, 8)
if err != nil {
return err
}
*v = uint8(n)
return nil
case *uint16:
n, err := util.ParseUint(b, 10, 16)
if err != nil {
return err
}
*v = uint16(n)
return nil
case *uint32:
n, err := util.ParseUint(b, 10, 32)
if err != nil {
return err
}
*v = uint32(n)
return nil
case *uint64:
n, err := util.ParseUint(b, 10, 64)
if err != nil {
return err
}
*v = n
return nil
case *float32:
n, err := util.ParseFloat(b, 32)
if err != nil {
return err
}
*v = float32(n)
return err
case *float64:
var err error
*v, err = util.ParseFloat(b, 64)
return err
case *bool:
*v = len(b) == 1 && b[0] == '1'
return nil
case *time.Time:
var err error
*v, err = time.Parse(time.RFC3339Nano, util.BytesToString(b))
return err
case *time.Duration:
n, err := util.ParseInt(b, 10, 64)
if err != nil {
return err
}
*v = time.Duration(n)
return nil
case encoding.BinaryUnmarshaler:
return v.UnmarshalBinary(b)
case *net.IP:
*v = b
return nil
default:
return fmt.Errorf(
"redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v)
}
}
Cognitive complexity: 45
, Cyclomatic complexity: 34
func ScanSlice
func ScanSlice(data []string, slice interface{}) error {
v := reflect.ValueOf(slice)
if !v.IsValid() {
return fmt.Errorf("redis: ScanSlice(nil)")
}
if v.Kind() != reflect.Ptr {
return fmt.Errorf("redis: ScanSlice(non-pointer %T)", slice)
}
v = v.Elem()
if v.Kind() != reflect.Slice {
return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice)
}
next := makeSliceNextElemFunc(v)
for i, s := range data {
elem := next()
if err := Scan([]byte(s), elem.Addr().Interface()); err != nil {
err = fmt.Errorf("redis: ScanSlice index=%d value=%q failed: %w", i, s, err)
return err
}
}
return nil
}
Cognitive complexity: 12
, Cyclomatic complexity: 6
func (*Reader) Buffered
func (r *Reader) Buffered() int {
return r.rd.Buffered()
}
Cognitive complexity: 0
, Cyclomatic complexity: 1
func (*Reader) Discard
Discard the data represented by line.
func (r *Reader) Discard(line []byte) (err error) {
if len(line) == 0 {
return errors.New("redis: invalid line")
}
switch line[0] {
case RespStatus, RespError, RespInt, RespNil, RespFloat, RespBool, RespBigInt:
return nil
}
n, err := replyLen(line)
if err != nil && err != Nil {
return err
}
switch line[0] {
case RespBlobError, RespString, RespVerbatim:
// +\r\n
_, err = r.rd.Discard(n + 2)
return err
case RespArray, RespSet, RespPush:
for i := 0; i < n; i++ {
if err = r.DiscardNext(); err != nil {
return err
}
}
return nil
case RespMap, RespAttr:
// Read key & value.
for i := 0; i < n*2; i++ {
if err = r.DiscardNext(); err != nil {
return err
}
}
return nil
}
return fmt.Errorf("redis: can't parse %.100q", line)
}
Cognitive complexity: 20
, Cyclomatic complexity: 14
func (*Reader) DiscardNext
DiscardNext read and discard the data represented by the next line.
func (r *Reader) DiscardNext() error {
line, err := r.readLine()
if err != nil {
return err
}
return r.Discard(line)
}
Cognitive complexity: 2
, Cyclomatic complexity: 2
func (*Reader) Peek
func (r *Reader) Peek(n int) ([]byte, error) {
return r.rd.Peek(n)
}
Cognitive complexity: 0
, Cyclomatic complexity: 1
func (*Reader) PeekReplyType
PeekReplyType returns the data type of the next response without advancing the Reader, and discard the attribute type.
func (r *Reader) PeekReplyType() (byte, error) {
b, err := r.rd.Peek(1)
if err != nil {
return 0, err
}
if b[0] == RespAttr {
if err = r.DiscardNext(); err != nil {
return 0, err
}
return r.PeekReplyType()
}
return b[0], nil
}
Cognitive complexity: 6
, Cyclomatic complexity: 4
func (*Reader) ReadArrayLen
ReadArrayLen Read and return the length of the array.
func (r *Reader) ReadArrayLen() (int, error) {
line, err := r.ReadLine()
if err != nil {
return 0, err
}
switch line[0] {
case RespArray, RespSet, RespPush:
return replyLen(line)
default:
return 0, fmt.Errorf("redis: can't parse array/set/push reply: %.100q", line)
}
}
Cognitive complexity: 5
, Cyclomatic complexity: 4
func (*Reader) ReadBool
func (r *Reader) ReadBool() (bool, error) {
s, err := r.ReadString()
if err != nil {
return false, err
}
return s == "OK" || s == "1" || s == "true", nil
}
Cognitive complexity: 2
, Cyclomatic complexity: 4
func (*Reader) ReadFixedArrayLen
ReadFixedArrayLen read fixed array length.
func (r *Reader) ReadFixedArrayLen(fixedLen int) error {
n, err := r.ReadArrayLen()
if err != nil {
return err
}
if n != fixedLen {
return fmt.Errorf("redis: got %d elements in the array, wanted %d", n, fixedLen)
}
return nil
}
Cognitive complexity: 4
, Cyclomatic complexity: 3
func (*Reader) ReadFixedMapLen
ReadFixedMapLen reads fixed map length.
func (r *Reader) ReadFixedMapLen(fixedLen int) error {
n, err := r.ReadMapLen()
if err != nil {
return err
}
if n != fixedLen {
return fmt.Errorf("redis: got %d elements in the map, wanted %d", n, fixedLen)
}
return nil
}
Cognitive complexity: 4
, Cyclomatic complexity: 3
func (*Reader) ReadFloat
func (r *Reader) ReadFloat() (float64, error) {
line, err := r.ReadLine()
if err != nil {
return 0, err
}
switch line[0] {
case RespFloat:
return r.readFloat(line)
case RespStatus:
return strconv.ParseFloat(string(line[1:]), 64)
case RespString:
s, err := r.readStringReply(line)
if err != nil {
return 0, err
}
return strconv.ParseFloat(s, 64)
}
return 0, fmt.Errorf("redis: can't parse float reply: %.100q", line)
}
Cognitive complexity: 9
, Cyclomatic complexity: 7
func (*Reader) ReadInt
func (r *Reader) ReadInt() (int64, error) {
line, err := r.ReadLine()
if err != nil {
return 0, err
}
switch line[0] {
case RespInt, RespStatus:
return util.ParseInt(line[1:], 10, 64)
case RespString:
s, err := r.readStringReply(line)
if err != nil {
return 0, err
}
return util.ParseInt([]byte(s), 10, 64)
case RespBigInt:
b, err := r.readBigInt(line)
if err != nil {
return 0, err
}
if !b.IsInt64() {
return 0, fmt.Errorf("bigInt(%s) value out of range", b.String())
}
return b.Int64(), nil
}
return 0, fmt.Errorf("redis: can't parse int reply: %.100q", line)
}
Cognitive complexity: 13
, Cyclomatic complexity: 9
func (*Reader) ReadLine
ReadLine Return a valid reply, it will check the protocol or redis error, and discard the attribute type.
func (r *Reader) ReadLine() ([]byte, error) {
line, err := r.readLine()
if err != nil {
return nil, err
}
switch line[0] {
case RespError:
return nil, ParseErrorReply(line)
case RespNil:
return nil, Nil
case RespBlobError:
var blobErr string
blobErr, err = r.readStringReply(line)
if err == nil {
err = RedisError(blobErr)
}
return nil, err
case RespAttr:
if err = r.Discard(line); err != nil {
return nil, err
}
return r.ReadLine()
}
// Compatible with RESP2
if IsNilReply(line) {
return nil, Nil
}
return line, nil
}
Cognitive complexity: 14
, Cyclomatic complexity: 10
func (*Reader) ReadMapLen
ReadMapLen reads the length of the map type. If responding to the array type (RespArray/RespSet/RespPush), it must be a multiple of 2 and return n/2. Other types will return an error.
func (r *Reader) ReadMapLen() (int, error) {
line, err := r.ReadLine()
if err != nil {
return 0, err
}
switch line[0] {
case RespMap:
return replyLen(line)
case RespArray, RespSet, RespPush:
// Some commands and RESP2 protocol may respond to array types.
n, err := replyLen(line)
if err != nil {
return 0, err
}
if n%2 != 0 {
return 0, fmt.Errorf("redis: the length of the array must be a multiple of 2, got: %d", n)
}
return n / 2, nil
default:
return 0, fmt.Errorf("redis: can't parse map reply: %.100q", line)
}
}
Cognitive complexity: 10
, Cyclomatic complexity: 7
func (*Reader) ReadReply
func (r *Reader) ReadReply() (interface{}, error) {
line, err := r.ReadLine()
if err != nil {
return nil, err
}
switch line[0] {
case RespStatus:
return string(line[1:]), nil
case RespInt:
return util.ParseInt(line[1:], 10, 64)
case RespFloat:
return r.readFloat(line)
case RespBool:
return r.readBool(line)
case RespBigInt:
return r.readBigInt(line)
case RespString:
return r.readStringReply(line)
case RespVerbatim:
return r.readVerb(line)
case RespArray, RespSet, RespPush:
return r.readSlice(line)
case RespMap:
return r.readMap(line)
}
return nil, fmt.Errorf("redis: can't parse %.100q", line)
}
Cognitive complexity: 14
, Cyclomatic complexity: 12
func (*Reader) ReadSlice
func (r *Reader) ReadSlice() ([]interface{}, error) {
line, err := r.ReadLine()
if err != nil {
return nil, err
}
return r.readSlice(line)
}
Cognitive complexity: 3
, Cyclomatic complexity: 2
func (*Reader) ReadString
func (r *Reader) ReadString() (string, error) {
line, err := r.ReadLine()
if err != nil {
return "", err
}
switch line[0] {
case RespStatus, RespInt, RespFloat:
return string(line[1:]), nil
case RespString:
return r.readStringReply(line)
case RespBool:
b, err := r.readBool(line)
return strconv.FormatBool(b), err
case RespVerbatim:
return r.readVerb(line)
case RespBigInt:
b, err := r.readBigInt(line)
if err != nil {
return "", err
}
return b.String(), nil
}
return "", fmt.Errorf("redis: can't parse reply=%.100q reading string", line)
}
Cognitive complexity: 11
, Cyclomatic complexity: 9
func (*Reader) ReadUint
func (r *Reader) ReadUint() (uint64, error) {
line, err := r.ReadLine()
if err != nil {
return 0, err
}
switch line[0] {
case RespInt, RespStatus:
return util.ParseUint(line[1:], 10, 64)
case RespString:
s, err := r.readStringReply(line)
if err != nil {
return 0, err
}
return util.ParseUint([]byte(s), 10, 64)
case RespBigInt:
b, err := r.readBigInt(line)
if err != nil {
return 0, err
}
if !b.IsUint64() {
return 0, fmt.Errorf("bigInt(%s) value out of range", b.String())
}
return b.Uint64(), nil
}
return 0, fmt.Errorf("redis: can't parse uint reply: %.100q", line)
}
Cognitive complexity: 13
, Cyclomatic complexity: 9
func (*Reader) Reset
func (r *Reader) Reset(rd io.Reader) {
r.rd.Reset(rd)
}
Cognitive complexity: 0
, Cyclomatic complexity: 1
func (*Writer) WriteArg
func (w *Writer) WriteArg(v interface{}) error {
switch v := v.(type) {
case nil:
return w.string("")
case string:
return w.string(v)
case *string:
return w.string(*v)
case []byte:
return w.bytes(v)
case int:
return w.int(int64(v))
case *int:
return w.int(int64(*v))
case int8:
return w.int(int64(v))
case *int8:
return w.int(int64(*v))
case int16:
return w.int(int64(v))
case *int16:
return w.int(int64(*v))
case int32:
return w.int(int64(v))
case *int32:
return w.int(int64(*v))
case int64:
return w.int(v)
case *int64:
return w.int(*v)
case uint:
return w.uint(uint64(v))
case *uint:
return w.uint(uint64(*v))
case uint8:
return w.uint(uint64(v))
case *uint8:
return w.uint(uint64(*v))
case uint16:
return w.uint(uint64(v))
case *uint16:
return w.uint(uint64(*v))
case uint32:
return w.uint(uint64(v))
case *uint32:
return w.uint(uint64(*v))
case uint64:
return w.uint(v)
case *uint64:
return w.uint(*v)
case float32:
return w.float(float64(v))
case *float32:
return w.float(float64(*v))
case float64:
return w.float(v)
case *float64:
return w.float(*v)
case bool:
if v {
return w.int(1)
}
return w.int(0)
case *bool:
if *v {
return w.int(1)
}
return w.int(0)
case time.Time:
w.numBuf = v.AppendFormat(w.numBuf[:0], time.RFC3339Nano)
return w.bytes(w.numBuf)
case time.Duration:
return w.int(v.Nanoseconds())
case encoding.BinaryMarshaler:
b, err := v.MarshalBinary()
if err != nil {
return err
}
return w.bytes(b)
case net.IP:
return w.bytes(v)
default:
return fmt.Errorf(
"redis: can't marshal %T (implement encoding.BinaryMarshaler)", v)
}
}
Cognitive complexity: 43
, Cyclomatic complexity: 39
func (*Writer) WriteArgs
func (w *Writer) WriteArgs(args []interface{}) error {
if err := w.WriteByte(RespArray); err != nil {
return err
}
if err := w.writeLen(len(args)); err != nil {
return err
}
for _, arg := range args {
if err := w.WriteArg(arg); err != nil {
return err
}
}
return nil
}
Cognitive complexity: 10
, Cyclomatic complexity: 5
func (RedisError) Error
func (e RedisError) Error() string { return string(e) }
Cognitive complexity: 0
, Cyclomatic complexity: 1
func (RedisError) RedisError
func (RedisError) RedisError() {}
Cognitive complexity: 0
, Cyclomatic complexity: 1
Private functions
func makeSliceNextElemFunc
makeSliceNextElemFunc (v reflect.Value) func() reflect.Value
References: reflect.Append, reflect.New, reflect.Ptr, reflect.Value, reflect.Zero.
func replyLen
replyLen (line []byte) (int, error)
References: fmt.Errorf, util.Atoi.
func readBigInt
readBigInt (line []byte) (*big.Int, error)
References: big.Int, fmt.Errorf.
func readBool
readBool (line []byte) (bool, error)
References: fmt.Errorf.
func readFloat
readFloat (line []byte) (float64, error)
References: math.Inf, math.NaN, strconv.ParseFloat.
func readLine
readLine returns an error if:
- there is a pending read error;
- or line does not end with \r\n.
readLine () ([]byte, error)
References: bufio.ErrBufferFull, fmt.Errorf.
func readMap
readMap (line []byte) (map[interface{}]interface{}, error)
func readSlice
readSlice (line []byte) ([]interface{}, error)
func readStringReply
readStringReply (line []byte) (string, error)
References: io.ReadFull, util.BytesToString.
func readVerb
readVerb (line []byte) (string, error)
References: fmt.Errorf.
func bytes
bytes (b []byte) error
func crlf
crlf () error
func float
float (f float64) error
References: strconv.AppendFloat.
func int
int (n int64) error
References: strconv.AppendInt.
func string
string (s string) error
References: util.StringToBytes.
func uint
uint (n uint64) error
References: strconv.AppendUint.
func writeLen
writeLen (n int) error
References: strconv.AppendUint.
Tests
Files: 4. Third party imports: 2. Imports from organisation: 0. Tests: 2. Benchmarks: 16.
Vars
var _ = Describe("ScanSlice", func() {
data := []string{
`{"ID":-1,"Name":"Back Yu"}`,
`{"ID":1,"Name":"szyhf"}`,
}
It("[]testScanSliceStruct", func() {
var slice []testScanSliceStruct
err := proto.ScanSlice(data, &slice)
Expect(err).NotTo(HaveOccurred())
Expect(slice).To(Equal([]testScanSliceStruct{
{-1, "Back Yu"},
{1, "szyhf"},
}))
})
It("var testContainer []*testScanSliceStruct", func() {
var slice []*testScanSliceStruct
err := proto.ScanSlice(data, &slice)
Expect(err).NotTo(HaveOccurred())
Expect(slice).To(Equal([]*testScanSliceStruct{
{-1, "Back Yu"},
{1, "szyhf"},
}))
})
})
var buf *bytes.Buffer
var slice []testScanSliceStruct
var wr *proto.Writer
Types
MyType
This type doesn't have documentation.
type MyType struct{}
discard
This type doesn't have documentation.
type discard struct{}
testScanSliceStruct
This type doesn't have documentation.
type testScanSliceStruct struct {
ID int
Name string
}