2
0

Replace MarshalBinary with Encode

This new approach can avoid allocations.
This commit is contained in:
Jack Christensen
2017-05-26 17:00:44 -05:00
parent b1934ad4c2
commit d6312305ae
35 changed files with 277 additions and 285 deletions
+10 -10
View File
@@ -1,9 +1,10 @@
package pgproto3 package pgproto3
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/jackc/pgx/pgio"
) )
const ( const (
@@ -36,19 +37,18 @@ func (dst *Authentication) Decode(src []byte) error {
return nil return nil
} }
func (src *Authentication) MarshalBinary() ([]byte, error) { func (src *Authentication) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'R')
buf := &bytes.Buffer{} sp := len(dst)
buf.WriteByte('R') dst = pgio.AppendInt32(dst, -1)
buf.Write(bigEndian.Uint32(0)) dst = pgio.AppendUint32(dst, src.Type)
buf.Write(bigEndian.Uint32(src.Type))
switch src.Type { switch src.Type {
case AuthTypeMD5Password: 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
} }
+1 -6
View File
@@ -32,12 +32,7 @@ func NewBackend(r io.Reader, w io.Writer) (*Backend, error) {
} }
func (b *Backend) Send(msg BackendMessage) error { func (b *Backend) Send(msg BackendMessage) error {
buf, err := msg.MarshalBinary() _, err := b.w.Write(msg.Encode(nil))
if err != nil {
return nil
}
_, err = b.w.Write(buf)
return err return err
} }
+8 -9
View File
@@ -1,9 +1,10 @@
package pgproto3 package pgproto3
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type BackendKeyData struct { type BackendKeyData struct {
@@ -24,14 +25,12 @@ func (dst *BackendKeyData) Decode(src []byte) error {
return nil return nil
} }
func (src *BackendKeyData) MarshalBinary() ([]byte, error) { func (src *BackendKeyData) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'K')
buf := &bytes.Buffer{} dst = pgio.AppendUint32(dst, 12)
buf.WriteByte('K') dst = pgio.AppendUint32(dst, src.ProcessID)
buf.Write(bigEndian.Uint32(12)) dst = pgio.AppendUint32(dst, src.SecretKey)
buf.Write(bigEndian.Uint32(src.ProcessID)) return dst
buf.Write(bigEndian.Uint32(src.SecretKey))
return buf.Bytes(), nil
} }
func (src *BackendKeyData) MarshalJSON() ([]byte, error) { func (src *BackendKeyData) MarshalJSON() ([]byte, error) {
+20 -23
View File
@@ -5,6 +5,8 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type Bind struct { type Bind struct {
@@ -101,45 +103,40 @@ func (dst *Bind) Decode(src []byte) error {
return nil return nil
} }
func (src *Bind) MarshalBinary() ([]byte, error) { func (src *Bind) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'B')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('B') dst = append(dst, src.DestinationPortal...)
buf.Write(bigEndian.Uint32(0)) dst = append(dst, 0)
dst = append(dst, src.PreparedStatement...)
buf.WriteString(src.DestinationPortal) dst = append(dst, 0)
buf.WriteByte(0)
buf.WriteString(src.PreparedStatement)
buf.WriteByte(0)
buf.Write(bigEndian.Uint16(uint16(len(src.ParameterFormatCodes))))
dst = pgio.AppendUint16(dst, uint16(len(src.ParameterFormatCodes)))
for _, fc := range 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 { for _, p := range src.Parameters {
if p == nil { if p == nil {
buf.Write(bigEndian.Int32(-1)) dst = pgio.AppendInt32(dst, -1)
continue continue
} }
buf.Write(bigEndian.Int32(int32(len(p)))) dst = pgio.AppendInt32(dst, int32(len(p)))
buf.Write(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 { 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) { func (src *Bind) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *BindComplete) Decode(src []byte) error {
return nil return nil
} }
func (src *BindComplete) MarshalBinary() ([]byte, error) { func (src *BindComplete) Encode(dst []byte) []byte {
return []byte{'2', 0, 0, 0, 4}, nil return append(dst, '2', 0, 0, 0, 4)
} }
func (src *BindComplete) MarshalJSON() ([]byte, error) { func (src *BindComplete) MarshalJSON() ([]byte, error) {
+11 -12
View File
@@ -2,8 +2,9 @@ package pgproto3
import ( import (
"bytes" "bytes"
"encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type Close struct { type Close struct {
@@ -31,20 +32,18 @@ func (dst *Close) Decode(src []byte) error {
return nil return nil
} }
func (src *Close) MarshalBinary() ([]byte, error) { func (src *Close) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'C')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('C') dst = append(dst, src.ObjectType)
buf.Write(bigEndian.Uint32(0)) dst = append(dst, src.Name...)
dst = append(dst, 0)
buf.WriteByte(src.ObjectType) pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
buf.WriteString(src.Name)
buf.WriteByte(0)
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1)) return dst
return buf.Bytes(), nil
} }
func (src *Close) MarshalJSON() ([]byte, error) { func (src *Close) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *CloseComplete) Decode(src []byte) error {
return nil return nil
} }
func (src *CloseComplete) MarshalBinary() ([]byte, error) { func (src *CloseComplete) Encode(dst []byte) []byte {
return []byte{'3', 0, 0, 0, 4}, nil return append(dst, '3', 0, 0, 0, 4)
} }
func (src *CloseComplete) MarshalJSON() ([]byte, error) { func (src *CloseComplete) MarshalJSON() ([]byte, error) {
+10 -8
View File
@@ -3,6 +3,8 @@ package pgproto3
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type CommandComplete struct { type CommandComplete struct {
@@ -22,17 +24,17 @@ func (dst *CommandComplete) Decode(src []byte) error {
return nil return nil
} }
func (src *CommandComplete) MarshalBinary() ([]byte, error) { func (src *CommandComplete) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'C')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('C') dst = append(dst, src.CommandTag...)
buf.Write(bigEndian.Uint32(uint32(4 + len(src.CommandTag) + 1))) dst = append(dst, 0)
buf.WriteString(src.CommandTag) pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
buf.WriteByte(0)
return buf.Bytes(), nil return dst
} }
func (src *CommandComplete) MarshalJSON() ([]byte, error) { func (src *CommandComplete) MarshalJSON() ([]byte, error) {
+11 -10
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type CopyBothResponse struct { type CopyBothResponse struct {
@@ -37,20 +39,19 @@ func (dst *CopyBothResponse) Decode(src []byte) error {
return nil return nil
} }
func (src *CopyBothResponse) MarshalBinary() ([]byte, error) { func (src *CopyBothResponse) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'W')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('W')
buf.Write(bigEndian.Uint32(uint32(4 + 1 + 2 + 2*len(src.ColumnFormatCodes))))
buf.Write(bigEndian.Uint16(uint16(len(src.ColumnFormatCodes))))
dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
for _, fc := range 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) { func (src *CopyBothResponse) MarshalJSON() ([]byte, error) {
+7 -10
View File
@@ -1,9 +1,10 @@
package pgproto3 package pgproto3
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type CopyData struct { type CopyData struct {
@@ -18,15 +19,11 @@ func (dst *CopyData) Decode(src []byte) error {
return nil return nil
} }
func (src *CopyData) MarshalBinary() ([]byte, error) { func (src *CopyData) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'd')
buf := &bytes.Buffer{} dst = pgio.AppendInt32(dst, int32(4+len(src.Data)))
dst = append(dst, src.Data...)
buf.WriteByte('d') return dst
buf.Write(bigEndian.Uint32(uint32(4 + len(src.Data))))
buf.Write(src.Data)
return buf.Bytes(), nil
} }
func (src *CopyData) MarshalJSON() ([]byte, error) { func (src *CopyData) MarshalJSON() ([]byte, error) {
+11 -10
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type CopyInResponse struct { type CopyInResponse struct {
@@ -37,20 +39,19 @@ func (dst *CopyInResponse) Decode(src []byte) error {
return nil return nil
} }
func (src *CopyInResponse) MarshalBinary() ([]byte, error) { func (src *CopyInResponse) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'G')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('G')
buf.Write(bigEndian.Uint32(uint32(4 + 1 + 2 + 2*len(src.ColumnFormatCodes))))
buf.Write(bigEndian.Uint16(uint16(len(src.ColumnFormatCodes))))
dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
for _, fc := range 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) { func (src *CopyInResponse) MarshalJSON() ([]byte, error) {
+11 -10
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type CopyOutResponse struct { type CopyOutResponse struct {
@@ -37,20 +39,19 @@ func (dst *CopyOutResponse) Decode(src []byte) error {
return nil return nil
} }
func (src *CopyOutResponse) MarshalBinary() ([]byte, error) { func (src *CopyOutResponse) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'H')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('H')
buf.Write(bigEndian.Uint32(uint32(4 + 1 + 2 + 2*len(src.ColumnFormatCodes))))
buf.Write(bigEndian.Uint16(uint16(len(src.ColumnFormatCodes))))
dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
for _, fc := range 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) { func (src *CopyOutResponse) MarshalJSON() ([]byte, error) {
+12 -14
View File
@@ -1,10 +1,11 @@
package pgproto3 package pgproto3
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type DataRow struct { type DataRow struct {
@@ -58,28 +59,25 @@ func (dst *DataRow) Decode(src []byte) error {
return nil return nil
} }
func (src *DataRow) MarshalBinary() ([]byte, error) { func (src *DataRow) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'D')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('D')
buf.Write(bigEndian.Uint32(0))
buf.Write(bigEndian.Uint16(uint16(len(src.Values))))
dst = pgio.AppendUint16(dst, uint16(len(src.Values)))
for _, v := range src.Values { for _, v := range src.Values {
if v == nil { if v == nil {
buf.Write(bigEndian.Int32(-1)) dst = pgio.AppendInt32(dst, -1)
continue continue
} }
buf.Write(bigEndian.Int32(int32(len(v)))) dst = pgio.AppendInt32(dst, int32(len(v)))
buf.Write(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) { func (src *DataRow) MarshalJSON() ([]byte, error) {
+11 -12
View File
@@ -2,8 +2,9 @@ package pgproto3
import ( import (
"bytes" "bytes"
"encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type Describe struct { type Describe struct {
@@ -31,20 +32,18 @@ func (dst *Describe) Decode(src []byte) error {
return nil return nil
} }
func (src *Describe) MarshalBinary() ([]byte, error) { func (src *Describe) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'D')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('D') dst = append(dst, src.ObjectType)
buf.Write(bigEndian.Uint32(0)) dst = append(dst, src.Name...)
dst = append(dst, 0)
buf.WriteByte(src.ObjectType) pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
buf.WriteString(src.Name)
buf.WriteByte(0)
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1)) return dst
return buf.Bytes(), nil
} }
func (src *Describe) MarshalJSON() ([]byte, error) { func (src *Describe) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *EmptyQueryResponse) Decode(src []byte) error {
return nil return nil
} }
func (src *EmptyQueryResponse) MarshalBinary() ([]byte, error) { func (src *EmptyQueryResponse) Encode(dst []byte) []byte {
return []byte{'I', 0, 0, 0, 4}, nil return append(dst, 'I', 0, 0, 0, 4)
} }
func (src *EmptyQueryResponse) MarshalJSON() ([]byte, error) { func (src *EmptyQueryResponse) MarshalJSON() ([]byte, error) {
+4 -4
View File
@@ -103,11 +103,11 @@ func (dst *ErrorResponse) Decode(src []byte) error {
return nil return nil
} }
func (src *ErrorResponse) MarshalBinary() ([]byte, error) { func (src *ErrorResponse) Encode(dst []byte) []byte {
return src.marshalBinary('E') return append(dst, src.marshalBinary('E')...)
} }
func (src *ErrorResponse) marshalBinary(typeByte byte) ([]byte, error) { func (src *ErrorResponse) marshalBinary(typeByte byte) []byte {
var bigEndian BigEndianBuf var bigEndian BigEndianBuf
buf := &bytes.Buffer{} 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)) binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1))
return buf.Bytes(), nil return buf.Bytes()
} }
+11 -11
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type Execute struct { type Execute struct {
@@ -30,21 +32,19 @@ func (dst *Execute) Decode(src []byte) error {
return nil return nil
} }
func (src *Execute) MarshalBinary() ([]byte, error) { func (src *Execute) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'E')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('E') dst = append(dst, src.Portal...)
buf.Write(bigEndian.Uint32(0)) dst = append(dst, 0)
buf.WriteString(src.Portal) dst = pgio.AppendUint32(dst, src.MaxRows)
buf.WriteByte(0)
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 dst
return buf.Bytes(), nil
} }
func (src *Execute) MarshalJSON() ([]byte, error) { func (src *Execute) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *Flush) Decode(src []byte) error {
return nil return nil
} }
func (src *Flush) MarshalBinary() ([]byte, error) { func (src *Flush) Encode(dst []byte) []byte {
return []byte{'H', 0, 0, 0, 4}, nil return append(dst, 'H', 0, 0, 0, 4)
} }
func (src *Flush) MarshalJSON() ([]byte, error) { func (src *Flush) MarshalJSON() ([]byte, error) {
+1 -6
View File
@@ -42,12 +42,7 @@ func NewFrontend(r io.Reader, w io.Writer) (*Frontend, error) {
} }
func (b *Frontend) Send(msg FrontendMessage) error { func (b *Frontend) Send(msg FrontendMessage) error {
buf, err := msg.MarshalBinary() _, err := b.w.Write(msg.Encode(nil))
if err != nil {
return nil
}
_, err = b.w.Write(buf)
return err return err
} }
+12 -11
View File
@@ -1,10 +1,11 @@
package pgproto3 package pgproto3
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type FunctionCallResponse struct { type FunctionCallResponse struct {
@@ -34,21 +35,21 @@ func (dst *FunctionCallResponse) Decode(src []byte) error {
return nil return nil
} }
func (src *FunctionCallResponse) MarshalBinary() ([]byte, error) { func (src *FunctionCallResponse) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'V')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('V')
buf.Write(bigEndian.Uint32(uint32(4 + 4 + len(src.Result))))
if src.Result == nil { if src.Result == nil {
buf.Write(bigEndian.Int32(-1)) dst = pgio.AppendInt32(dst, -1)
} else { } else {
buf.Write(bigEndian.Int32(int32(len(src.Result)))) dst = pgio.AppendInt32(dst, int32(len(src.Result)))
buf.Write(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) { func (src *FunctionCallResponse) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *NoData) Decode(src []byte) error {
return nil return nil
} }
func (src *NoData) MarshalBinary() ([]byte, error) { func (src *NoData) Encode(dst []byte) []byte {
return []byte{'n', 0, 0, 0, 4}, nil return append(dst, 'n', 0, 0, 0, 4)
} }
func (src *NoData) MarshalJSON() ([]byte, error) { func (src *NoData) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -8,6 +8,6 @@ func (dst *NoticeResponse) Decode(src []byte) error {
return (*ErrorResponse)(dst).Decode(src) return (*ErrorResponse)(dst).Decode(src)
} }
func (src *NoticeResponse) MarshalBinary() ([]byte, error) { func (src *NoticeResponse) Encode(dst []byte) []byte {
return (*ErrorResponse)(src).marshalBinary('N') return append(dst, (*ErrorResponse)(src).marshalBinary('N')...)
} }
+12 -10
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type NotificationResponse struct { type NotificationResponse struct {
@@ -35,19 +37,19 @@ func (dst *NotificationResponse) Decode(src []byte) error {
return nil return nil
} }
func (src *NotificationResponse) MarshalBinary() ([]byte, error) { func (src *NotificationResponse) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'A')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('A') dst = append(dst, src.Channel...)
buf.Write(bigEndian.Uint32(uint32(4 + 4 + len(src.Channel) + len(src.Payload)))) dst = append(dst, 0)
dst = append(dst, src.Payload...)
dst = append(dst, 0)
buf.WriteString(src.Channel) pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
buf.WriteByte(0)
buf.WriteString(src.Payload)
buf.WriteByte(0)
return buf.Bytes(), nil return dst
} }
func (src *NotificationResponse) MarshalJSON() ([]byte, error) { func (src *NotificationResponse) MarshalJSON() ([]byte, error) {
+11 -10
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type ParameterDescription struct { type ParameterDescription struct {
@@ -33,20 +35,19 @@ func (dst *ParameterDescription) Decode(src []byte) error {
return nil return nil
} }
func (src *ParameterDescription) MarshalBinary() ([]byte, error) { func (src *ParameterDescription) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 't')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('t')
buf.Write(bigEndian.Uint32(uint32(4 + 2 + 4*len(src.ParameterOIDs))))
buf.Write(bigEndian.Uint16(uint16(len(src.ParameterOIDs))))
dst = pgio.AppendUint16(dst, uint16(len(src.ParameterOIDs)))
for _, oid := range 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) { func (src *ParameterDescription) MarshalJSON() ([]byte, error) {
+12 -13
View File
@@ -2,8 +2,9 @@ package pgproto3
import ( import (
"bytes" "bytes"
"encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type ParameterStatus struct { type ParameterStatus struct {
@@ -32,21 +33,19 @@ func (dst *ParameterStatus) Decode(src []byte) error {
return nil return nil
} }
func (src *ParameterStatus) MarshalBinary() ([]byte, error) { func (src *ParameterStatus) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'S')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('S') dst = append(dst, src.Name...)
buf.Write(bigEndian.Uint32(0)) dst = append(dst, 0)
dst = append(dst, src.Value...)
dst = append(dst, 0)
buf.WriteString(src.Name) pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
buf.WriteByte(0)
buf.WriteString(src.Value)
buf.WriteByte(0)
binary.BigEndian.PutUint32(buf.Bytes()[1:5], uint32(buf.Len()-1)) return dst
return buf.Bytes(), nil
} }
func (ps *ParameterStatus) MarshalJSON() ([]byte, error) { func (ps *ParameterStatus) MarshalJSON() ([]byte, error) {
+15 -16
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type Parse struct { type Parse struct {
@@ -44,27 +46,24 @@ func (dst *Parse) Decode(src []byte) error {
return nil return nil
} }
func (src *Parse) MarshalBinary() ([]byte, error) { func (src *Parse) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'P')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('P') dst = append(dst, src.Name...)
buf.Write(bigEndian.Uint32(0)) dst = append(dst, 0)
dst = append(dst, src.Query...)
dst = append(dst, 0)
buf.WriteString(src.Name) dst = pgio.AppendUint16(dst, uint16(len(src.ParameterOIDs)))
buf.WriteByte(0) for _, oid := range src.ParameterOIDs {
buf.WriteString(src.Query) dst = pgio.AppendUint32(dst, oid)
buf.WriteByte(0)
buf.Write(bigEndian.Uint16(uint16(len(src.ParameterOIDs))))
for _, v := range src.ParameterOIDs {
buf.Write(bigEndian.Uint32(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 *Parse) MarshalJSON() ([]byte, error) { func (src *Parse) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *ParseComplete) Decode(src []byte) error {
return nil return nil
} }
func (src *ParseComplete) MarshalBinary() ([]byte, error) { func (src *ParseComplete) Encode(dst []byte) []byte {
return []byte{'1', 0, 0, 0, 4}, nil return append(dst, '1', 0, 0, 0, 4)
} }
func (src *ParseComplete) MarshalJSON() ([]byte, error) { func (src *ParseComplete) MarshalJSON() ([]byte, error) {
+10 -8
View File
@@ -3,6 +3,8 @@ package pgproto3
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type PasswordMessage struct { type PasswordMessage struct {
@@ -23,14 +25,14 @@ func (dst *PasswordMessage) Decode(src []byte) error {
return nil return nil
} }
func (src *PasswordMessage) MarshalBinary() ([]byte, error) { func (src *PasswordMessage) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'p')
buf := &bytes.Buffer{} dst = pgio.AppendInt32(dst, int32(4+len(src.Password)+1))
buf.WriteByte('p')
buf.Write(bigEndian.Uint32(uint32(4 + len(src.Password) + 1))) dst = append(dst, src.Password...)
buf.WriteString(src.Password) dst = append(dst, 0)
buf.WriteByte(0)
return buf.Bytes(), nil return dst
} }
func (src *PasswordMessage) MarshalJSON() ([]byte, error) { func (src *PasswordMessage) MarshalJSON() ([]byte, error) {
+5 -4
View File
@@ -4,12 +4,13 @@ import "fmt"
// Message is the interface implemented by an object that can decode and encode // Message is the interface implemented by an object that can decode and encode
// a particular PostgreSQL message. // a particular PostgreSQL message.
//
// Decode is allowed and expected to retain a reference to data after
// returning (unlike encoding.BinaryUnmarshaler).
type Message interface { type Message interface {
// Decode is allowed and expected to retain a reference to data after
// returning (unlike encoding.BinaryUnmarshaler).
Decode(data []byte) error 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 { type FrontendMessage interface {
+10 -8
View File
@@ -3,6 +3,8 @@ package pgproto3
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
type Query struct { type Query struct {
@@ -22,14 +24,14 @@ func (dst *Query) Decode(src []byte) error {
return nil return nil
} }
func (src *Query) MarshalBinary() ([]byte, error) { func (src *Query) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'Q')
buf := &bytes.Buffer{} dst = pgio.AppendInt32(dst, int32(4+len(src.String)+1))
buf.WriteByte('Q')
buf.Write(bigEndian.Uint32(uint32(4 + len(src.String) + 1))) dst = append(dst, src.String...)
buf.WriteString(src.String) dst = append(dst, 0)
buf.WriteByte(0)
return buf.Bytes(), nil return dst
} }
func (src *Query) MarshalJSON() ([]byte, error) { func (src *Query) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -20,8 +20,8 @@ func (dst *ReadyForQuery) Decode(src []byte) error {
return nil return nil
} }
func (src *ReadyForQuery) MarshalBinary() ([]byte, error) { func (src *ReadyForQuery) Encode(dst []byte) []byte {
return []byte{'Z', 0, 0, 0, 5, src.TxStatus}, nil return append(dst, 'Z', 0, 0, 0, 5, src.TxStatus)
} }
func (src *ReadyForQuery) MarshalJSON() ([]byte, error) { func (src *ReadyForQuery) MarshalJSON() ([]byte, error) {
+17 -18
View File
@@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/jackc/pgx/pgio"
) )
const ( const (
@@ -64,30 +66,27 @@ func (dst *RowDescription) Decode(src []byte) error {
return nil return nil
} }
func (src *RowDescription) MarshalBinary() ([]byte, error) { func (src *RowDescription) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf dst = append(dst, 'T')
buf := &bytes.Buffer{} sp := len(dst)
dst = pgio.AppendInt32(dst, -1)
buf.WriteByte('T')
buf.Write(bigEndian.Uint32(0))
buf.Write(bigEndian.Uint16(uint16(len(src.Fields))))
dst = pgio.AppendUint16(dst, uint16(len(src.Fields)))
for _, fd := range src.Fields { for _, fd := range src.Fields {
buf.WriteString(fd.Name) dst = append(dst, fd.Name...)
buf.WriteByte(0) dst = append(dst, 0)
buf.Write(bigEndian.Uint32(fd.TableOID)) dst = pgio.AppendUint32(dst, fd.TableOID)
buf.Write(bigEndian.Uint16(fd.TableAttributeNumber)) dst = pgio.AppendUint16(dst, fd.TableAttributeNumber)
buf.Write(bigEndian.Uint32(fd.DataTypeOID)) dst = pgio.AppendUint32(dst, fd.DataTypeOID)
buf.Write(bigEndian.Uint16(uint16(fd.DataTypeSize))) dst = pgio.AppendInt16(dst, fd.DataTypeSize)
buf.Write(bigEndian.Uint32(fd.TypeModifier)) dst = pgio.AppendUint32(dst, fd.TypeModifier)
buf.Write(bigEndian.Uint16(uint16(fd.Format))) 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) { func (src *RowDescription) MarshalJSON() ([]byte, error) {
+14 -12
View File
@@ -5,6 +5,8 @@ import (
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/jackc/pgx/pgio"
) )
const ( const (
@@ -64,22 +66,22 @@ func (dst *StartupMessage) Decode(src []byte) error {
return nil return nil
} }
func (src *StartupMessage) MarshalBinary() ([]byte, error) { func (src *StartupMessage) Encode(dst []byte) []byte {
var bigEndian BigEndianBuf sp := len(dst)
buf := &bytes.Buffer{} dst = pgio.AppendInt32(dst, -1)
buf.Write(bigEndian.Uint32(0))
buf.Write(bigEndian.Uint32(src.ProtocolVersion)) dst = pgio.AppendUint32(dst, src.ProtocolVersion)
for k, v := range src.Parameters { for k, v := range src.Parameters {
buf.WriteString(k) dst = append(dst, k...)
buf.WriteByte(0) dst = append(dst, 0)
buf.WriteString(v) dst = append(dst, v...)
buf.WriteByte(0) 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) { func (src *StartupMessage) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *Sync) Decode(src []byte) error {
return nil return nil
} }
func (src *Sync) MarshalBinary() ([]byte, error) { func (src *Sync) Encode(dst []byte) []byte {
return []byte{'S', 0, 0, 0, 4}, nil return append(dst, 'S', 0, 0, 0, 4)
} }
func (src *Sync) MarshalJSON() ([]byte, error) { func (src *Sync) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -16,8 +16,8 @@ func (dst *Terminate) Decode(src []byte) error {
return nil return nil
} }
func (src *Terminate) MarshalBinary() ([]byte, error) { func (src *Terminate) Encode(dst []byte) []byte {
return []byte{'X', 0, 0, 0, 4}, nil return append(dst, 'X', 0, 0, 0, 4)
} }
func (src *Terminate) MarshalJSON() ([]byte, error) { func (src *Terminate) MarshalJSON() ([]byte, error) {