func (m *TruncateMessage) Decode(src []byte) (err error) {
	if len(src) < 9 {
		return m.lengthError("TruncateMessage", 9, len(src))
	}
	var low, used int
	m.RelationNum, used = m.decodeUint32(src)
	low += used
	m.Option = uint8(src[low])
	low++
	m.RelationIDs = make([]uint32, m.RelationNum)
	for i := 0; i < int(m.RelationNum); i++ {
		m.RelationIDs[i], used = m.decodeUint32(src[low:])
		low += used
	}
	m.SetType(MessageTypeTruncate)
	return nil
}
Decode decodes to message from src.
package pglogrepl
import (
	"bytes"
	"encoding/binary"
	"fmt"
	"strconv"
	"time"
)
type MessageType uint8
func (t MessageType) String() string {
	switch t {
	case MessageTypeBegin:
		return "Begin"
	case MessageTypeCommit:
		return "Commit"
	case MessageTypeOrigin:
		return "Origin"
	case MessageTypeRelation:
		return "Relation"
	case MessageTypeType:
		return "Type"
	case MessageTypeInsert:
		return "Insert"
	case MessageTypeUpdate:
		return "Update"
	case MessageTypeDelete:
		return "Delete"
	case MessageTypeTruncate:
		return "Truncate"
	default:
		return "Unknown"
	}
}
const (
	MessageTypeBegin    MessageType = 'B'
	MessageTypeCommit               = 'C'
	MessageTypeOrigin               = 'O'
	MessageTypeRelation             = 'R'
	MessageTypeType                 = 'Y'
	MessageTypeInsert               = 'I'
	MessageTypeUpdate               = 'U'
	MessageTypeDelete               = 'D'
	MessageTypeTruncate             = 'T'
)
type Message interface {
	Type() MessageType
}
type MessageDecoder interface {
	Decode([]byte) error
}
type baseMessage struct {
	msgType MessageType
}
func (m *baseMessage) Type() MessageType {
	return m.msgType
}
func (m *baseMessage) SetType(t MessageType) {
	m.msgType = t
}
func (m *baseMessage) Decode(src []byte) error {
	return fmt.Errorf("message decode not implemented")
}
func (m *baseMessage) lengthError(name string, expectedLen, actualLen int) error {
	return fmt.Errorf("%s must have %d bytes, got %d bytes", name, expectedLen, actualLen)
}
func (m *baseMessage) decodeStringError(name, field string) error {
	return fmt.Errorf("%s.%s decode string error", name, field)
}
func (m *baseMessage) decodeTupleDataError(name, field string, e error) error {
	return fmt.Errorf("%s.%s decode tuple error: %s", name, field, e.Error())
}
func (m *baseMessage) invalidTupleTypeError(name, field string, e string, a byte) error {
	return fmt.Errorf("%s.%s invalid tuple type value, expect %s, actual %c", name, field, e, a)
}
func (m *baseMessage) decodeString(src []byte) (string, int) {
	end := bytes.IndexByte(src, byte(0))
	if end == -1 {
		return "", -1
	}
	return string(src[:end]), end + 1
}
func (m *baseMessage) decodeLSN(src []byte) (LSN, int) {
	return LSN(binary.BigEndian.Uint64(src)), 8
}
func (m *baseMessage) decodeTime(src []byte) (time.Time, int) {
	return pgTimeToTime(int64(binary.BigEndian.Uint64(src))), 8
}
func (m *baseMessage) decodeUint16(src []byte) (uint16, int) {
	return binary.BigEndian.Uint16(src), 2
}
func (m *baseMessage) decodeUint32(src []byte) (uint32, int) {
	return binary.BigEndian.Uint32(src), 4
}
func (m *baseMessage) decodeUint64(src []byte) (uint64, int) {
	return binary.BigEndian.Uint64(src), 8
}
type BeginMessage struct {
	baseMessage
	FinalLSN LSN
	CommitTime time.Time
	Xid uint32
}
func (m *BeginMessage) Decode(src []byte) error {
	if len(src) < 20 {
		return m.lengthError("BeginMessage", 20, len(src))
	}
	var low, used int
	m.FinalLSN, used = m.decodeLSN(src)
	low += used
	m.CommitTime, used = m.decodeTime(src[low:])
	low += used
	m.Xid = binary.BigEndian.Uint32(src[low:])
	m.SetType(MessageTypeBegin)
	return nil
}
type CommitMessage struct {
	baseMessage
	Flags uint8
	CommitLSN LSN
	TransactionEndLSN LSN
	CommitTime time.Time
}
func (m *CommitMessage) Decode(src []byte) error {
	if len(src) < 25 {
		return m.lengthError("CommitMessage", 25, len(src))
	}
	var low, used int
	m.Flags = src[0]
	low += 1
	m.CommitLSN, used = m.decodeLSN(src[low:])
	low += used
	m.TransactionEndLSN, used = m.decodeLSN(src[low:])
	low += used
	m.CommitTime, _ = m.decodeTime(src[low:])
	m.SetType(MessageTypeCommit)
	return nil
}
type OriginMessage struct {
	baseMessage
	CommitLSN LSN
	Name      string
}
func (m *OriginMessage) Decode(src []byte) error {
	if len(src) < 8 {
		return m.lengthError("OriginMessage", 9, len(src))
	}
	var low, used int
	m.CommitLSN, used = m.decodeLSN(src)
	low += used
	m.Name, used = m.decodeString(src[low:])
	if used < 0 {
		return m.decodeStringError("OriginMessage", "Name")
	}
	m.SetType(MessageTypeOrigin)
	return nil
}
type RelationMessageColumn struct {
	Flags uint8
	Name string
	DataType uint32
	TypeModifier uint32
}
type RelationMessage struct {
	baseMessage
	RelationID      uint32
	Namespace       string
	RelationName    string
	ReplicaIdentity uint8
	ColumnNum       uint16
	Columns         []*RelationMessageColumn
}
func (m *RelationMessage) Decode(src []byte) error {
	if len(src) < 7 {
		return m.lengthError("RelationMessage", 7, len(src))
	}
	var low, used int
	m.RelationID, used = m.decodeUint32(src)
	low += used
	m.Namespace, used = m.decodeString(src[low:])
	if used < 0 {
		return m.decodeStringError("RelationMessage", "Namespace")
	}
	low += used
	m.RelationName, used = m.decodeString(src[low:])
	if used < 0 {
		return m.decodeStringError("RelationMessage", "RelationName")
	}
	low += used
	m.ReplicaIdentity = uint8(src[low])
	low++
	m.ColumnNum, used = m.decodeUint16(src[low:])
	low += used
	for i := 0; i < int(m.ColumnNum); i++ {
		column := new(RelationMessageColumn)
		column.Flags = uint8(src[low])
		low++
		column.Name, used = m.decodeString(src[low:])
		if used < 0 {
			return m.decodeStringError("RelationMessage", fmt.Sprintf("Column[%d].Name", i))
		}
		low += used
		column.DataType, used = m.decodeUint32(src[low:])
		low += used
		column.TypeModifier, used = m.decodeUint32(src[low:])
		low += used
		m.Columns = append(m.Columns, column)
	}
	m.SetType(MessageTypeRelation)
	return nil
}
type TypeMessage struct {
	baseMessage
	DataType  uint32
	Namespace string
	Name      string
}
func (m *TypeMessage) Decode(src []byte) error {
	if len(src) < 6 {
		return m.lengthError("TypeMessage", 6, len(src))
	}
	var low, used int
	m.DataType, used = m.decodeUint32(src)
	low += used
	m.Namespace, used = m.decodeString(src[low:])
	if used < 0 {
		return m.decodeStringError("TypeMessage", "Namespace")
	}
	low += used
	m.Name, used = m.decodeString(src[low:])
	if used < 0 {
		return m.decodeStringError("TypeMessage", "Name")
	}
	m.SetType(MessageTypeType)
	return nil
}
const (
	TupleDataTypeNull  = uint8('n')
	TupleDataTypeToast = uint8('u')
	TupleDataTypeText  = uint8('t')
)
type TupleDataColumn struct {
	DataType uint8
	Length   uint32
	Data []byte
}
func (c *TupleDataColumn) Int64() (int64, error) {
	if c.DataType != TupleDataTypeText {
		return 0, fmt.Errorf("invalid column's data type, expect %c, actual %c",
			TupleDataTypeText, c.DataType)
	}
	return strconv.ParseInt(string(c.Data), 10, 64)
}
type TupleData struct {
	baseMessage
	ColumnNum uint16
	Columns   []*TupleDataColumn
}
func (m *TupleData) Decode(src []byte) (int, error) {
	var low, used int
	m.ColumnNum, used = m.decodeUint16(src)
	low += used
	for i := 0; i < int(m.ColumnNum); i++ {
		column := new(TupleDataColumn)
		column.DataType = uint8(src[low])
		low += 1
		switch column.DataType {
		case TupleDataTypeText:
			column.Length, used = m.decodeUint32(src[low:])
			low += used
			column.Data = make([]byte, int(column.Length))
			for j := 0; j < int(column.Length); j++ {
				column.Data[j] = src[low+j]
			}
			low += int(column.Length)
		case TupleDataTypeNull, TupleDataTypeToast:
		}
		m.Columns = append(m.Columns, column)
	}
	return low, nil
}
type InsertMessage struct {
	baseMessage
	RelationID uint32
	Tuple      *TupleData
}
func (m *InsertMessage) Decode(src []byte) error {
	if len(src) < 8 {
		return m.lengthError("InsertMessage", 8, len(src))
	}
	var low, used int
	m.RelationID, used = m.decodeUint32(src)
	low += used
	tupleType := uint8(src[low])
	low += 1
	if tupleType != 'N' {
		return m.invalidTupleTypeError("InsertMessage", "TupleType", "N", tupleType)
	}
	m.Tuple = new(TupleData)
	_, err := m.Tuple.Decode(src[low:])
	if err != nil {
		return m.decodeTupleDataError("InsertMessage", "TupleData", err)
	}
	m.SetType(MessageTypeInsert)
	return nil
}
const (
	UpdateMessageTupleTypeNone = uint8(0)
	UpdateMessageTupleTypeKey  = uint8('K')
	UpdateMessageTupleTypeOld  = uint8('O')
	UpdateMessageTupleTypeNew  = uint8('N')
)
type UpdateMessage struct {
	baseMessage
	RelationID uint32
	OldTupleType uint8
	OldTuple     *TupleData
	NewTuple *TupleData
}
func (m *UpdateMessage) Decode(src []byte) (err error) {
	if len(src) < 6 {
		return m.lengthError("UpdateMessage", 6, len(src))
	}
	var low, used int
	m.RelationID, used = m.decodeUint32(src)
	low += used
	tupleType := uint8(src[low])
	low++
	switch tupleType {
	case UpdateMessageTupleTypeKey, UpdateMessageTupleTypeOld:
		m.OldTupleType = tupleType
		m.OldTuple = new(TupleData)
		used, err = m.OldTuple.Decode(src[low:])
		if err != nil {
			return m.decodeTupleDataError("UpdateMessage", "OldTuple", err)
		}
		low += used
		tupleType = uint8(src[low])
		low++
		fallthrough
	case UpdateMessageTupleTypeNew:
		m.NewTuple = new(TupleData)
		_, err = m.NewTuple.Decode(src[low:])
		if err != nil {
			return m.decodeTupleDataError("UpdateMessage", "NewTuple", err)
		}
	default:
		return m.invalidTupleTypeError("UpdateMessage", "Tuple", "K/O/N", tupleType)
	}
	m.SetType(MessageTypeUpdate)
	return nil
}
const (
	DeleteMessageTupleTypeKey = uint8('K')
	DeleteMessageTupleTypeOld = uint8('O')
)
type DeleteMessage struct {
	baseMessage
	RelationID uint32
	OldTupleType uint8
	OldTuple     *TupleData
}
func (m *DeleteMessage) Decode(src []byte) (err error) {
	if len(src) < 4 {
		return m.lengthError("DeleteMessage", 4, len(src))
	}
	var low, used int
	m.RelationID, used = m.decodeUint32(src)
	low += used
	m.OldTupleType = uint8(src[low])
	low++
	switch m.OldTupleType {
	case DeleteMessageTupleTypeKey, DeleteMessageTupleTypeOld:
		m.OldTuple = new(TupleData)
		_, err = m.OldTuple.Decode(src[low:])
		if err != nil {
			return m.decodeTupleDataError("DeleteMessage", "OldTuple", err)
		}
	default:
		return m.invalidTupleTypeError("DeleteMessage", "OldTupleType", "K/O", m.OldTupleType)
	}
	m.SetType(MessageTypeDelete)
	return nil
}
const (
	TruncateOptionCascade = uint8(1) << iota
	TruncateOptionRestartIdentity
)
type TruncateMessage struct {
	baseMessage
	RelationNum uint32
	Option      uint8
	RelationIDs []uint32
}