func (packet *PacketHandler) parseColumns() error {
	packet.columnCount = int(binary.BigEndian.Uint16(packet.descriptionBuf.Bytes()[:2]))
	if packet.columnCount == 0 {
		return nil
	}
	columnReader := bytes.NewReader(packet.descriptionBuf.Bytes()[2:])
	var columns []*ColumnData
	for i := 0; i < packet.columnCount; i++ {
		column := &ColumnData{}
		if err := column.ReadLength(columnReader); err != nil {
			return err
		}
		if err := column.readData(columnReader); err != nil {
			return err
		}
		columns = append(columns, column)
	}
	packet.Columns = columns
	return nil
}
parseColumns split whole data row packet into separate columns data
package postgresql
import (
	"bufio"
	"bytes"
	"encoding/binary"
	"errors"
	"github.com/cossacklabs/acra/decryptor/base"
	"github.com/cossacklabs/acra/logging"
	"github.com/cossacklabs/acra/utils"
	"github.com/sirupsen/logrus"
	"io"
)
type PacketHandler struct {
	messageType          [1]byte
	descriptionLengthBuf []byte
	descriptionBuf       *bytes.Buffer
	columnCount     int
	dataLength      int
	reader          io.Reader
	writer          *bufio.Writer
	logger          *logrus.Entry
	Columns         []*ColumnData
	terminatePacket bool
}
func NewClientSidePacketHandler(reader io.Reader, writer *bufio.Writer, logger *logrus.Entry) (*PacketHandler, error) {
	return newPacketHandlerWithLogger(reader, writer, logger.WithField("proxy", "client"))
}
func NewDbSidePacketHandler(reader io.Reader, writer *bufio.Writer, logger *logrus.Entry) (*PacketHandler, error) {
	return newPacketHandlerWithLogger(reader, writer, logger.WithField("proxy", "server"))
}
func newPacketHandlerWithLogger(reader io.Reader, writer *bufio.Writer, logger *logrus.Entry) (*PacketHandler, error) {
	return &PacketHandler{
		descriptionBuf:       bytes.NewBuffer(make([]byte, 0, OutputDefaultSize)),
		descriptionLengthBuf: make([]byte, 4),
		reader:               reader,
		writer:               writer,
		logger:               logger,
		terminatePacket:      false,
	}, nil
}
func (packet *PacketHandler) updatePacketLength(newLength int) {
	binary.BigEndian.PutUint32(packet.descriptionLengthBuf[:], uint32(newLength+DataRowLengthBufSize))
}
func (packet *PacketHandler) updateDataFromColumns() {
	columnsDataChanged := false
	for i := 0; i < packet.columnCount; i++ {
		if packet.Columns[i].changed {
			columnsDataChanged = true
			break
		}
	}
	if columnsDataChanged {
		newDataLength := packet.columnCount*4 + 2
		for i := 0; i < packet.columnCount; i++ {
			newDataLength += packet.Columns[i].Length()
		}
		packet.descriptionBuf.Reset()
		packet.descriptionBuf.Grow(newDataLength)
		columnCountBuf := make([]byte, 2)
		binary.BigEndian.PutUint16(columnCountBuf, uint16(packet.columnCount))
		packet.descriptionBuf.Write(columnCountBuf)
		for i := 0; i < packet.columnCount; i++ {
			packet.descriptionBuf.Write(packet.Columns[i].LengthBuf[:])
			if !packet.Columns[i].IsNull() {
				packet.descriptionBuf.Write(packet.Columns[i].data.Encoded())
			}
		}
		packet.updatePacketLength(newDataLength)
	}
}
func (packet *PacketHandler) sendPacket() error {
	data, err := packet.Marshal()
	if err != nil {
		packet.logger.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorCodingCantSerializePostgresqlPacket).WithError(err).Errorln("Can't marshal packet")
		return err
	}
	if _, err := packet.writer.Write(data); err != nil {
		packet.logger.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorNetworkWrite).WithError(err).Warningln("Can't dump marshaled packet")
		return err
	}
	if err := packet.writer.Flush(); err != nil {
		packet.logger.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorNetworkFlush).WithError(err).Warningln("Can't flush writer")
		return err
	}
	return nil
}
func (packet *PacketHandler) sendMessageType() error {
	n, err := packet.writer.Write(packet.messageType[:])
	if err2 := base.CheckReadWrite(n, 1, err); err2 != nil {
		return err2
	}
	if err := packet.writer.Flush(); err != nil {
		packet.logger.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorNetworkFlush).WithError(err).Warningln("Can't flush writer")
		return err
	}
	return nil
}
type ColumnData struct {
	LengthBuf [4]byte
	data      *utils.DecodedData
	changed   bool
	isNull    bool
}
func (column *ColumnData) GetData() []byte {
	return column.data.Data()
}
func (column *ColumnData) Length() int {
	if column.isNull {
		return 0
	}
	return int(binary.BigEndian.Uint32(column.LengthBuf[:]))
}
func (column *ColumnData) IsNull() bool {
	return column.isNull
}
func (column *ColumnData) ReadLength(reader io.Reader) error {
	n, err := io.ReadFull(reader, column.LengthBuf[:])
	if err2 := base.CheckReadWrite(n, 4, err); err2 != nil {
		return err
	}
	return nil
}
const (
	NullColumnValue int32 = -1
)
func (column *ColumnData) readData(reader io.Reader) error {
	length := column.Length()
	if int32(length) == NullColumnValue {
		column.data = utils.WrapRawDataAsDecoded(nil)
		column.isNull = true
		return nil
	}
	column.isNull = false
	if length == 0 {
		var err error
		column.data, err = utils.DecodeEscaped(nil)
		if err != nil && err != utils.ErrDecodeOctalString {
			return err
		}
		return nil
	}
	data := make([]byte, length)
	n, err := io.ReadFull(reader, data)
	if err != nil {
		return err
	}
	column.data, err = utils.DecodeEscaped(data)
	if err != nil && err != utils.ErrDecodeOctalString {
		return err
	}
	err = nil
	return base.CheckReadWrite(n, length, err)
}
func (column *ColumnData) SetData(newData []byte) {
	column.changed = true
	if column.data == nil {
		column.data = utils.WrapRawDataAsDecoded(newData)
	}
	column.data.Set(newData)
	binary.BigEndian.PutUint32(column.LengthBuf[:], uint32(len(column.data.Encoded())))
}