pgx/value_transcoder.go

253 lines
5.6 KiB
Go

package pgx
import (
"encoding/hex"
"fmt"
"strconv"
"unsafe"
)
type valueTranscoder struct {
DecodeText func(*MessageReader, int32) interface{}
DecodeBinary func(*MessageReader, int32) interface{}
EncodeTo func(*messageWriter, interface{})
EncodeFormat int16
}
var valueTranscoders map[Oid]*valueTranscoder
var defaultTranscoder *valueTranscoder
func init() {
valueTranscoders = make(map[Oid]*valueTranscoder)
// bool
valueTranscoders[Oid(16)] = &valueTranscoder{
DecodeText: decodeBoolFromText,
DecodeBinary: decodeBoolFromBinary,
EncodeTo: encodeBool,
EncodeFormat: 1}
// bytea
valueTranscoders[Oid(17)] = &valueTranscoder{
DecodeText: decodeByteaFromText,
EncodeTo: encodeBytea,
EncodeFormat: 1}
// int8
valueTranscoders[Oid(20)] = &valueTranscoder{
DecodeText: decodeInt8FromText,
DecodeBinary: decodeInt8FromBinary,
EncodeTo: encodeInt8,
EncodeFormat: 1}
// int2
valueTranscoders[Oid(21)] = &valueTranscoder{
DecodeText: decodeInt2FromText,
DecodeBinary: decodeInt2FromBinary,
EncodeTo: encodeInt2,
EncodeFormat: 1}
// int4
valueTranscoders[Oid(23)] = &valueTranscoder{
DecodeText: decodeInt4FromText,
DecodeBinary: decodeInt4FromBinary,
EncodeTo: encodeInt4,
EncodeFormat: 1}
// text
valueTranscoders[Oid(25)] = &valueTranscoder{
DecodeText: decodeTextFromText,
EncodeTo: encodeText}
// float4
valueTranscoders[Oid(700)] = &valueTranscoder{
DecodeText: decodeFloat4FromText,
DecodeBinary: decodeFloat4FromBinary,
EncodeTo: encodeFloat4,
EncodeFormat: 1}
// float8
valueTranscoders[Oid(701)] = &valueTranscoder{
DecodeText: decodeFloat8FromText,
DecodeBinary: decodeFloat8FromBinary,
EncodeTo: encodeFloat8,
EncodeFormat: 1}
// varchar -- same as text
valueTranscoders[Oid(1043)] = valueTranscoders[Oid(25)]
// use text transcoder for anything we don't understand
defaultTranscoder = valueTranscoders[Oid(25)]
}
func decodeBoolFromText(mr *MessageReader, size int32) interface{} {
s := mr.ReadByteString(size)
switch s {
case "t":
return true
case "f":
return false
default:
panic(fmt.Sprintf("Received invalid bool: %v", s))
}
}
func decodeBoolFromBinary(mr *MessageReader, size int32) interface{} {
if size != 1 {
panic("Received an invalid size for an bool")
}
b := mr.ReadByte()
return b != 0
}
func encodeBool(w *messageWriter, value interface{}) {
v := value.(bool)
w.write(int32(1))
if v {
w.writeByte(1)
} else {
w.writeByte(0)
}
}
func decodeInt8FromText(mr *MessageReader, size int32) interface{} {
s := mr.ReadByteString(size)
n, err := strconv.ParseInt(s, 10, 64)
if err != nil {
panic(fmt.Sprintf("Received invalid int8: %v", s))
}
return n
}
func decodeInt8FromBinary(mr *MessageReader, size int32) interface{} {
if size != 8 {
panic("Received an invalid size for an int8")
}
return mr.ReadInt64()
}
func encodeInt8(w *messageWriter, value interface{}) {
v := value.(int64)
w.write(int32(8))
w.write(v)
}
func decodeInt2FromText(mr *MessageReader, size int32) interface{} {
s := mr.ReadByteString(size)
n, err := strconv.ParseInt(s, 10, 16)
if err != nil {
panic(fmt.Sprintf("Received invalid int2: %v", s))
}
return int16(n)
}
func decodeInt2FromBinary(mr *MessageReader, size int32) interface{} {
if size != 2 {
panic("Received an invalid size for an int8")
}
return mr.ReadInt16()
}
func encodeInt2(w *messageWriter, value interface{}) {
v := value.(int16)
w.write(int32(2))
w.write(v)
}
func decodeInt4FromText(mr *MessageReader, size int32) interface{} {
s := mr.ReadByteString(size)
n, err := strconv.ParseInt(s, 10, 32)
if err != nil {
panic(fmt.Sprintf("Received invalid int4: %v", s))
}
return int32(n)
}
func decodeInt4FromBinary(mr *MessageReader, size int32) interface{} {
if size != 4 {
panic("Received an invalid size for an int4")
}
return mr.ReadInt32()
}
func encodeInt4(w *messageWriter, value interface{}) {
v := value.(int32)
w.write(int32(4))
w.write(v)
}
func decodeFloat4FromText(mr *MessageReader, size int32) interface{} {
s := mr.ReadByteString(size)
n, err := strconv.ParseFloat(s, 32)
if err != nil {
panic(fmt.Sprintf("Received invalid float4: %v", s))
}
return float32(n)
}
func decodeFloat4FromBinary(mr *MessageReader, size int32) interface{} {
if size != 4 {
panic("Received an invalid size for an float4")
}
i := mr.ReadInt32()
p := unsafe.Pointer(&i)
return *(*float32)(p)
}
func encodeFloat4(w *messageWriter, value interface{}) {
v := value.(float32)
w.write(int32(4))
w.write(v)
}
func decodeFloat8FromText(mr *MessageReader, size int32) interface{} {
s := mr.ReadByteString(size)
v, err := strconv.ParseFloat(s, 64)
if err != nil {
panic(fmt.Sprintf("Received invalid float8: %v", s))
}
return v
}
func decodeFloat8FromBinary(mr *MessageReader, size int32) interface{} {
if size != 8 {
panic("Received an invalid size for an float4")
}
i := mr.ReadInt64()
p := unsafe.Pointer(&i)
return *(*float64)(p)
}
func encodeFloat8(w *messageWriter, value interface{}) {
v := value.(float64)
w.write(int32(8))
w.write(v)
}
func decodeTextFromText(mr *MessageReader, size int32) interface{} {
return mr.ReadByteString(size)
}
func encodeText(w *messageWriter, value interface{}) {
s := value.(string)
w.write(int32(len(s)))
w.writeString(s)
}
func decodeByteaFromText(mr *MessageReader, size int32) interface{} {
s := mr.ReadByteString(size)
b, err := hex.DecodeString(s[2:])
if err != nil {
panic("Can't decode byte array")
}
return b
}
func encodeBytea(w *messageWriter, value interface{}) {
b := value.([]byte)
w.write(int32(len(b)))
w.write(b)
}