func (b *buf) watchCancel(ctx context.Context, reading bool) func() {
	if done := ctx.Done(); done != nil {
		finished := make(chan struct{})
		go func() {
			select {
			case <-done:
				_ = b.cancel(ctx.Err(), reading)
				finished <- struct{}{}
			case <-finished:
			}
		}()
		return func() {
			select {
			case <-finished:
			case finished <- struct{}{}:
			}
		}
	}
	return nil
}
watchCancel will start a cancelation goroutine
if the context can be terminated.
Returns a function to end the goroutine
package tds
import (
	"bytes"
	"context"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
	"sync/atomic"
	"time"
	bin "github.com/thda/tds/binary"
)
const headerSize = 8
const (
	_ = iota
	eom
	cancelAck
	cancel
)
type header struct {
	token      packetType
	status     uint8
	packetSize uint16
	spid       uint16
	packetNo   uint8
	pad        uint8
}
func (h *header) read(e *bin.Encoder) error {
	h.token = packetType(e.ReadByte())
	h.status = e.Uint8()
	h.packetSize = e.Uint16()
	h.spid = e.Uint16()
	h.packetNo = e.Uint8()
	h.pad = e.Uint8()
	err := e.Err()
	return err
}
func (h header) write(e *bin.Encoder) error {
	e.WriteByte(byte(h.token))
	e.WriteByte(h.status)
	e.WriteUint16(h.packetSize)
	e.WriteUint16(h.spid)
	e.WriteUint8(h.packetNo)
	e.WriteUint8(h.pad)
	err := e.Err()
	return err
}
const maxMsgBufSize = 25000
const defaultCancelTimeout = 10
type buf struct {
	rw io.ReadWriter
	h  header        
	pb bytes.Buffer  
	d  [50]byte      
	mb bytes.Buffer  
	me bin.Encoder   
	he bin.Encoder   
	pe         bin.Encoder
	debug      bool
	PacketSize int
	cancelCh      chan error  
	inCancel      int32       
	WriteTimeout  int
	ReadTimeout   int
	CancelTimeout int  
	defaultMessageMap map[token]messageReader
}
func newBuf(packetSize int, rw io.ReadWriter) *buf {
	b := new(buf)
	b.PacketSize = packetSize
	b.rw = rw
	b.me = bin.NewEncoder(&b.mb, binary.LittleEndian)
	b.pe = bin.NewEncoder(b, binary.LittleEndian)
	b.he = bin.NewEncoder(&struct {
		io.Reader
		io.Writer
	}{b.rw, &b.pb}, binary.BigEndian)
	b.cancelCh = make(chan error, 1)
	b.CancelTimeout = defaultCancelTimeout
	return b
}
func (b *buf) SetEndianness(endianness binary.ByteOrder) {
	b.pe.SetEndianness(endianness)
	b.me.SetEndianness(endianness)
}
func (b *buf) SetCharset(c string) error {
	e, err := getEncoding(c)
	if err != nil {
		return fmt.Errorf("netlib: could not find encoder for %s", c)
	}
	b.pe.SetCharset(e)
	b.me.SetCharset(e)
	return nil
}
func (b *buf) initPkt(t packetType) {
	b.pb.Reset()
	b.h.token, b.h.status = t, 0
	b.h.write(&b.he)
}
func (b *buf) readPkt(ignoreCan bool) (err error) {
	b.pb.Reset()
	if err = b.h.read(&b.he); err != nil {
		return err
	}
	if _, err = io.CopyN(&b.pb, b.rw, int64(b.h.packetSize)-headerSize); err != nil {
		return err
	}
	if !ignoreCan && b.cancelling() {
		err = b.processCancel()
	}
	return err
}
func (b *buf) sendPkt(status uint8) (err error) {
	b.pb.Bytes()[1] = status
	if b.cancelling() {
		if b.h.status&cancel == cancel &&
			status&eom != eom {
			return nil
		}
		b.h.status |= cancel
		b.pb.Bytes()[1] = eom | cancel
	}
	binary.BigEndian.PutUint16(b.pb.Bytes()[2:], uint16(b.pb.Len()))
	_, err = b.pb.WriteTo(b.rw)
	if status&eom == 0 {
		b.initPkt(b.h.token)
	} else if b.cancelling() {
		b.h.status = 0
		return b.processCancel()
	}
	return err
}
func (b *buf) Read(buf []byte) (n int, err error) {
	n, err = io.ReadFull(&b.pb, buf)
	if err == io.ErrUnexpectedEOF || err == io.EOF {
		if err = b.readPkt(false); err != nil {
			return 0, err
		}
	} else if n == 0 && b.h.status == 1 {
		return 0, io.EOF
	}
	return n, err
}
func (b *buf) Write(p []byte) (n int, err error) {
	var copied, remaining int
	for {
		remaining = int(b.PacketSize) - b.pb.Len()
		if len(p) >= remaining {
			n, err = b.pb.Write(p[:remaining])
		} else {
			n, err = b.pb.Write(p[:])
		}
		if err != nil {
			return 0, err
		}
		p = p[n:]
		copied += n
		if len(p) == 0 {
			return copied, nil
		}
		if err = b.sendPkt(0); err != nil {
			return copied, err
		}
	}
}
func (b *buf) skip(cnt int) (err error) {
	if cnt == 0 {
		return nil
	}
	if cnt < len(b.d) {
		_, err = io.ReadFull(b, b.d[:cnt])
		return err
	}
	for skipped := 0; skipped < cnt; skipped += len(b.d) {
		if cnt-skipped < len(b.d) {
			_, err = io.ReadFull(b, b.d[:cnt%len(b.d)])
		} else {
			_, err = io.ReadFull(b, b.d[:])
		}
		if err != nil {
			return err
		}
	}
	return nil
}
func (b *buf) peek() (out byte, err error) {
	out = b.pe.ReadByte()
	err = b.pe.Err()
	b.pb.UnreadByte()
	return out, err
}
func (b *buf) writeMsg(msg messageReaderWriter) (err error) {
	b.mb.Reset()
	if err = msg.Write(&b.me); err != nil {
		return err
	}
	if msg.Token() != token(nonePacket) {
		b.pe.WriteByte(byte(msg.Token()))
	}
	switch msg.SizeLen() {
	case 8:
		b.pe.WriteInt8(int8(b.mb.Len()))
	case 16:
		b.pe.WriteInt16(int16(b.mb.Len()))
	case 32:
		b.pe.WriteInt32(int32(b.mb.Len()))
	}
	if err = b.pe.Err(); err != nil {
		return err
	}
	_, err = b.mb.WriteTo(b)
	if b.mb.Cap() > maxMsgBufSize {
		b.mb = *new(bytes.Buffer)
	}
	return err
}
func (b *buf) readMsg(msg messageReader) (err error) {
	var size int
	switch msg.SizeLen() {
	case 8:
		size = int(b.pe.Uint8())
	case 16:
		size = int(b.pe.Uint16())
	case 32:
		size = int(b.pe.Uint32())
	}
	if err = b.pe.Err(); err != nil {
		return err
	}
	if msg.LimitRead() {
		b.pe.LimitRead(int64(size))
		defer func(e *bin.Encoder) {
			e.UnlimitRead()
		}(&b.pe)
	}
	return msg.Read(&b.pe)
}
func (b *buf) skipMsg(msg messageReader) (err error) {
	var size int
	if msg.Size() != 0 {
		size = int(msg.Size())
	} else {
		switch msg.SizeLen() {
		default:
			return fmt.Errorf("netlib: unknown token size for %s message", msg)
		case 8:
			size = int(b.pe.Uint8())
		case 16:
			size = int(b.pe.Uint16())
		case 32:
			size = int(b.pe.Uint32())
		}
	}
	err = b.skip(size)
	return err
}
func (b *buf) send(ctx context.Context, pt packetType, msgs ...messageReaderWriter) (err error) {
	b.initPkt(pt)
	if ctx == nil && b.WriteTimeout > 0 {
		var cancelFunc func()
		ctx, cancelFunc = context.WithTimeout(context.Background(), time.Duration(b.WriteTimeout)*time.Second)
		defer cancelFunc()
	}
	if ctx != nil {
		if cancel := b.watchCancel(ctx, false); cancel != nil {
			defer cancel()
		}
	}
	for _, msg := range msgs {
		if err = b.writeMsg(msg); err != nil {
			return err
		}
	}
	return b.sendPkt(1)
}
type state struct {
	t       token                    
	handler func(t token) error      
	msg     map[token]messageReader  
	err     error                    
	ctx     context.Context
}
type stateFn func(*state) stateFn
func (b *buf) receive(s *state) stateFn {
	if s.ctx == nil && b.ReadTimeout > 0 {
		var cancelFunc func()
		s.ctx, cancelFunc = context.WithTimeout(context.Background(), time.Duration(b.ReadTimeout)*time.Second)
		defer cancelFunc()
	}
	if s.ctx != nil {
		if cancel := b.watchCancel(s.ctx, true); cancel != nil {
			defer cancel()
		}
	}
	s.t = token(b.pe.ReadByte())
	if s.err = b.pe.Err(); s.err != nil {
		if s.err == io.EOF {
			s.err = fmt.Errorf("netlib: unexpected EOF while reading message")
		}
		return nil
	}
	if b.h.token != normalPacket && b.h.token != replyPacket {
		s.err = fmt.Errorf("netlib: expected reply or normal token, got %s", b.h.token)
		return nil
	}
	msg, ok := b.defaultMessageMap[s.t]
	if !ok {
		msg, ok = s.msg[s.t]
	}
	if !ok {
		if s.err = b.skipMsg(emptyMsg{msg: newMsg(s.t)}); s.err != nil {
			return nil
		}
	} else {
		s.err = b.readMsg(msg)
		if s.err != nil {
			return nil
		}
		if s.err = s.handler(s.t); s.err != nil {
			return nil
		}
	}
	return b.receive
}