func (wr *Writer) WriteValue(v Value) error {
	b, err := v.MarshalRESP()
	if err != nil {
		return err
	}
	_, err = wr.wr.Write(b)
	return nil
}
WriteValue writes a RESP Value.
package resp
import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"strconv"
)
const bufsz = 4096
type Type byte
const (
	SimpleString Type = '+'
	Error        Type = '-'
	Integer      Type = ':'
	BulkString   Type = '$'
	Array        Type = '*'
)
func (t Type) String() string {
	switch t {
	default:
		return "Unknown"
	case '+':
		return "SimpleString"
	case '-':
		return "Error"
	case ':':
		return "Integer"
	case '$':
		return "BulkString"
	case '*':
		return "Array"
	}
}
type Value struct {
	typ     Type
	integer int
	str     []byte
	array   []Value
	null    bool
}
func (v Value) Integer() int {
	switch v.typ {
	default:
		n, _ := strconv.ParseInt(v.String(), 10, 64)
		return int(n)
	case ':':
		return v.integer
	}
}
func (v Value) String() string {
	if v.typ == '$' {
		return string(v.str)
	}
	switch v.typ {
	case '+', '-':
		return string(v.str)
	case ':':
		return strconv.FormatInt(int64(v.integer), 10)
	case '*':
		return fmt.Sprintf("%v", v.array)
	}
	return ""
}
func (v Value) Bytes() []byte {
	switch v.typ {
	default:
		return []byte(v.String())
	case '$', '+', '-':
		return v.str
	}
}
func (v Value) Float() float64 {
	switch v.typ {
	default:
		f, _ := strconv.ParseFloat(v.String(), 64)
		return f
	case ':':
		return float64(v.integer)
	}
}
func (v Value) IsNull() bool {
	return v.null
}
func (v Value) Bool() bool {
	return v.Integer() != 0
}
func (v Value) Error() error {
	switch v.typ {
	case '-':
		return errors.New(string(v.str))
	}
	return nil
}
func (v Value) Array() []Value {
	if v.typ == '*' && !v.null {
		return v.array
	}
	return nil
}
func (v Value) Type() Type {
	return v.typ
}
func marshalSimpleRESP(typ Type, b []byte) ([]byte, error) {
	bb := make([]byte, 3+len(b))
	bb[0] = byte(typ)
	copy(bb[1:], b)
	bb[1+len(b)+0] = '\r'
	bb[1+len(b)+1] = '\n'
	return bb, nil
}
func marshalBulkRESP(v Value) ([]byte, error) {
	if v.null {
		return []byte("$-1\r\n"), nil
	}
	szb := []byte(strconv.FormatInt(int64(len(v.str)), 10))
	bb := make([]byte, 5+len(szb)+len(v.str))
	bb[0] = '$'
	copy(bb[1:], szb)
	bb[1+len(szb)+0] = '\r'
	bb[1+len(szb)+1] = '\n'
	copy(bb[1+len(szb)+2:], v.str)
	bb[1+len(szb)+2+len(v.str)+0] = '\r'
	bb[1+len(szb)+2+len(v.str)+1] = '\n'
	return bb, nil
}
func marshalArrayRESP(v Value) ([]byte, error) {
	if v.null {
		return []byte("*-1\r\n"), nil
	}
	szb := []byte(strconv.FormatInt(int64(len(v.array)), 10))
	var buf bytes.Buffer
	buf.Grow(3 + len(szb) + 16*len(v.array))  
	buf.WriteByte('*')
	buf.Write(szb)
	buf.WriteByte('\r')
	buf.WriteByte('\n')
	for i := 0; i < len(v.array); i++ {
		data, err := v.array[i].MarshalRESP()
		if err != nil {
			return nil, err
		}
		buf.Write(data)
	}
	return buf.Bytes(), nil
}
func marshalAnyRESP(v Value) ([]byte, error) {
	switch v.typ {
	default:
		if v.typ == 0 && v.null {
			return []byte("$-1\r\n"), nil
		}
		return nil, errors.New("unknown resp type encountered")
	case '-', '+':
		return marshalSimpleRESP(v.typ, v.str)
	case ':':
		return marshalSimpleRESP(v.typ, []byte(strconv.FormatInt(int64(v.integer), 10)))
	case '$':
		return marshalBulkRESP(v)
	case '*':
		return marshalArrayRESP(v)
	}
}
func (v Value) Equals(value Value) bool {
	data1, err := v.MarshalRESP()
	if err != nil {
		return false
	}
	data2, err := value.MarshalRESP()
	if err != nil {
		return false
	}
	return string(data1) == string(data2)
}
func (v Value) MarshalRESP() ([]byte, error) {
	return marshalAnyRESP(v)
}
var nullValue = Value{null: true}
type errProtocol struct{ msg string }
func (err errProtocol) Error() string {
	return "Protocol error: " + err.msg
}
type Reader struct {
	rd *bufio.Reader
}
func NewReader(rd io.Reader) *Reader {
	r := &Reader{rd: bufio.NewReader(rd)}
	return r
}
func (rd *Reader) ReadValue() (value Value, n int, err error) {
	value, _, n, err = rd.readValue(false, false)
	return
}
func (rd *Reader) ReadMultiBulk() (value Value, telnet bool, n int, err error) {
	return rd.readValue(true, false)
}
func (rd *Reader) readValue(multibulk, child bool) (val Value, telnet bool, n int, err error) {
	var rn int
	var c byte
	c, err = rd.rd.ReadByte()
	if err != nil {
		return nullValue, false, n, err
	}
	n++
	if c == '*' {
		val, rn, err = rd.readArrayValue(multibulk)
	} else if multibulk && !child {
		telnet = true
	} else {
		switch c {
		default:
			if multibulk && child {
				return nullValue, telnet, n, &errProtocol{"expected '$', got '" + string(c) + "'"}
			}
			if child {
				return nullValue, telnet, n, &errProtocol{"unknown first byte"}
			}
			telnet = true
		case '-', '+':
			val, rn, err = rd.readSimpleValue(c)
		case ':':
			val, rn, err = rd.readIntegerValue()
		case '$':
			val, rn, err = rd.readBulkValue()
		}
	}
	if telnet {
		n--
		rd.rd.UnreadByte()
		val, rn, err = rd.readTelnetMultiBulk()
		if err == nil {
			telnet = true
		}
	}
	n += rn
	if err == io.EOF {
		return nullValue, telnet, n, io.ErrUnexpectedEOF
	}
	return val, telnet, n, err
}
func (rd *Reader) readTelnetMultiBulk() (v Value, n int, err error) {
	values := make([]Value, 0, 8)
	var c byte
	var bline []byte
	var quote, mustspace bool
	for {
		c, err = rd.rd.ReadByte()
		if err != nil {
			return nullValue, n, err
		}
		n += 1
		if c == '\n' {
			if len(bline) > 0 && bline[len(bline)-1] == '\r' {
				bline = bline[:len(bline)-1]
			}
			break
		}
		if mustspace && c != ' ' {
			return nullValue, n, &errProtocol{"unbalanced quotes in request"}
		}
		if c == ' ' {
			if quote {
				bline = append(bline, c)
			} else {
				values = append(values, Value{typ: '$', str: bline})
				bline = nil
			}
		} else if c == '"' {
			if quote {
				mustspace = true
			} else {
				if len(bline) > 0 {
					return nullValue, n, &errProtocol{"unbalanced quotes in request"}
				}
				quote = true
			}
		} else {
			bline = append(bline, c)
		}
	}
	if quote {
		return nullValue, n, &errProtocol{"unbalanced quotes in request"}
	}
	if len(bline) > 0 {
		values = append(values, Value{typ: '$', str: bline})
	}
	return Value{typ: '*', array: values}, n, nil
}
func (rd *Reader) readSimpleValue(typ byte) (val Value, n int, err error) {
	var line []byte
	line, n, err = rd.readLine()
	if err != nil {
		return nullValue, n, err
	}
	return Value{typ: Type(typ), str: line}, n, nil
}
func (rd *Reader) readLine() (line []byte, n int, err error) {
	for {
		b, err := rd.rd.ReadBytes('\n')
		if err != nil {
			return nil, 0, err
		}
		n += len(b)
		line = append(line, b...)
		if len(line) >= 2 && line[len(line)-2] == '\r' {
			break
		}
	}
	return line[:len(line)-2], n, nil
}
func (rd *Reader) readBulkValue() (val Value, n int, err error) {
	var rn int
	var l int
	l, rn, err = rd.readInt()
	n += rn
	if err != nil {
		if _, ok := err.(*errProtocol); ok {
			return nullValue, n, &errProtocol{"invalid bulk length"}
		}
		return nullValue, n, err
	}
	if l < 0 {
		return Value{typ: '$', null: true}, n, nil
	}
	if l > 512*1024*1024 {
		return nullValue, n, &errProtocol{"invalid bulk length"}
	}
	b := make([]byte, l+2)
	rn, err = io.ReadFull(rd.rd, b)
	n += rn
	if err != nil {
		return nullValue, n, err
	}
	if b[l] != '\r' || b[l+1] != '\n' {
		return nullValue, n, &errProtocol{"invalid bulk line ending"}
	}
	return Value{typ: '$', str: b[:l]}, n, nil
}
func (rd *Reader) readArrayValue(multibulk bool) (val Value, n int, err error) {
	var rn int
	var l int
	l, rn, err = rd.readInt()
	n += rn
	if err != nil || l > 1024*1024 {
		if _, ok := err.(*errProtocol); ok {
			if multibulk {
				return nullValue, n, &errProtocol{"invalid multibulk length"}
			}
			return nullValue, n, &errProtocol{"invalid array length"}
		}
		return nullValue, n, err
	}
	if l < 0 {
		return Value{typ: '*', null: true}, n, nil
	}
	var aval Value
	vals := make([]Value, l)
	for i := 0; i < l; i++ {
		aval, _, rn, err = rd.readValue(multibulk, true)
		n += rn
		if err != nil {
			return nullValue, n, err
		}
		vals[i] = aval
	}
	return Value{typ: '*', array: vals}, n, nil
}
func (rd *Reader) readIntegerValue() (val Value, n int, err error) {
	var l int
	l, n, err = rd.readInt()
	if err != nil {
		if _, ok := err.(*errProtocol); ok {
			return nullValue, n, &errProtocol{"invalid integer"}
		}
		return nullValue, n, err
	}
	return Value{typ: ':', integer: l}, n, nil
}
func (rd *Reader) readInt() (x int, n int, err error) {
	line, n, err := rd.readLine()
	if err != nil {
		return 0, 0, err
	}
	i64, err := strconv.ParseInt(string(line), 10, 64)
	if err != nil {
		return 0, n, err
	}
	return int(i64), n, nil
}
func AnyValue(v interface{}) Value {
	switch v := v.(type) {
	default:
		return StringValue(fmt.Sprintf("%v", v))
	case nil:
		return NullValue()
	case int:
		return IntegerValue(int(v))
	case uint:
		return IntegerValue(int(v))
	case int8:
		return IntegerValue(int(v))
	case uint8:
		return IntegerValue(int(v))
	case int16:
		return IntegerValue(int(v))
	case uint16:
		return IntegerValue(int(v))
	case int32:
		return IntegerValue(int(v))
	case uint32:
		return IntegerValue(int(v))
	case int64:
		return IntegerValue(int(v))
	case uint64:
		return IntegerValue(int(v))
	case bool:
		return BoolValue(v)
	case float32:
		return FloatValue(float64(v))
	case float64:
		return FloatValue(float64(v))
	case []byte:
		return BytesValue(v)
	case string:
		return StringValue(v)
	}
}
func SimpleStringValue(s string) Value { return Value{typ: '+', str: []byte(formSingleLine(s))} }
func BytesValue(b []byte) Value { return Value{typ: '$', str: b} }
func StringValue(s string) Value { return Value{typ: '$', str: []byte(s)} }
func NullValue() Value { return Value{typ: '$', null: true} }
func ErrorValue(err error) Value {
	if err == nil {
		return Value{typ: '-'}
	}
	return Value{typ: '-', str: []byte(err.Error())}
}
func IntegerValue(i int) Value { return Value{typ: ':', integer: i} }
func BoolValue(t bool) Value {
	if t {
		return Value{typ: ':', integer: 1}
	}
	return Value{typ: ':', integer: 0}
}
func FloatValue(f float64) Value { return StringValue(strconv.FormatFloat(f, 'f', -1, 64)) }
func ArrayValue(vals []Value) Value { return Value{typ: '*', array: vals} }
func formSingleLine(s string) string {
	bs1 := []byte(s)
	for i := 0; i < len(bs1); i++ {
		switch bs1[i] {
		case '\r', '\n':
			bs2 := make([]byte, len(bs1))
			copy(bs2, bs1)
			bs2[i] = ' '
			i++
			for ; i < len(bs2); i++ {
				switch bs1[i] {
				case '\r', '\n':
					bs2[i] = ' '
				}
			}
			return string(bs2)
		}
	}
	return s
}
func MultiBulkValue(commandName string, args ...interface{}) Value {
	vals := make([]Value, len(args)+1)
	vals[0] = StringValue(commandName)
	for i, arg := range args {
		if rval, ok := arg.(Value); ok && rval.Type() == BulkString {
			vals[i+1] = rval
			continue
		}
		switch arg := arg.(type) {
		default:
			vals[i+1] = StringValue(fmt.Sprintf("%v", arg))
		case []byte:
			vals[i+1] = StringValue(string(arg))
		case string:
			vals[i+1] = StringValue(arg)
		case nil:
			vals[i+1] = NullValue()
		}
	}
	return ArrayValue(vals)
}
type Writer struct {
	wr io.Writer
}
func NewWriter(wr io.Writer) *Writer {
	return &Writer{wr}
}