func (r *Resp) Str() (string, error) {
	b, err := r.Bytes()
	if err != nil {
		return "", err
	}
	return string(b), nil
}
Str is a wrapper around Bytes which returns the result as a string instead of
a byte slice
package resp
import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net"
	"reflect"
	"strconv"
	"strings"
)
var (
	delim    = []byte{'\r', '\n'}
	delimEnd = delim[len(delim)-1]
)
type RespType int
const (
	SimpleStr RespType = 1 << iota
	BulkStr
	IOErr
	AppErr
	Int
	Array
	Nil
	Str = SimpleStr | BulkStr
	Err = IOErr | AppErr
)
var (
	simpleStrPrefix = []byte{'+'}
	errPrefix       = []byte{'-'}
	intPrefix       = []byte{':'}
	bulkStrPrefix   = []byte{'$'}
	arrayPrefix     = []byte{'*'}
	nilFormatted    = []byte("$-1\r\n")
)
var (
	errBadType  = errors.New("wrong type")
	errParse    = errors.New("parse error")
	errNotStr   = errors.New("could not convert to string")
	errNotInt   = errors.New("could not convert to int")
	errNotArray = errors.New("could not convert to array")
)
type Resp struct {
	Typ RespType
	Val interface{}
	Err error
}
func NewResp(v interface{}) *Resp {
	r := format(v, false)
	return &r
}
func NewRespSimple(s string) *Resp {
	return &Resp{
		Typ: SimpleStr,
		Val: []byte(s),
	}
}
func NewRespFlattenedStrings(v interface{}) *Resp {
	fv := flatten(v)
	r := format(fv, true)
	return &r
}
func NewRespIOErr(err error) *Resp {
	r := NewResp(err)
	r.Typ = IOErr
	return r
}
func NewRespErr(s string) *Resp {
	err := fmt.Errorf("ERR %v", s)
	return NewResp(err)
}
type RespReader struct {
	r *bufio.Reader
}
func NewRespReader(r io.Reader) *RespReader {
	br, ok := r.(*bufio.Reader)
	if !ok {
		br = bufio.NewReader(r)
	}
	return &RespReader{br}
}
func (rr *RespReader) Read() *Resp {
	res, err := bufioReadResp(rr.r)
	if err != nil {
		res = Resp{Typ: IOErr, Val: err, Err: err}
	}
	return &res
}
func bufioReadResp(r *bufio.Reader) (Resp, error) {
	b, err := r.Peek(1)
	if err != nil {
		return Resp{}, err
	}
	switch b[0] {
	case simpleStrPrefix[0]:
		return readSimpleStr(r)
	case errPrefix[0]:
		return readError(r)
	case intPrefix[0]:
		return readInt(r)
	case bulkStrPrefix[0]:
		return readBulkStr(r)
	case arrayPrefix[0]:
		return readArray(r)
	default:
		return Resp{}, errBadType
	}
}
func readSimpleStr(r *bufio.Reader) (Resp, error) {
	b, err := r.ReadBytes(delimEnd)
	if err != nil {
		return Resp{}, err
	}
	return Resp{Typ: SimpleStr, Val: b[1 : len(b)-2]}, nil
}
func readError(r *bufio.Reader) (Resp, error) {
	b, err := r.ReadBytes(delimEnd)
	if err != nil {
		return Resp{}, err
	}
	err = errors.New(string(b[1 : len(b)-2]))
	return Resp{Typ: AppErr, Val: err, Err: err}, nil
}
func readInt(r *bufio.Reader) (Resp, error) {
	b, err := r.ReadBytes(delimEnd)
	if err != nil {
		return Resp{}, err
	}
	i, err := strconv.ParseInt(string(b[1:len(b)-2]), 10, 64)
	if err != nil {
		return Resp{}, errParse
	}
	return Resp{Typ: Int, Val: i}, nil
}
func readBulkStr(r *bufio.Reader) (Resp, error) {
	b, err := r.ReadBytes(delimEnd)
	if err != nil {
		return Resp{}, err
	}
	size, err := strconv.ParseInt(string(b[1:len(b)-2]), 10, 64)
	if err != nil {
		return Resp{}, errParse
	}
	if size < 0 {
		return Resp{Typ: Nil}, nil
	}
	total := make([]byte, size)
	b2 := total
	var n int
	for len(b2) > 0 {
		n, err = r.Read(b2)
		if err != nil {
			return Resp{}, err
		}
		b2 = b2[n:]
	}
	trail := make([]byte, 2)
	for i := 0; i < 2; i++ {
		c, err := r.ReadByte()
		if err != nil {
			return Resp{}, err
		}
		trail[i] = c
	}
	return Resp{Typ: BulkStr, Val: total}, nil
}
func readArray(r *bufio.Reader) (Resp, error) {
	b, err := r.ReadBytes(delimEnd)
	if err != nil {
		return Resp{}, err
	}
	size, err := strconv.ParseInt(string(b[1:len(b)-2]), 10, 64)
	if err != nil {
		return Resp{}, errParse
	}
	if size < 0 {
		return Resp{Typ: Nil}, nil
	}
	arr := make([]Resp, size)
	for i := range arr {
		m, err := bufioReadResp(r)
		if err != nil {
			return Resp{}, err
		}
		arr[i] = m
	}
	return Resp{Typ: Array, Val: arr}, nil
}
func (r *Resp) IsType(t RespType) bool {
	return r.Typ&t > 0
}
func (r *Resp) WriteTo(w io.Writer) (int64, error) {
	if r.Typ == SimpleStr {
		s := r.Val.([]byte)
		b := append(make([]byte, 0, len(s)+3), simpleStrPrefix...)
		b = append(b, s...)
		b = append(b, delim...)
		written, err := w.Write(b)
		return int64(written), err
	}
	return writeTo(w, nil, r.Val, false, false)
}
func (r *Resp) Bytes() ([]byte, error) {
	if r.Err != nil {
		return nil, r.Err
	} else if !r.IsType(Str) {
		return nil, errBadType
	}
	if b, ok := r.Val.([]byte); ok {
		return b, nil
	}
	return nil, errNotStr
}