func (c *Conn) WriteErrorPacket(errorCode uint16, sqlState string, format string, args ...interface{}) error {
	errorMessage := fmt.Sprintf(format, args...)
	length := 1 + 2 + 1 + 5 + len(errorMessage)
	data := c.StartEphemeralPacket(length)
	pos := 0
	pos = WriteByte(data, pos, ErrHeader)
	pos = WriteUint16(data, pos, errorCode)
	pos = WriteByte(data, pos, '#')
	if sqlState == "" {
		sqlState = DefaultMySQLState
	}
	if len(sqlState) != 5 {
		panic("sqlState has to be 5 characters long")
	}
	pos = writeEOFString(data, pos, sqlState)
	pos = writeEOFString(data, pos, errorMessage)
	return c.WriteEphemeralPacket()
}
WriteErrorPacket writes an error packet.
Server -> Client.
This method returns a generic error, not a SQLError.
package mysql
import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net"
	"strings"
	"sync"
	"github.com/nooncall/shazam/util/bucketpool"
	"github.com/nooncall/shazam/util/sync2"
)
const (
	connBufferSize = 128
	MaxPacketSize = (1 << 24) - 1
)
const (
	ephemeralUnused = iota
	ephemeralWrite
	ephemeralRead
)
type Conn struct {
	conn net.Conn
	ConnectionID uint32
	closed sync2.AtomicBool
	bufferedReader *bufio.Reader
	bufferedWriter *bufio.Writer
	sequence       uint8
	currentEphemeralPolicy int
	currentEphemeralBuffer *[]byte
}
var bufPool = bucketpool.New(connBufferSize, MaxPacketSize)
var writersPool = sync.Pool{New: func() interface{} { return bufio.NewWriterSize(nil, connBufferSize) }}
func NewConn(conn net.Conn) *Conn {
	return &Conn{
		conn:           conn,
		closed:         sync2.NewAtomicBool(false),
		bufferedReader: bufio.NewReaderSize(conn, connBufferSize),
	}
}
func (c *Conn) StartWriterBuffering() {
	c.bufferedWriter = writersPool.Get().(*bufio.Writer)
	c.bufferedWriter.Reset(c.conn)
}
func (c *Conn) Flush() error {
	if c.bufferedWriter == nil {
		return nil
	}
	defer func() {
		c.bufferedWriter.Reset(nil)
		writersPool.Put(c.bufferedWriter)
		c.bufferedWriter = nil
	}()
	return c.bufferedWriter.Flush()
}
func (c *Conn) getWriter() io.Writer {
	if c.bufferedWriter != nil {
		return c.bufferedWriter
	}
	return c.conn
}
func (c *Conn) getReader() io.Reader {
	if c.bufferedReader != nil {
		return c.bufferedReader
	}
	return c.conn
}
func (c *Conn) readHeaderFrom(r io.Reader) (int, error) {
	var header [4]byte
	if _, err := io.ReadFull(r, header[:]); err != nil {
		if err == io.EOF {
			return 0, err
		}
		if strings.HasSuffix(err.Error(), "read: connection reset by peer") {
			return 0, io.EOF
		}
		return 0, fmt.Errorf("io.ReadFull(header size) failed: %v", err)
	}
	sequence := uint8(header[3])
	if sequence != c.sequence {
		return 0, fmt.Errorf("invalid sequence, expected %v got %v", c.sequence, sequence)
	}
	c.sequence++
	return int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16), nil
}
func (c *Conn) ReadEphemeralPacket() ([]byte, error) {
	if c.currentEphemeralPolicy != ephemeralUnused {
		panic(fmt.Errorf("ReadEphemeralPacket: unexpected currentEphemeralPolicy: %v", c.currentEphemeralPolicy))
	}
	r := c.getReader()
	length, err := c.readHeaderFrom(r)
	if err != nil {
		return nil, err
	}
	c.currentEphemeralPolicy = ephemeralRead
	if length == 0 {
		return nil, nil
	}
	if length < MaxPacketSize {
		c.currentEphemeralBuffer = bufPool.Get(length)
		if _, err := io.ReadFull(r, *c.currentEphemeralBuffer); err != nil {
			return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err)
		}
		return *c.currentEphemeralBuffer, nil
	}
	data := make([]byte, length)
	if _, err := io.ReadFull(r, data); err != nil {
		return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err)
	}
	for {
		next, err := c.readOnePacket()
		if err != nil {
			return nil, err
		}
		if len(next) == 0 {
			break
		}
		data = append(data, next...)
		if len(next) < MaxPacketSize {
			break
		}
	}
	return data, nil
}
func (c *Conn) ReadEphemeralPacketDirect() ([]byte, error) {
	if c.currentEphemeralPolicy != ephemeralUnused {
		panic(fmt.Errorf("ReadEphemeralPacketDirect: unexpected currentEphemeralPolicy: %v", c.currentEphemeralPolicy))
	}
	var r io.Reader = c.conn
	length, err := c.readHeaderFrom(r)
	if err != nil {
		return nil, err
	}
	c.currentEphemeralPolicy = ephemeralRead
	if length == 0 {
		return nil, nil
	}
	if length < MaxPacketSize {
		c.currentEphemeralBuffer = bufPool.Get(length)
		if _, err := io.ReadFull(r, *c.currentEphemeralBuffer); err != nil {
			return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err)
		}
		return *c.currentEphemeralBuffer, nil
	}
	return nil, fmt.Errorf("ReadEphemeralPacketDirect doesn't support more than one packet")
}
func (c *Conn) RecycleReadPacket() {
	if c.currentEphemeralPolicy != ephemeralRead {
		panic(fmt.Errorf("trying to call RecycleReadPacket while currentEphemeralPolicy is %d", c.currentEphemeralPolicy))
	}
	if c.currentEphemeralBuffer != nil {
		bufPool.Put(c.currentEphemeralBuffer)
		c.currentEphemeralBuffer = nil
	}
	c.currentEphemeralPolicy = ephemeralUnused
}
func (c *Conn) readOnePacket() ([]byte, error) {
	r := c.getReader()
	length, err := c.readHeaderFrom(r)
	if err != nil {
		return nil, err
	}
	if length == 0 {
		return nil, nil
	}
	data := make([]byte, length)
	if _, err := io.ReadFull(r, data); err != nil {
		return nil, fmt.Errorf("io.ReadFull(packet body of length %v) failed: %v", length, err)
	}
	return data, nil
}
func (c *Conn) readPacket() ([]byte, error) {
	data, err := c.readOnePacket()
	if err != nil {
		return nil, err
	}
	if len(data) < MaxPacketSize {
		return data, nil
	}
	for {
		next, err := c.readOnePacket()
		if err != nil {
			return nil, err
		}
		if len(next) == 0 {
			break
		}
		data = append(data, next...)
		if len(next) < MaxPacketSize {
			break
		}
	}
	return data, nil
}
func (c *Conn) ReadPacket() ([]byte, error) {
	result, err := c.readPacket()
	if err != nil {
		return nil, err
	}
	return result, err
}
func (c *Conn) WritePacket(data []byte) error {
	index := 0
	length := len(data)
	w := c.getWriter()
	for {
		packetLength := length
		if packetLength > MaxPacketSize {
			packetLength = MaxPacketSize
		}
		var header [4]byte
		header[0] = byte(packetLength)
		header[1] = byte(packetLength >> 8)
		header[2] = byte(packetLength >> 16)
		header[3] = c.sequence
		if n, err := w.Write(header[:]); err != nil {
			return fmt.Errorf("Write(header) failed: %v", err)
		} else if n != 4 {
			return fmt.Errorf("Write(header) returned a short write: %v < 4", n)
		}
		if n, err := w.Write(data[index : index+packetLength]); err != nil {
			return fmt.Errorf("Write(packet) failed: %v", err)
		} else if n != packetLength {
			return fmt.Errorf("Write(packet) returned a short write: %v < %v", n, packetLength)
		}
		c.sequence++
		length -= packetLength
		if length == 0 {
			if packetLength == MaxPacketSize {
				header[0] = 0
				header[1] = 0
				header[2] = 0
				header[3] = c.sequence
				if n, err := w.Write(header[:]); err != nil {
					return fmt.Errorf("Write(empty header) failed: %v", err)
				} else if n != 4 {
					return fmt.Errorf("Write(empty header) returned a short write: %v < 4", n)
				}
				c.sequence++
			}
			return nil
		}
		index += packetLength
	}
}
func (c *Conn) StartEphemeralPacket(length int) []byte {
	if c.currentEphemeralPolicy != ephemeralUnused {
		panic("StartEphemeralPacket cannot be used while a packet is already started.")
	}
	c.currentEphemeralPolicy = ephemeralWrite
	c.currentEphemeralBuffer = bufPool.Get(length)
	return *c.currentEphemeralBuffer
}
func (c *Conn) WriteEphemeralPacket() error {
	defer c.recycleWritePacket()
	switch c.currentEphemeralPolicy {
	case ephemeralWrite:
		if err := c.WritePacket(*c.currentEphemeralBuffer); err != nil {
			return fmt.Errorf("Conn %v: %v", c.GetConnectionID(), err)
		}
	case ephemeralUnused, ephemeralRead:
		panic(fmt.Errorf("Conn %v: trying to call writeEphemeralPacket while currentEphemeralPolicy is %v", c.GetConnectionID(), c.currentEphemeralPolicy))
	}
	return nil
}
func (c *Conn) recycleWritePacket() {
	if c.currentEphemeralPolicy != ephemeralWrite {
		panic(fmt.Errorf("trying to call recycleWritePacket while currentEphemeralPolicy is %d", c.currentEphemeralPolicy))
	}
	bufPool.Put(c.currentEphemeralBuffer)
	c.currentEphemeralBuffer = nil
	c.currentEphemeralPolicy = ephemeralUnused
}
func (c *Conn) writeComQuit() error {
	c.sequence = 0
	data := c.StartEphemeralPacket(1)
	data[0] = ComQuit
	if err := c.WriteEphemeralPacket(); err != nil {
		return err
	}
	return nil
}
func (c *Conn) RemoteAddr() net.Addr {
	return c.conn.RemoteAddr()
}
func (c *Conn) GetConnectionID() uint32 {
	return c.ConnectionID
}
func (c *Conn) SetConnectionID(connectionID uint32) {
	c.ConnectionID = connectionID
}
func (c *Conn) SetSequence(sequence uint8) {
	c.sequence = sequence
}
func (c *Conn) GetSequence() uint8 {
	return c.sequence
}
func (c *Conn) String() string {
	return fmt.Sprintf("client %v (%s)", c.ConnectionID, c.RemoteAddr().String())
}
func (c *Conn) Close() {
	if c.closed.CompareAndSwap(false, true) {
		c.conn.Close()
	}
}
func (c *Conn) IsClosed() bool {
	return c.closed.Get()
}
func (c *Conn) WriteOKPacket(affectedRows, lastInsertID uint64, flags uint16, warnings uint16) error {
	length := 1 +  
		LenEncIntSize(affectedRows) +
		LenEncIntSize(lastInsertID) +
		2 +  
		2  
	data := c.StartEphemeralPacket(length)
	pos := 0
	pos = WriteByte(data, pos, OKHeader)
	pos = WriteLenEncInt(data, pos, affectedRows)
	pos = WriteLenEncInt(data, pos, lastInsertID)
	pos = WriteUint16(data, pos, flags)
	pos = WriteUint16(data, pos, warnings)
	return c.WriteEphemeralPacket()
}
func (c *Conn) WriteOKPacketWithEOFHeader(affectedRows, lastInsertID uint64, flags uint16, warnings uint16) error {
	length := 1 +  
		LenEncIntSize(affectedRows) +
		LenEncIntSize(lastInsertID) +
		2 +  
		2  
	data := c.StartEphemeralPacket(length)
	pos := 0
	pos = WriteByte(data, pos, EOFHeader)
	pos = WriteLenEncInt(data, pos, affectedRows)
	pos = WriteLenEncInt(data, pos, lastInsertID)
	pos = WriteUint16(data, pos, flags)
	pos = WriteUint16(data, pos, warnings)
	return c.WriteEphemeralPacket()
}