func (f *framer) readFrame(head *frameHeader) error {
	if head.length < 0 {
		return fmt.Errorf("frame body length can not be less than 0: %d", head.length)
	} else if head.length > maxFrameSize {
		_, err := io.CopyN(ioutil.Discard, f.r, int64(head.length))
		if err != nil {
			return fmt.Errorf("error whilst trying to discard frame with invalid length: %v", err)
		}
		return ErrFrameTooBig
	}
	if cap(f.readBuffer) >= head.length {
		f.rbuf = f.readBuffer[:head.length]
	} else {
		f.readBuffer = make([]byte, head.length)
		f.rbuf = f.readBuffer
	}
	_, err := io.ReadFull(f.r, f.rbuf)
	if err != nil {
		return err
	}
	if head.flags&flagCompress == flagCompress {
		if f.compres == nil {
			return NewErrProtocol("no compressor available with compressed frame body")
		}
		f.rbuf, err = f.compres.Decode(f.rbuf)
		if err != nil {
			return err
		}
	}
	f.header = head
	return nil
}
reads a frame form the wire into the framers buffer
package gocql
import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"runtime"
	"strings"
	"sync"
	"time"
)
const (
	protoDirectionMask = 0x80
	protoVersionMask   = 0x7F
	protoVersion1      = 0x01
	protoVersion2      = 0x02
	protoVersion3      = 0x03
	protoVersion4      = 0x04
	maxFrameSize = 256 * 1024 * 1024
)
type protoVersion byte
func (p protoVersion) request() bool {
	return p&protoDirectionMask == 0x00
}
func (p protoVersion) response() bool {
	return p&protoDirectionMask == 0x80
}
func (p protoVersion) version() byte {
	return byte(p) & protoVersionMask
}
func (p protoVersion) String() string {
	dir := "REQ"
	if p.response() {
		dir = "RESP"
	}
	return fmt.Sprintf("[version=%d direction=%s]", p.version(), dir)
}
type frameOp byte
const (
	opError         frameOp = 0x00
	opStartup       frameOp = 0x01
	opReady         frameOp = 0x02
	opAuthenticate  frameOp = 0x03
	opOptions       frameOp = 0x05
	opSupported     frameOp = 0x06
	opQuery         frameOp = 0x07
	opResult        frameOp = 0x08
	opPrepare       frameOp = 0x09
	opExecute       frameOp = 0x0A
	opRegister      frameOp = 0x0B
	opEvent         frameOp = 0x0C
	opBatch         frameOp = 0x0D
	opAuthChallenge frameOp = 0x0E
	opAuthResponse  frameOp = 0x0F
	opAuthSuccess   frameOp = 0x10
)
func (f frameOp) String() string {
	switch f {
	case opError:
		return "ERROR"
	case opStartup:
		return "STARTUP"
	case opReady:
		return "READY"
	case opAuthenticate:
		return "AUTHENTICATE"
	case opOptions:
		return "OPTIONS"
	case opSupported:
		return "SUPPORTED"
	case opQuery:
		return "QUERY"
	case opResult:
		return "RESULT"
	case opPrepare:
		return "PREPARE"
	case opExecute:
		return "EXECUTE"
	case opRegister:
		return "REGISTER"
	case opEvent:
		return "EVENT"
	case opBatch:
		return "BATCH"
	case opAuthChallenge:
		return "AUTH_CHALLENGE"
	case opAuthResponse:
		return "AUTH_RESPONSE"
	case opAuthSuccess:
		return "AUTH_SUCCESS"
	default:
		return fmt.Sprintf("UNKNOWN_OP_%d", f)
	}
}
const (
	resultKindVoid          = 1
	resultKindRows          = 2
	resultKindKeyspace      = 3
	resultKindPrepared      = 4
	resultKindSchemaChanged = 5
	flagGlobalTableSpec int = 0x01
	flagHasMorePages    int = 0x02
	flagNoMetaData      int = 0x04
	flagValues                byte = 0x01
	flagSkipMetaData          byte = 0x02
	flagPageSize              byte = 0x04
	flagWithPagingState       byte = 0x08
	flagWithSerialConsistency byte = 0x10
	flagDefaultTimestamp      byte = 0x20
	flagWithNameValues        byte = 0x40
	flagCompress      byte = 0x01
	flagTracing       byte = 0x02
	flagCustomPayload byte = 0x04
	flagWarning       byte = 0x08
)
type Consistency uint16
const (
	Any         Consistency = 0x00
	One         Consistency = 0x01
	Two         Consistency = 0x02
	Three       Consistency = 0x03
	Quorum      Consistency = 0x04
	All         Consistency = 0x05
	LocalQuorum Consistency = 0x06
	EachQuorum  Consistency = 0x07
	LocalOne    Consistency = 0x0A
)
func (c Consistency) String() string {
	switch c {
	case Any:
		return "ANY"
	case One:
		return "ONE"
	case Two:
		return "TWO"
	case Three:
		return "THREE"
	case Quorum:
		return "QUORUM"
	case All:
		return "ALL"
	case LocalQuorum:
		return "LOCAL_QUORUM"
	case EachQuorum:
		return "EACH_QUORUM"
	case LocalOne:
		return "LOCAL_ONE"
	default:
		return fmt.Sprintf("UNKNOWN_CONS_0x%x", uint16(c))
	}
}
func ParseConsistency(s string) Consistency {
	switch strings.ToUpper(s) {
	case "ANY":
		return Any
	case "ONE":
		return One
	case "TWO":
		return Two
	case "THREE":
		return Three
	case "QUORUM":
		return Quorum
	case "ALL":
		return All
	case "LOCAL_QUORUM":
		return LocalQuorum
	case "EACH_QUORUM":
		return EachQuorum
	case "LOCAL_ONE":
		return LocalOne
	default:
		panic("invalid consistency: " + s)
	}
}
type SerialConsistency uint16
const (
	Serial      SerialConsistency = 0x08
	LocalSerial SerialConsistency = 0x09
)
func (s SerialConsistency) String() string {
	switch s {
	case Serial:
		return "SERIAL"
	case LocalSerial:
		return "LOCAL_SERIAL"
	default:
		return fmt.Sprintf("UNKNOWN_SERIAL_CONS_0x%x", uint16(s))
	}
}
const (
	apacheCassandraTypePrefix = "org.apache.cassandra.db.marshal."
)
var (
	ErrFrameTooBig = errors.New("frame length is bigger than the maximum allowed")
)
func writeInt(p []byte, n int32) {
	p[0] = byte(n >> 24)
	p[1] = byte(n >> 16)
	p[2] = byte(n >> 8)
	p[3] = byte(n)
}
func readInt(p []byte) int32 {
	return int32(p[0])<<24 | int32(p[1])<<16 | int32(p[2])<<8 | int32(p[3])
}
func writeShort(p []byte, n uint16) {
	p[0] = byte(n >> 8)
	p[1] = byte(n)
}
func readShort(p []byte) uint16 {
	return uint16(p[0])<<8 | uint16(p[1])
}
type frameHeader struct {
	version       protoVersion
	flags         byte
	stream        int
	op            frameOp
	length        int
	customPayload map[string][]byte
}
func (f frameHeader) String() string {
	return fmt.Sprintf("[header version=%s flags=0x%x stream=%d op=%s length=%d]", f.version, f.flags, f.stream, f.op, f.length)
}
func (f frameHeader) Header() frameHeader {
	return f
}
const defaultBufSize = 128
var framerPool = sync.Pool{
	New: func() interface{} {
		return &framer{
			wbuf:       make([]byte, defaultBufSize),
			readBuffer: make([]byte, defaultBufSize),
		}
	},
}
type framer struct {
	r io.Reader
	w io.Writer
	proto byte
	flags    byte
	compres  Compressor
	headSize int
	header *frameHeader
	traceID []byte
	readBuffer []byte
	rbuf []byte
	wbuf []byte
}
func newFramer(r io.Reader, w io.Writer, compressor Compressor, version byte) *framer {
	f := framerPool.Get().(*framer)
	var flags byte
	if compressor != nil {
		flags |= flagCompress
	}
	version &= protoVersionMask
	headSize := 8
	if version > protoVersion2 {
		headSize = 9
	}
	f.compres = compressor
	f.proto = version
	f.flags = flags
	f.headSize = headSize
	f.r = r
	f.rbuf = f.readBuffer[:0]
	f.w = w
	f.wbuf = f.wbuf[:0]
	f.header = nil
	f.traceID = nil
	return f
}
type frame interface {
	Header() frameHeader
}
func readHeader(r io.Reader, p []byte) (head frameHeader, err error) {
	_, err = io.ReadFull(r, p)
	if err != nil {
		return
	}
	version := p[0] & protoVersionMask
	if version < protoVersion1 || version > protoVersion4 {
		err = fmt.Errorf("gocql: invalid version: %d", version)
		return
	}
	head.version = protoVersion(p[0])
	head.flags = p[1]
	if version > protoVersion2 {
		if len(p) < 9 {
			return frameHeader{}, fmt.Errorf("not enough bytes to read header require 9 got: %d", len(p))
		}
		head.stream = int(int16(p[2])<<8 | int16(p[3]))
		head.op = frameOp(p[4])
		head.length = int(readInt(p[5:]))
	} else {
		if len(p) < 8 {
			return frameHeader{}, fmt.Errorf("not enough bytes to read header require 8 got: %d", len(p))
		}
		head.stream = int(int8(p[2]))
		head.op = frameOp(p[3])
		head.length = int(readInt(p[4:]))
	}
	return
}
func (f *framer) trace() {
	f.flags |= flagTracing
}