...

Source file src/github.com/jackc/pgproto3/v2/pgproto3.go

Documentation: github.com/jackc/pgproto3/v2

     1  package pgproto3
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/jackc/pgio"
     9  )
    10  
    11  // maxMessageBodyLen is the maximum length of a message body in bytes. See PG_LARGE_MESSAGE_LIMIT in the PostgreSQL
    12  // source. It is defined as (MaxAllocSize - 1). MaxAllocSize is defined as 0x3fffffff.
    13  const maxMessageBodyLen = (0x3fffffff - 1)
    14  
    15  // Message is the interface implemented by an object that can decode and encode
    16  // a particular PostgreSQL message.
    17  type Message interface {
    18  	// Decode is allowed and expected to retain a reference to data after
    19  	// returning (unlike encoding.BinaryUnmarshaler).
    20  	Decode(data []byte) error
    21  
    22  	// Encode appends itself to dst and returns the new buffer.
    23  	Encode(dst []byte) ([]byte, error)
    24  }
    25  
    26  type FrontendMessage interface {
    27  	Message
    28  	Frontend() // no-op method to distinguish frontend from backend methods
    29  }
    30  
    31  type BackendMessage interface {
    32  	Message
    33  	Backend() // no-op method to distinguish frontend from backend methods
    34  }
    35  
    36  type AuthenticationResponseMessage interface {
    37  	BackendMessage
    38  	AuthenticationResponse() // no-op method to distinguish authentication responses
    39  }
    40  
    41  type invalidMessageLenErr struct {
    42  	messageType string
    43  	expectedLen int
    44  	actualLen   int
    45  }
    46  
    47  func (e *invalidMessageLenErr) Error() string {
    48  	return fmt.Sprintf("%s body must have length of %d, but it is %d", e.messageType, e.expectedLen, e.actualLen)
    49  }
    50  
    51  type invalidMessageFormatErr struct {
    52  	messageType string
    53  }
    54  
    55  func (e *invalidMessageFormatErr) Error() string {
    56  	return fmt.Sprintf("%s body is invalid", e.messageType)
    57  }
    58  
    59  // getValueFromJSON gets the value from a protocol message representation in JSON.
    60  func getValueFromJSON(v map[string]string) ([]byte, error) {
    61  	if v == nil {
    62  		return nil, nil
    63  	}
    64  	if text, ok := v["text"]; ok {
    65  		return []byte(text), nil
    66  	}
    67  	if binary, ok := v["binary"]; ok {
    68  		return hex.DecodeString(binary)
    69  	}
    70  	return nil, errors.New("unknown protocol representation")
    71  }
    72  
    73  // beginMessage begines a new message of type t. It appends the message type and a placeholder for the message length to
    74  // dst. It returns the new buffer and the position of the message length placeholder.
    75  func beginMessage(dst []byte, t byte) ([]byte, int) {
    76  	dst = append(dst, t)
    77  	sp := len(dst)
    78  	dst = pgio.AppendInt32(dst, -1)
    79  	return dst, sp
    80  }
    81  
    82  // finishMessage finishes a message that was started with beginMessage. It computes the message length and writes it to
    83  // dst[sp]. If the message length is too large it returns an error. Otherwise it returns the final message buffer.
    84  func finishMessage(dst []byte, sp int) ([]byte, error) {
    85  	messageBodyLen := len(dst[sp:])
    86  	if messageBodyLen > maxMessageBodyLen {
    87  		return nil, errors.New("message body too large")
    88  	}
    89  	pgio.SetInt32(dst[sp:], int32(messageBodyLen))
    90  	return dst, nil
    91  }
    92  

View as plain text