|
|
@ -19,7 +19,14 @@ type value interface {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func readValue(r io.Reader) (value, error) {
|
|
|
|
func readValue(r io.Reader) (value, error) {
|
|
|
|
br := bufio.NewReader(r)
|
|
|
|
var br *bufio.Reader
|
|
|
|
|
|
|
|
switch t := r.(type) {
|
|
|
|
|
|
|
|
case *bufio.Reader:
|
|
|
|
|
|
|
|
br = t
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
br = bufio.NewReader(r)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
line, err := br.ReadBytes('\n')
|
|
|
|
line, err := br.ReadBytes('\n')
|
|
|
|
switch err {
|
|
|
|
switch err {
|
|
|
|
case io.EOF:
|
|
|
|
case io.EOF:
|
|
|
@ -34,7 +41,7 @@ func readValue(r io.Reader) (value, error) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if len(line) < 3 {
|
|
|
|
if len(line) < 3 {
|
|
|
|
return nil, fmt.Errorf("unable to read redis protocol value: input is too small")
|
|
|
|
return nil, fmt.Errorf("unable to read redis protocol value: input %q is too small", line)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if line[len(line)-2] != '\r' {
|
|
|
|
if line[len(line)-2] != '\r' {
|
|
|
|
return nil, fmt.Errorf("unable to read redis protocol value: bad line terminator")
|
|
|
|
return nil, fmt.Errorf("unable to read redis protocol value: bad line terminator")
|
|
|
@ -49,6 +56,8 @@ func readValue(r io.Reader) (value, error) {
|
|
|
|
return readInteger(line[1:])
|
|
|
|
return readInteger(line[1:])
|
|
|
|
case start_bulkstring:
|
|
|
|
case start_bulkstring:
|
|
|
|
return readBulkString(line[1:], br)
|
|
|
|
return readBulkString(line[1:], br)
|
|
|
|
|
|
|
|
case start_array:
|
|
|
|
|
|
|
|
return readArray(line[1:], br)
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unable to read redis protocol value: illegal start character: %c", line[0])
|
|
|
|
return nil, fmt.Errorf("unable to read redis protocol value: illegal start character: %c", line[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -92,6 +101,7 @@ func readBulkString(prefix []byte, r io.Reader) (value, error) {
|
|
|
|
return nil, fmt.Errorf("unable to read bulkstring in redis protocol: bad prefix: %v", err)
|
|
|
|
return nil, fmt.Errorf("unable to read bulkstring in redis protocol: bad prefix: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
n += 2
|
|
|
|
b := make([]byte, n)
|
|
|
|
b := make([]byte, n)
|
|
|
|
n_read, err := r.Read(b)
|
|
|
|
n_read, err := r.Read(b)
|
|
|
|
switch err {
|
|
|
|
switch err {
|
|
|
@ -105,5 +115,30 @@ func readBulkString(prefix []byte, r io.Reader) (value, error) {
|
|
|
|
return nil, fmt.Errorf("unable to read bulkstring in redis protocol: read %d bytes, expected to read %d bytes", int64(n_read), n)
|
|
|
|
return nil, fmt.Errorf("unable to read bulkstring in redis protocol: read %d bytes, expected to read %d bytes", int64(n_read), n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return BulkString(b), nil
|
|
|
|
if len(b) < 2 {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to read bulkstring in redis protocol: input %q is too short", b)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return BulkString(b[:len(b)-2]), nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type Array []value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func readArray(prefix []byte, r *bufio.Reader) (value, error) {
|
|
|
|
|
|
|
|
n, err := strconv.ParseInt(string(prefix), 10, 64)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to read array in redis protocol: bad prefix: %v", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a := make(Array, n)
|
|
|
|
|
|
|
|
for i := int64(0); i < n; i++ {
|
|
|
|
|
|
|
|
v, err := readValue(r)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to read array value in redis protocol: %v", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
a[i] = v
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return a, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|