Replace MarshalBinary with Encode

This new approach can avoid allocations.
batch-wip
Jack Christensen 2017-05-26 17:00:44 -05:00
parent 21d2ed0934
commit 2e2c2ad778
35 changed files with 277 additions and 285 deletions

View File

@ -1,9 +1,10 @@
package pgproto3
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/jackc/pgx/pgio"
)
const (
@ -36,19 +37,18 @@ func (dst *Authentication) Decode(src []byte) error {
return nil
}
func (src *Authentication) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('R')
buf.Write(bigEndian.Uint32(0))
buf.Write(bigEndian.Uint32(src.Type))
func (src *Authentication) Encode(dst []byte) []byte {
dst = append(dst, 'R')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint32(dst, src.Type)
switch src.Type {
case AuthTypeMD5Password:
buf.Write(src.Salt[:])
dst = append(dst, src.Salt[:]...)
}
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}

View File

@ -32,12 +32,7 @@ func NewBackend(r io.Reader, w io.Writer) (*Backend, error) {
}
func (b *Backend) Send(msg BackendMessage) error {
buf, err := msg.MarshalBinary()
if err != nil {
return nil
}
_, err = b.w.Write(buf)
_, err := b.w.Write(msg.Encode(nil))
return err
}

View File

@ -1,9 +1,10 @@
package pgproto3
import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type BackendKeyData struct {
@ -24,14 +25,12 @@ func (dst *BackendKeyData) Decode(src []byte) error {
return nil
}
func (src *BackendKeyData) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('K')
buf.Write(bigEndian.Uint32(12))
buf.Write(bigEndian.Uint32(src.ProcessID))
buf.Write(bigEndian.Uint32(src.SecretKey))
return buf.Bytes(), nil
func (src *BackendKeyData) Encode(dst []byte) []byte {
dst = append(dst, 'K')
dst = pgio.AppendUint32(dst, 12)
dst = pgio.AppendUint32(dst, src.ProcessID)
dst = pgio.AppendUint32(dst, src.SecretKey)
return dst
}
func (src *BackendKeyData) MarshalJSON() ([]byte, error) {

View File

@ -5,6 +5,8 @@ import (
"encoding/binary"
"encoding/hex"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type Bind struct {
@ -101,45 +103,40 @@ func (dst *Bind) Decode(src []byte) error {
return nil
}
func (src *Bind) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *Bind) Encode(dst []byte) []byte {
dst = append(dst, 'B')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('B')
buf.Write(bigEndian.Uint32(0))
buf.WriteString(src.DestinationPortal)
buf.WriteByte(0)
buf.WriteString(src.PreparedStatement)
buf.WriteByte(0)
buf.Write(bigEndian.Uint16(uint16(len(src.ParameterFormatCodes))))
dst = append(dst, src.DestinationPortal...)
dst = append(dst, 0)
dst = append(dst, src.PreparedStatement...)
dst = append(dst, 0)
dst = pgio.AppendUint16(dst, uint16(len(src.ParameterFormatCodes)))
for _, fc := range src.ParameterFormatCodes {
buf.Write(bigEndian.Int16(fc))
dst = pgio.AppendInt16(dst, fc)
}
buf.Write(bigEndian.Uint16(uint16(len(src.Parameters))))
dst = pgio.AppendUint16(dst, uint16(len(src.Parameters)))
for _, p := range src.Parameters {
if p == nil {
buf.Write(bigEndian.Int32(-1))
dst = pgio.AppendInt32(dst, -1)
continue
}
buf.Write(bigEndian.Int32(int32(len(p))))
buf.Write(p)
dst = pgio.AppendInt32(dst, int32(len(p)))
dst = append(dst, p...)
}
buf.Write(bigEndian.Uint16(uint16(len(src.ResultFormatCodes))))
dst = pgio.AppendUint16(dst, uint16(len(src.ResultFormatCodes)))
for _, fc := range src.ResultFormatCodes {
buf.Write(bigEndian.Int16(fc))
dst = pgio.AppendInt16(dst, fc)
}
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}
func (src *Bind) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *BindComplete) Decode(src []byte) error {
return nil
}
func (src *BindComplete) MarshalBinary() ([]byte, error) {
return []byte{'2', 0, 0, 0, 4}, nil
func (src *BindComplete) Encode(dst []byte) []byte {
return append(dst, '2', 0, 0, 0, 4)
}
func (src *BindComplete) MarshalJSON() ([]byte, error) {

View File

@ -2,8 +2,9 @@ package pgproto3
import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type Close struct {
@ -31,20 +32,18 @@ func (dst *Close) Decode(src []byte) error {
return nil
}
func (src *Close) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *Close) Encode(dst []byte) []byte {
dst = append(dst, 'C')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('C')
buf.Write(bigEndian.Uint32(0))
dst = append(dst, src.ObjectType)
dst = append(dst, src.Name...)
dst = append(dst, 0)
buf.WriteByte(src.ObjectType)
buf.WriteString(src.Name)
buf.WriteByte(0)
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
return buf.Bytes(), nil
return dst
}
func (src *Close) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *CloseComplete) Decode(src []byte) error {
return nil
}
func (src *CloseComplete) MarshalBinary() ([]byte, error) {
return []byte{'3', 0, 0, 0, 4}, nil
func (src *CloseComplete) Encode(dst []byte) []byte {
return append(dst, '3', 0, 0, 0, 4)
}
func (src *CloseComplete) MarshalJSON() ([]byte, error) {

View File

@ -3,6 +3,8 @@ package pgproto3
import (
"bytes"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type CommandComplete struct {
@ -22,17 +24,17 @@ func (dst *CommandComplete) Decode(src []byte) error {
return nil
}
func (src *CommandComplete) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *CommandComplete) Encode(dst []byte) []byte {
dst = append(dst, 'C')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('C')
buf.Write(bigEndian.Uint32(uint32(4 + len(src.CommandTag) + 1)))
dst = append(dst, src.CommandTag...)
dst = append(dst, 0)
buf.WriteString(src.CommandTag)
buf.WriteByte(0)
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}
func (src *CommandComplete) MarshalJSON() ([]byte, error) {

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type CopyBothResponse struct {
@ -37,20 +39,19 @@ func (dst *CopyBothResponse) Decode(src []byte) error {
return nil
}
func (src *CopyBothResponse) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('W')
buf.Write(bigEndian.Uint32(uint32(4 + 1 + 2 + 2*len(src.ColumnFormatCodes))))
buf.Write(bigEndian.Uint16(uint16(len(src.ColumnFormatCodes))))
func (src *CopyBothResponse) Encode(dst []byte) []byte {
dst = append(dst, 'W')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
for _, fc := range src.ColumnFormatCodes {
buf.Write(bigEndian.Uint16(fc))
dst = pgio.AppendUint16(dst, fc)
}
return buf.Bytes(), nil
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return dst
}
func (src *CopyBothResponse) MarshalJSON() ([]byte, error) {

View File

@ -1,9 +1,10 @@
package pgproto3
import (
"bytes"
"encoding/hex"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type CopyData struct {
@ -18,15 +19,11 @@ func (dst *CopyData) Decode(src []byte) error {
return nil
}
func (src *CopyData) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('d')
buf.Write(bigEndian.Uint32(uint32(4 + len(src.Data))))
buf.Write(src.Data)
return buf.Bytes(), nil
func (src *CopyData) Encode(dst []byte) []byte {
dst = append(dst, 'd')
dst = pgio.AppendInt32(dst, int32(4+len(src.Data)))
dst = append(dst, src.Data...)
return dst
}
func (src *CopyData) MarshalJSON() ([]byte, error) {

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type CopyInResponse struct {
@ -37,20 +39,19 @@ func (dst *CopyInResponse) Decode(src []byte) error {
return nil
}
func (src *CopyInResponse) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('G')
buf.Write(bigEndian.Uint32(uint32(4 + 1 + 2 + 2*len(src.ColumnFormatCodes))))
buf.Write(bigEndian.Uint16(uint16(len(src.ColumnFormatCodes))))
func (src *CopyInResponse) Encode(dst []byte) []byte {
dst = append(dst, 'G')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
for _, fc := range src.ColumnFormatCodes {
buf.Write(bigEndian.Uint16(fc))
dst = pgio.AppendUint16(dst, fc)
}
return buf.Bytes(), nil
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return dst
}
func (src *CopyInResponse) MarshalJSON() ([]byte, error) {

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type CopyOutResponse struct {
@ -37,20 +39,19 @@ func (dst *CopyOutResponse) Decode(src []byte) error {
return nil
}
func (src *CopyOutResponse) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('H')
buf.Write(bigEndian.Uint32(uint32(4 + 1 + 2 + 2*len(src.ColumnFormatCodes))))
buf.Write(bigEndian.Uint16(uint16(len(src.ColumnFormatCodes))))
func (src *CopyOutResponse) Encode(dst []byte) []byte {
dst = append(dst, 'H')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
for _, fc := range src.ColumnFormatCodes {
buf.Write(bigEndian.Uint16(fc))
dst = pgio.AppendUint16(dst, fc)
}
return buf.Bytes(), nil
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return dst
}
func (src *CopyOutResponse) MarshalJSON() ([]byte, error) {

View File

@ -1,10 +1,11 @@
package pgproto3
import (
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type DataRow struct {
@ -58,28 +59,25 @@ func (dst *DataRow) Decode(src []byte) error {
return nil
}
func (src *DataRow) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('D')
buf.Write(bigEndian.Uint32(0))
buf.Write(bigEndian.Uint16(uint16(len(src.Values))))
func (src *DataRow) Encode(dst []byte) []byte {
dst = append(dst, 'D')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint16(dst, uint16(len(src.Values)))
for _, v := range src.Values {
if v == nil {
buf.Write(bigEndian.Int32(-1))
dst = pgio.AppendInt32(dst, -1)
continue
}
buf.Write(bigEndian.Int32(int32(len(v))))
buf.Write(v)
dst = pgio.AppendInt32(dst, int32(len(v)))
dst = append(dst, v...)
}
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}
func (src *DataRow) MarshalJSON() ([]byte, error) {

View File

@ -2,8 +2,9 @@ package pgproto3
import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type Describe struct {
@ -31,20 +32,18 @@ func (dst *Describe) Decode(src []byte) error {
return nil
}
func (src *Describe) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *Describe) Encode(dst []byte) []byte {
dst = append(dst, 'D')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('D')
buf.Write(bigEndian.Uint32(0))
dst = append(dst, src.ObjectType)
dst = append(dst, src.Name...)
dst = append(dst, 0)
buf.WriteByte(src.ObjectType)
buf.WriteString(src.Name)
buf.WriteByte(0)
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
return buf.Bytes(), nil
return dst
}
func (src *Describe) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *EmptyQueryResponse) Decode(src []byte) error {
return nil
}
func (src *EmptyQueryResponse) MarshalBinary() ([]byte, error) {
return []byte{'I', 0, 0, 0, 4}, nil
func (src *EmptyQueryResponse) Encode(dst []byte) []byte {
return append(dst, 'I', 0, 0, 0, 4)
}
func (src *EmptyQueryResponse) MarshalJSON() ([]byte, error) {

View File

@ -103,11 +103,11 @@ func (dst *ErrorResponse) Decode(src []byte) error {
return nil
}
func (src *ErrorResponse) MarshalBinary() ([]byte, error) {
return src.marshalBinary('E')
func (src *ErrorResponse) Encode(dst []byte) []byte {
return append(dst, src.marshalBinary('E')...)
}
func (src *ErrorResponse) marshalBinary(typeByte byte) ([]byte, error) {
func (src *ErrorResponse) marshalBinary(typeByte byte) []byte {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
@ -193,5 +193,5 @@ func (src *ErrorResponse) marshalBinary(typeByte byte) ([]byte, error) {
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
return buf.Bytes(), nil
return buf.Bytes()
}

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type Execute struct {
@ -30,21 +32,19 @@ func (dst *Execute) Decode(src []byte) error {
return nil
}
func (src *Execute) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *Execute) Encode(dst []byte) []byte {
dst = append(dst, 'E')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('E')
buf.Write(bigEndian.Uint32(0))
dst = append(dst, src.Portal...)
dst = append(dst, 0)
buf.WriteString(src.Portal)
buf.WriteByte(0)
dst = pgio.AppendUint32(dst, src.MaxRows)
buf.Write(bigEndian.Uint32(src.MaxRows))
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
return buf.Bytes(), nil
return dst
}
func (src *Execute) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *Flush) Decode(src []byte) error {
return nil
}
func (src *Flush) MarshalBinary() ([]byte, error) {
return []byte{'H', 0, 0, 0, 4}, nil
func (src *Flush) Encode(dst []byte) []byte {
return append(dst, 'H', 0, 0, 0, 4)
}
func (src *Flush) MarshalJSON() ([]byte, error) {

View File

@ -42,12 +42,7 @@ func NewFrontend(r io.Reader, w io.Writer) (*Frontend, error) {
}
func (b *Frontend) Send(msg FrontendMessage) error {
buf, err := msg.MarshalBinary()
if err != nil {
return nil
}
_, err = b.w.Write(buf)
_, err := b.w.Write(msg.Encode(nil))
return err
}

View File

@ -1,10 +1,11 @@
package pgproto3
import (
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type FunctionCallResponse struct {
@ -34,21 +35,21 @@ func (dst *FunctionCallResponse) Decode(src []byte) error {
return nil
}
func (src *FunctionCallResponse) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('V')
buf.Write(bigEndian.Uint32(uint32(4 + 4 + len(src.Result))))
func (src *FunctionCallResponse) Encode(dst []byte) []byte {
dst = append(dst, 'V')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
if src.Result == nil {
buf.Write(bigEndian.Int32(-1))
dst = pgio.AppendInt32(dst, -1)
} else {
buf.Write(bigEndian.Int32(int32(len(src.Result))))
buf.Write(src.Result)
dst = pgio.AppendInt32(dst, int32(len(src.Result)))
dst = append(dst, src.Result...)
}
return buf.Bytes(), nil
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return dst
}
func (src *FunctionCallResponse) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *NoData) Decode(src []byte) error {
return nil
}
func (src *NoData) MarshalBinary() ([]byte, error) {
return []byte{'n', 0, 0, 0, 4}, nil
func (src *NoData) Encode(dst []byte) []byte {
return append(dst, 'n', 0, 0, 0, 4)
}
func (src *NoData) MarshalJSON() ([]byte, error) {

View File

@ -8,6 +8,6 @@ func (dst *NoticeResponse) Decode(src []byte) error {
return (*ErrorResponse)(dst).Decode(src)
}
func (src *NoticeResponse) MarshalBinary() ([]byte, error) {
return (*ErrorResponse)(src).marshalBinary('N')
func (src *NoticeResponse) Encode(dst []byte) []byte {
return append(dst, (*ErrorResponse)(src).marshalBinary('N')...)
}

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type NotificationResponse struct {
@ -35,19 +37,19 @@ func (dst *NotificationResponse) Decode(src []byte) error {
return nil
}
func (src *NotificationResponse) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *NotificationResponse) Encode(dst []byte) []byte {
dst = append(dst, 'A')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('A')
buf.Write(bigEndian.Uint32(uint32(4 + 4 + len(src.Channel) + len(src.Payload))))
dst = append(dst, src.Channel...)
dst = append(dst, 0)
dst = append(dst, src.Payload...)
dst = append(dst, 0)
buf.WriteString(src.Channel)
buf.WriteByte(0)
buf.WriteString(src.Payload)
buf.WriteByte(0)
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}
func (src *NotificationResponse) MarshalJSON() ([]byte, error) {

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type ParameterDescription struct {
@ -33,20 +35,19 @@ func (dst *ParameterDescription) Decode(src []byte) error {
return nil
}
func (src *ParameterDescription) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('t')
buf.Write(bigEndian.Uint32(uint32(4 + 2 + 4*len(src.ParameterOIDs))))
buf.Write(bigEndian.Uint16(uint16(len(src.ParameterOIDs))))
func (src *ParameterDescription) Encode(dst []byte) []byte {
dst = append(dst, 't')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint16(dst, uint16(len(src.ParameterOIDs)))
for _, oid := range src.ParameterOIDs {
buf.Write(bigEndian.Uint32(oid))
dst = pgio.AppendUint32(dst, oid)
}
return buf.Bytes(), nil
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return dst
}
func (src *ParameterDescription) MarshalJSON() ([]byte, error) {

View File

@ -2,8 +2,9 @@ package pgproto3
import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type ParameterStatus struct {
@ -32,21 +33,19 @@ func (dst *ParameterStatus) Decode(src []byte) error {
return nil
}
func (src *ParameterStatus) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *ParameterStatus) Encode(dst []byte) []byte {
dst = append(dst, 'S')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('S')
buf.Write(bigEndian.Uint32(0))
dst = append(dst, src.Name...)
dst = append(dst, 0)
dst = append(dst, src.Value...)
dst = append(dst, 0)
buf.WriteString(src.Name)
buf.WriteByte(0)
buf.WriteString(src.Value)
buf.WriteByte(0)
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
return buf.Bytes(), nil
return dst
}
func (ps *ParameterStatus) MarshalJSON() ([]byte, error) {

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type Parse struct {
@ -44,27 +46,24 @@ func (dst *Parse) Decode(src []byte) error {
return nil
}
func (src *Parse) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
func (src *Parse) Encode(dst []byte) []byte {
dst = append(dst, 'P')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('P')
buf.Write(bigEndian.Uint32(0))
dst = append(dst, src.Name...)
dst = append(dst, 0)
dst = append(dst, src.Query...)
dst = append(dst, 0)
buf.WriteString(src.Name)
buf.WriteByte(0)
buf.WriteString(src.Query)
buf.WriteByte(0)
buf.Write(bigEndian.Uint16(uint16(len(src.ParameterOIDs))))
for _, v := range src.ParameterOIDs {
buf.Write(bigEndian.Uint32(v))
dst = pgio.AppendUint16(dst, uint16(len(src.ParameterOIDs)))
for _, oid := range src.ParameterOIDs {
dst = pgio.AppendUint32(dst, oid)
}
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}
func (src *Parse) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *ParseComplete) Decode(src []byte) error {
return nil
}
func (src *ParseComplete) MarshalBinary() ([]byte, error) {
return []byte{'1', 0, 0, 0, 4}, nil
func (src *ParseComplete) Encode(dst []byte) []byte {
return append(dst, '1', 0, 0, 0, 4)
}
func (src *ParseComplete) MarshalJSON() ([]byte, error) {

View File

@ -3,6 +3,8 @@ package pgproto3
import (
"bytes"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type PasswordMessage struct {
@ -23,14 +25,14 @@ func (dst *PasswordMessage) Decode(src []byte) error {
return nil
}
func (src *PasswordMessage) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('p')
buf.Write(bigEndian.Uint32(uint32(4 + len(src.Password) + 1)))
buf.WriteString(src.Password)
buf.WriteByte(0)
return buf.Bytes(), nil
func (src *PasswordMessage) Encode(dst []byte) []byte {
dst = append(dst, 'p')
dst = pgio.AppendInt32(dst, int32(4+len(src.Password)+1))
dst = append(dst, src.Password...)
dst = append(dst, 0)
return dst
}
func (src *PasswordMessage) MarshalJSON() ([]byte, error) {

View File

@ -4,12 +4,13 @@ import "fmt"
// Message is the interface implemented by an object that can decode and encode
// a particular PostgreSQL message.
//
// Decode is allowed and expected to retain a reference to data after
// returning (unlike encoding.BinaryUnmarshaler).
type Message interface {
// Decode is allowed and expected to retain a reference to data after
// returning (unlike encoding.BinaryUnmarshaler).
Decode(data []byte) error
MarshalBinary() (data []byte, err error)
// Encode appends itself to dst and returns the new buffer.
Encode(dst []byte) []byte
}
type FrontendMessage interface {

View File

@ -3,6 +3,8 @@ package pgproto3
import (
"bytes"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
type Query struct {
@ -22,14 +24,14 @@ func (dst *Query) Decode(src []byte) error {
return nil
}
func (src *Query) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('Q')
buf.Write(bigEndian.Uint32(uint32(4 + len(src.String) + 1)))
buf.WriteString(src.String)
buf.WriteByte(0)
return buf.Bytes(), nil
func (src *Query) Encode(dst []byte) []byte {
dst = append(dst, 'Q')
dst = pgio.AppendInt32(dst, int32(4+len(src.String)+1))
dst = append(dst, src.String...)
dst = append(dst, 0)
return dst
}
func (src *Query) MarshalJSON() ([]byte, error) {

View File

@ -20,8 +20,8 @@ func (dst *ReadyForQuery) Decode(src []byte) error {
return nil
}
func (src *ReadyForQuery) MarshalBinary() ([]byte, error) {
return []byte{'Z', 0, 0, 0, 5, src.TxStatus}, nil
func (src *ReadyForQuery) Encode(dst []byte) []byte {
return append(dst, 'Z', 0, 0, 0, 5, src.TxStatus)
}
func (src *ReadyForQuery) MarshalJSON() ([]byte, error) {

View File

@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"github.com/jackc/pgx/pgio"
)
const (
@ -64,30 +66,27 @@ func (dst *RowDescription) Decode(src []byte) error {
return nil
}
func (src *RowDescription) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.WriteByte('T')
buf.Write(bigEndian.Uint32(0))
buf.Write(bigEndian.Uint16(uint16(len(src.Fields))))
func (src *RowDescription) Encode(dst []byte) []byte {
dst = append(dst, 'T')
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint16(dst, uint16(len(src.Fields)))
for _, fd := range src.Fields {
buf.WriteString(fd.Name)
buf.WriteByte(0)
dst = append(dst, fd.Name...)
dst = append(dst, 0)
buf.Write(bigEndian.Uint32(fd.TableOID))
buf.Write(bigEndian.Uint16(fd.TableAttributeNumber))
buf.Write(bigEndian.Uint32(fd.DataTypeOID))
buf.Write(bigEndian.Uint16(uint16(fd.DataTypeSize)))
buf.Write(bigEndian.Uint32(fd.TypeModifier))
buf.Write(bigEndian.Uint16(uint16(fd.Format)))
dst = pgio.AppendUint32(dst, fd.TableOID)
dst = pgio.AppendUint16(dst, fd.TableAttributeNumber)
dst = pgio.AppendUint32(dst, fd.DataTypeOID)
dst = pgio.AppendInt16(dst, fd.DataTypeSize)
dst = pgio.AppendUint32(dst, fd.TypeModifier)
dst = pgio.AppendInt16(dst, fd.Format)
}
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}
func (src *RowDescription) MarshalJSON() ([]byte, error) {

View File

@ -5,6 +5,8 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
"github.com/jackc/pgx/pgio"
)
const (
@ -64,22 +66,22 @@ func (dst *StartupMessage) Decode(src []byte) error {
return nil
}
func (src *StartupMessage) MarshalBinary() ([]byte, error) {
var bigEndian BigEndianBuf
buf := &bytes.Buffer{}
buf.Write(bigEndian.Uint32(0))
buf.Write(bigEndian.Uint32(src.ProtocolVersion))
func (src *StartupMessage) Encode(dst []byte) []byte {
sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
dst = pgio.AppendUint32(dst, src.ProtocolVersion)
for k, v := range src.Parameters {
buf.WriteString(k)
buf.WriteByte(0)
buf.WriteString(v)
buf.WriteByte(0)
dst = append(dst, k...)
dst = append(dst, 0)
dst = append(dst, v...)
dst = append(dst, 0)
}
buf.WriteByte(0)
dst = append(dst, 0)
binary.BigEndian.PutUint32(buf.Bytes()[0:4], uint32(buf.Len()))
pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
return buf.Bytes(), nil
return dst
}
func (src *StartupMessage) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *Sync) Decode(src []byte) error {
return nil
}
func (src *Sync) MarshalBinary() ([]byte, error) {
return []byte{'S', 0, 0, 0, 4}, nil
func (src *Sync) Encode(dst []byte) []byte {
return append(dst, 'S', 0, 0, 0, 4)
}
func (src *Sync) MarshalJSON() ([]byte, error) {

View File

@ -16,8 +16,8 @@ func (dst *Terminate) Decode(src []byte) error {
return nil
}
func (src *Terminate) MarshalBinary() ([]byte, error) {
return []byte{'X', 0, 0, 0, 4}, nil
func (src *Terminate) Encode(dst []byte) []byte {
return append(dst, 'X', 0, 0, 0, 4)
}
func (src *Terminate) MarshalJSON() ([]byte, error) {