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 }