gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

function_call_response.go (2336B)


      1 package pgproto3
      2 
      3 import (
      4 	"encoding/binary"
      5 	"encoding/hex"
      6 	"encoding/json"
      7 
      8 	"github.com/jackc/pgio"
      9 )
     10 
     11 type FunctionCallResponse struct {
     12 	Result []byte
     13 }
     14 
     15 // Backend identifies this message as sendable by the PostgreSQL backend.
     16 func (*FunctionCallResponse) Backend() {}
     17 
     18 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
     19 // type identifier and 4 byte message length.
     20 func (dst *FunctionCallResponse) Decode(src []byte) error {
     21 	if len(src) < 4 {
     22 		return &invalidMessageFormatErr{messageType: "FunctionCallResponse"}
     23 	}
     24 	rp := 0
     25 	resultSize := int(binary.BigEndian.Uint32(src[rp:]))
     26 	rp += 4
     27 
     28 	if resultSize == -1 {
     29 		dst.Result = nil
     30 		return nil
     31 	}
     32 
     33 	if len(src[rp:]) != resultSize {
     34 		return &invalidMessageFormatErr{messageType: "FunctionCallResponse"}
     35 	}
     36 
     37 	dst.Result = src[rp:]
     38 	return nil
     39 }
     40 
     41 // Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
     42 func (src *FunctionCallResponse) Encode(dst []byte) []byte {
     43 	dst = append(dst, 'V')
     44 	sp := len(dst)
     45 	dst = pgio.AppendInt32(dst, -1)
     46 
     47 	if src.Result == nil {
     48 		dst = pgio.AppendInt32(dst, -1)
     49 	} else {
     50 		dst = pgio.AppendInt32(dst, int32(len(src.Result)))
     51 		dst = append(dst, src.Result...)
     52 	}
     53 
     54 	pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
     55 
     56 	return dst
     57 }
     58 
     59 // MarshalJSON implements encoding/json.Marshaler.
     60 func (src FunctionCallResponse) MarshalJSON() ([]byte, error) {
     61 	var formattedValue map[string]string
     62 	var hasNonPrintable bool
     63 	for _, b := range src.Result {
     64 		if b < 32 {
     65 			hasNonPrintable = true
     66 			break
     67 		}
     68 	}
     69 
     70 	if hasNonPrintable {
     71 		formattedValue = map[string]string{"binary": hex.EncodeToString(src.Result)}
     72 	} else {
     73 		formattedValue = map[string]string{"text": string(src.Result)}
     74 	}
     75 
     76 	return json.Marshal(struct {
     77 		Type   string
     78 		Result map[string]string
     79 	}{
     80 		Type:   "FunctionCallResponse",
     81 		Result: formattedValue,
     82 	})
     83 }
     84 
     85 // UnmarshalJSON implements encoding/json.Unmarshaler.
     86 func (dst *FunctionCallResponse) UnmarshalJSON(data []byte) error {
     87 	// Ignore null, like in the main JSON package.
     88 	if string(data) == "null" {
     89 		return nil
     90 	}
     91 
     92 	var msg struct {
     93 		Result map[string]string
     94 	}
     95 	err := json.Unmarshal(data, &msg)
     96 	if err != nil {
     97 		return err
     98 	}
     99 	dst.Result, err = getValueFromJSON(msg.Result)
    100 	return err
    101 }