package pgtype
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"net"
"net/netip"
"reflect"
"time"
)
const (
BoolOID = 16
ByteaOID = 17
QCharOID = 18
NameOID = 19
Int8OID = 20
Int2OID = 21
Int4OID = 23
TextOID = 25
OIDOID = 26
TIDOID = 27
XIDOID = 28
CIDOID = 29
JSONOID = 114
JSONArrayOID = 199
PointOID = 600
LsegOID = 601
PathOID = 602
BoxOID = 603
PolygonOID = 604
LineOID = 628
LineArrayOID = 629
CIDROID = 650
CIDRArrayOID = 651
Float4OID = 700
Float8OID = 701
CircleOID = 718
CircleArrayOID = 719
UnknownOID = 705
MacaddrOID = 829
InetOID = 869
BoolArrayOID = 1000
QCharArrayOID = 1002
NameArrayOID = 1003
Int2ArrayOID = 1005
Int4ArrayOID = 1007
TextArrayOID = 1009
TIDArrayOID = 1010
ByteaArrayOID = 1001
XIDArrayOID = 1011
CIDArrayOID = 1012
BPCharArrayOID = 1014
VarcharArrayOID = 1015
Int8ArrayOID = 1016
PointArrayOID = 1017
LsegArrayOID = 1018
PathArrayOID = 1019
BoxArrayOID = 1020
Float4ArrayOID = 1021
Float8ArrayOID = 1022
PolygonArrayOID = 1027
OIDArrayOID = 1028
ACLItemOID = 1033
ACLItemArrayOID = 1034
MacaddrArrayOID = 1040
InetArrayOID = 1041
BPCharOID = 1042
VarcharOID = 1043
DateOID = 1082
TimeOID = 1083
TimestampOID = 1114
TimestampArrayOID = 1115
DateArrayOID = 1182
TimeArrayOID = 1183
TimestamptzOID = 1184
TimestamptzArrayOID = 1185
IntervalOID = 1186
IntervalArrayOID = 1187
NumericArrayOID = 1231
BitOID = 1560
BitArrayOID = 1561
VarbitOID = 1562
VarbitArrayOID = 1563
NumericOID = 1700
RecordOID = 2249
RecordArrayOID = 2287
UUIDOID = 2950
UUIDArrayOID = 2951
JSONBOID = 3802
JSONBArrayOID = 3807
DaterangeOID = 3912
DaterangeArrayOID = 3913
Int4rangeOID = 3904
Int4rangeArrayOID = 3905
NumrangeOID = 3906
NumrangeArrayOID = 3907
TsrangeOID = 3908
TsrangeArrayOID = 3909
TstzrangeOID = 3910
TstzrangeArrayOID = 3911
Int8rangeOID = 3926
Int8rangeArrayOID = 3927
JSONPathOID = 4072
JSONPathArrayOID = 4073
Int4multirangeOID = 4451
NummultirangeOID = 4532
TsmultirangeOID = 4533
TstzmultirangeOID = 4534
DatemultirangeOID = 4535
Int8multirangeOID = 4536
Int4multirangeArrayOID = 6150
NummultirangeArrayOID = 6151
TsmultirangeArrayOID = 6152
TstzmultirangeArrayOID = 6153
DatemultirangeArrayOID = 6155
Int8multirangeArrayOID = 6157
)
type InfinityModifier int8
const (
Infinity InfinityModifier = 1
Finite InfinityModifier = 0
NegativeInfinity InfinityModifier = -Infinity
)
func (im InfinityModifier ) String () string {
switch im {
case Finite :
return "finite"
case Infinity :
return "infinity"
case NegativeInfinity :
return "-infinity"
default :
return "invalid"
}
}
const (
TextFormatCode = 0
BinaryFormatCode = 1
)
type Codec interface {
FormatSupported (int16 ) bool
PreferredFormat () int16
PlanEncode (m *Map , oid uint32 , format int16 , value any ) EncodePlan
PlanScan (m *Map , oid uint32 , format int16 , target any ) ScanPlan
DecodeDatabaseSQLValue (m *Map , oid uint32 , format int16 , src []byte ) (driver .Value , error )
DecodeValue (m *Map , oid uint32 , format int16 , src []byte ) (any , error )
}
type nullAssignmentError struct {
dst any
}
func (e *nullAssignmentError ) Error () string {
return fmt .Sprintf ("cannot assign NULL to %T" , e .dst )
}
type Type struct {
Codec Codec
Name string
OID uint32
}
type Map struct {
oidToType map [uint32 ]*Type
nameToType map [string ]*Type
reflectTypeToName map [reflect .Type ]string
oidToFormatCode map [uint32 ]int16
reflectTypeToType map [reflect .Type ]*Type
memoizedScanPlans map [uint32 ]map [reflect .Type ][2 ]ScanPlan
memoizedEncodePlans map [uint32 ]map [reflect .Type ][2 ]EncodePlan
TryWrapEncodePlanFuncs []TryWrapEncodePlanFunc
TryWrapScanPlanFuncs []TryWrapScanPlanFunc
}
func NewMap () *Map {
defaultMapInitOnce .Do (initDefaultMap )
return &Map {
oidToType : make (map [uint32 ]*Type ),
nameToType : make (map [string ]*Type ),
reflectTypeToName : make (map [reflect .Type ]string ),
oidToFormatCode : make (map [uint32 ]int16 ),
memoizedScanPlans : make (map [uint32 ]map [reflect .Type ][2 ]ScanPlan ),
memoizedEncodePlans : make (map [uint32 ]map [reflect .Type ][2 ]EncodePlan ),
TryWrapEncodePlanFuncs : []TryWrapEncodePlanFunc {
TryWrapDerefPointerEncodePlan ,
TryWrapBuiltinTypeEncodePlan ,
TryWrapFindUnderlyingTypeEncodePlan ,
TryWrapStructEncodePlan ,
TryWrapSliceEncodePlan ,
TryWrapMultiDimSliceEncodePlan ,
TryWrapArrayEncodePlan ,
},
TryWrapScanPlanFuncs : []TryWrapScanPlanFunc {
TryPointerPointerScanPlan ,
TryWrapBuiltinTypeScanPlan ,
TryFindUnderlyingTypeScanPlan ,
TryWrapStructScanPlan ,
TryWrapPtrSliceScanPlan ,
TryWrapPtrMultiDimSliceScanPlan ,
TryWrapPtrArrayScanPlan ,
},
}
}
func (m *Map ) RegisterType (t *Type ) {
m .oidToType [t .OID ] = t
m .nameToType [t .Name ] = t
m .oidToFormatCode [t .OID ] = t .Codec .PreferredFormat ()
m .reflectTypeToType = nil
for k := range m .memoizedScanPlans {
delete (m .memoizedScanPlans , k )
}
for k := range m .memoizedEncodePlans {
delete (m .memoizedEncodePlans , k )
}
}
func (m *Map ) RegisterDefaultPgType (value any , name string ) {
m .reflectTypeToName [reflect .TypeOf (value )] = name
m .reflectTypeToType = nil
for k := range m .memoizedScanPlans {
delete (m .memoizedScanPlans , k )
}
for k := range m .memoizedEncodePlans {
delete (m .memoizedEncodePlans , k )
}
}
func (m *Map ) TypeForOID (oid uint32 ) (*Type , bool ) {
if dt , ok := m .oidToType [oid ]; ok {
return dt , true
}
dt , ok := defaultMap .oidToType [oid ]
return dt , ok
}
func (m *Map ) TypeForName (name string ) (*Type , bool ) {
if dt , ok := m .nameToType [name ]; ok {
return dt , true
}
dt , ok := defaultMap .nameToType [name ]
return dt , ok
}
func (m *Map ) buildReflectTypeToType () {
m .reflectTypeToType = make (map [reflect .Type ]*Type )
for reflectType , name := range m .reflectTypeToName {
if dt , ok := m .TypeForName (name ); ok {
m .reflectTypeToType [reflectType ] = dt
}
}
}
func (m *Map ) TypeForValue (v any ) (*Type , bool ) {
if m .reflectTypeToType == nil {
m .buildReflectTypeToType ()
}
if dt , ok := m .reflectTypeToType [reflect .TypeOf (v )]; ok {
return dt , true
}
dt , ok := defaultMap .reflectTypeToType [reflect .TypeOf (v )]
return dt , ok
}
func (m *Map ) FormatCodeForOID (oid uint32 ) int16 {
if fc , ok := m .oidToFormatCode [oid ]; ok {
return fc
}
if fc , ok := defaultMap .oidToFormatCode [oid ]; ok {
return fc
}
return TextFormatCode
}
type EncodePlan interface {
Encode (value any , buf []byte ) (newBuf []byte , err error )
}
type ScanPlan interface {
Scan (src []byte , target any ) error
}
type scanPlanCodecSQLScanner struct {
c Codec
m *Map
oid uint32
formatCode int16
}
func (plan *scanPlanCodecSQLScanner ) Scan (src []byte , dst any ) error {
value , err := plan .c .DecodeDatabaseSQLValue (plan .m , plan .oid , plan .formatCode , src )
if err != nil {
return err
}
scanner := dst .(sql .Scanner )
return scanner .Scan (value )
}
type scanPlanSQLScanner struct {
formatCode int16
}
func (plan *scanPlanSQLScanner ) Scan (src []byte , dst any ) error {
scanner := dst .(sql .Scanner )
if src == nil {
return scanner .Scan (nil )
} else if plan .formatCode == BinaryFormatCode {
return scanner .Scan (src )
} else {
return scanner .Scan (string (src ))
}
}
type scanPlanString struct {}
func (scanPlanString ) Scan (src []byte , dst any ) error {
if src == nil {
return fmt .Errorf ("cannot scan NULL into %T" , dst )
}
p := (dst ).(*string )
*p = string (src )
return nil
}
type scanPlanAnyTextToBytes struct {}
func (scanPlanAnyTextToBytes ) Scan (src []byte , dst any ) error {
dstBuf := dst .(*[]byte )
if src == nil {
*dstBuf = nil
return nil
}
*dstBuf = make ([]byte , len (src ))
copy (*dstBuf , src )
return nil
}
type scanPlanFail struct {
m *Map
oid uint32
formatCode int16
}
func (plan *scanPlanFail ) Scan (src []byte , dst any ) error {
if src == nil {
for oid := range plan .m .oidToType {
plan := plan .m .planScan (oid , plan .formatCode , dst )
if _ , ok := plan .(*scanPlanFail ); !ok {
return plan .Scan (src , dst )
}
}
for oid := range defaultMap .oidToType {
if _ , ok := plan .m .oidToType [oid ]; !ok {
plan := plan .m .planScan (oid , plan .formatCode , dst )
if _ , ok := plan .(*scanPlanFail ); !ok {
return plan .Scan (src , dst )
}
}
}
}
var format string
switch plan .formatCode {
case TextFormatCode :
format = "text"
case BinaryFormatCode :
format = "binary"
default :
format = fmt .Sprintf ("unknown %d" , plan .formatCode )
}
var dataTypeName string
if t , ok := plan .m .TypeForOID (plan .oid ); ok {
dataTypeName = t .Name
} else {
dataTypeName = "unknown type"
}
return fmt .Errorf ("cannot scan %s (OID %d) in %v format into %T" , dataTypeName , plan .oid , format , dst )
}
type TryWrapScanPlanFunc func (target any ) (plan WrappedScanPlanNextSetter , nextTarget any , ok bool )
type pointerPointerScanPlan struct {
dstType reflect .Type
next ScanPlan
}
func (plan *pointerPointerScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *pointerPointerScanPlan ) Scan (src []byte , dst any ) error {
el := reflect .ValueOf (dst ).Elem ()
if src == nil {
el .Set (reflect .Zero (el .Type ()))
return nil
}
el .Set (reflect .New (el .Type ().Elem ()))
return plan .next .Scan (src , el .Interface ())
}
func TryPointerPointerScanPlan (target any ) (plan WrappedScanPlanNextSetter , nextTarget any , ok bool ) {
if dstValue := reflect .ValueOf (target ); dstValue .Kind () == reflect .Ptr {
elemValue := dstValue .Elem ()
if elemValue .Kind () == reflect .Ptr {
plan = &pointerPointerScanPlan {dstType : dstValue .Type ()}
return plan , reflect .Zero (elemValue .Type ()).Interface (), true
}
}
return nil , nil , false
}
type SkipUnderlyingTypePlanner interface {
SkipUnderlyingTypePlan ()
}
var elemKindToPointerTypes map [reflect .Kind ]reflect .Type = map [reflect .Kind ]reflect .Type {
reflect .Int : reflect .TypeOf (new (int )),
reflect .Int8 : reflect .TypeOf (new (int8 )),
reflect .Int16 : reflect .TypeOf (new (int16 )),
reflect .Int32 : reflect .TypeOf (new (int32 )),
reflect .Int64 : reflect .TypeOf (new (int64 )),
reflect .Uint : reflect .TypeOf (new (uint )),
reflect .Uint8 : reflect .TypeOf (new (uint8 )),
reflect .Uint16 : reflect .TypeOf (new (uint16 )),
reflect .Uint32 : reflect .TypeOf (new (uint32 )),
reflect .Uint64 : reflect .TypeOf (new (uint64 )),
reflect .Float32 : reflect .TypeOf (new (float32 )),
reflect .Float64 : reflect .TypeOf (new (float64 )),
reflect .String : reflect .TypeOf (new (string )),
reflect .Bool : reflect .TypeOf (new (bool )),
}
type underlyingTypeScanPlan struct {
dstType reflect .Type
nextDstType reflect .Type
next ScanPlan
}
func (plan *underlyingTypeScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *underlyingTypeScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , reflect .ValueOf (dst ).Convert (plan .nextDstType ).Interface ())
}
func TryFindUnderlyingTypeScanPlan (dst any ) (plan WrappedScanPlanNextSetter , nextDst any , ok bool ) {
if _ , ok := dst .(SkipUnderlyingTypePlanner ); ok {
return nil , nil , false
}
dstValue := reflect .ValueOf (dst )
if dstValue .Kind () == reflect .Ptr {
var elemValue reflect .Value
if dstValue .IsNil () {
elemValue = reflect .New (dstValue .Type ().Elem ()).Elem ()
} else {
elemValue = dstValue .Elem ()
}
nextDstType := elemKindToPointerTypes [elemValue .Kind ()]
if nextDstType == nil && elemValue .Kind () == reflect .Slice {
if elemValue .Type ().Elem ().Kind () == reflect .Uint8 {
var v *[]byte
nextDstType = reflect .TypeOf (v )
}
}
if nextDstType != nil && dstValue .Type () != nextDstType {
return &underlyingTypeScanPlan {dstType : dstValue .Type (), nextDstType : nextDstType }, dstValue .Convert (nextDstType ).Interface (), true
}
}
return nil , nil , false
}
type WrappedScanPlanNextSetter interface {
SetNext (ScanPlan )
ScanPlan
}
func TryWrapBuiltinTypeScanPlan (target any ) (plan WrappedScanPlanNextSetter , nextDst any , ok bool ) {
switch target := target .(type ) {
case *int8 :
return &wrapInt8ScanPlan {}, (*int8Wrapper )(target ), true
case *int16 :
return &wrapInt16ScanPlan {}, (*int16Wrapper )(target ), true
case *int32 :
return &wrapInt32ScanPlan {}, (*int32Wrapper )(target ), true
case *int64 :
return &wrapInt64ScanPlan {}, (*int64Wrapper )(target ), true
case *int :
return &wrapIntScanPlan {}, (*intWrapper )(target ), true
case *uint8 :
return &wrapUint8ScanPlan {}, (*uint8Wrapper )(target ), true
case *uint16 :
return &wrapUint16ScanPlan {}, (*uint16Wrapper )(target ), true
case *uint32 :
return &wrapUint32ScanPlan {}, (*uint32Wrapper )(target ), true
case *uint64 :
return &wrapUint64ScanPlan {}, (*uint64Wrapper )(target ), true
case *uint :
return &wrapUintScanPlan {}, (*uintWrapper )(target ), true
case *float32 :
return &wrapFloat32ScanPlan {}, (*float32Wrapper )(target ), true
case *float64 :
return &wrapFloat64ScanPlan {}, (*float64Wrapper )(target ), true
case *string :
return &wrapStringScanPlan {}, (*stringWrapper )(target ), true
case *time .Time :
return &wrapTimeScanPlan {}, (*timeWrapper )(target ), true
case *time .Duration :
return &wrapDurationScanPlan {}, (*durationWrapper )(target ), true
case *net .IPNet :
return &wrapNetIPNetScanPlan {}, (*netIPNetWrapper )(target ), true
case *net .IP :
return &wrapNetIPScanPlan {}, (*netIPWrapper )(target ), true
case *netip .Prefix :
return &wrapNetipPrefixScanPlan {}, (*netipPrefixWrapper )(target ), true
case *netip .Addr :
return &wrapNetipAddrScanPlan {}, (*netipAddrWrapper )(target ), true
case *map [string ]*string :
return &wrapMapStringToPointerStringScanPlan {}, (*mapStringToPointerStringWrapper )(target ), true
case *map [string ]string :
return &wrapMapStringToStringScanPlan {}, (*mapStringToStringWrapper )(target ), true
case *[16 ]byte :
return &wrapByte16ScanPlan {}, (*byte16Wrapper )(target ), true
case *[]byte :
return &wrapByteSliceScanPlan {}, (*byteSliceWrapper )(target ), true
}
return nil , nil , false
}
type wrapInt8ScanPlan struct {
next ScanPlan
}
func (plan *wrapInt8ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapInt8ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*int8Wrapper )(dst .(*int8 )))
}
type wrapInt16ScanPlan struct {
next ScanPlan
}
func (plan *wrapInt16ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapInt16ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*int16Wrapper )(dst .(*int16 )))
}
type wrapInt32ScanPlan struct {
next ScanPlan
}
func (plan *wrapInt32ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapInt32ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*int32Wrapper )(dst .(*int32 )))
}
type wrapInt64ScanPlan struct {
next ScanPlan
}
func (plan *wrapInt64ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapInt64ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*int64Wrapper )(dst .(*int64 )))
}
type wrapIntScanPlan struct {
next ScanPlan
}
func (plan *wrapIntScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapIntScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*intWrapper )(dst .(*int )))
}
type wrapUint8ScanPlan struct {
next ScanPlan
}
func (plan *wrapUint8ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapUint8ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*uint8Wrapper )(dst .(*uint8 )))
}
type wrapUint16ScanPlan struct {
next ScanPlan
}
func (plan *wrapUint16ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapUint16ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*uint16Wrapper )(dst .(*uint16 )))
}
type wrapUint32ScanPlan struct {
next ScanPlan
}
func (plan *wrapUint32ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapUint32ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*uint32Wrapper )(dst .(*uint32 )))
}
type wrapUint64ScanPlan struct {
next ScanPlan
}
func (plan *wrapUint64ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapUint64ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*uint64Wrapper )(dst .(*uint64 )))
}
type wrapUintScanPlan struct {
next ScanPlan
}
func (plan *wrapUintScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapUintScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*uintWrapper )(dst .(*uint )))
}
type wrapFloat32ScanPlan struct {
next ScanPlan
}
func (plan *wrapFloat32ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapFloat32ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*float32Wrapper )(dst .(*float32 )))
}
type wrapFloat64ScanPlan struct {
next ScanPlan
}
func (plan *wrapFloat64ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapFloat64ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*float64Wrapper )(dst .(*float64 )))
}
type wrapStringScanPlan struct {
next ScanPlan
}
func (plan *wrapStringScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapStringScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*stringWrapper )(dst .(*string )))
}
type wrapTimeScanPlan struct {
next ScanPlan
}
func (plan *wrapTimeScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapTimeScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*timeWrapper )(dst .(*time .Time )))
}
type wrapDurationScanPlan struct {
next ScanPlan
}
func (plan *wrapDurationScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapDurationScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*durationWrapper )(dst .(*time .Duration )))
}
type wrapNetIPNetScanPlan struct {
next ScanPlan
}
func (plan *wrapNetIPNetScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapNetIPNetScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*netIPNetWrapper )(dst .(*net .IPNet )))
}
type wrapNetIPScanPlan struct {
next ScanPlan
}
func (plan *wrapNetIPScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapNetIPScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*netIPWrapper )(dst .(*net .IP )))
}
type wrapNetipPrefixScanPlan struct {
next ScanPlan
}
func (plan *wrapNetipPrefixScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapNetipPrefixScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*netipPrefixWrapper )(dst .(*netip .Prefix )))
}
type wrapNetipAddrScanPlan struct {
next ScanPlan
}
func (plan *wrapNetipAddrScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapNetipAddrScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*netipAddrWrapper )(dst .(*netip .Addr )))
}
type wrapMapStringToPointerStringScanPlan struct {
next ScanPlan
}
func (plan *wrapMapStringToPointerStringScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapMapStringToPointerStringScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*mapStringToPointerStringWrapper )(dst .(*map [string ]*string )))
}
type wrapMapStringToStringScanPlan struct {
next ScanPlan
}
func (plan *wrapMapStringToStringScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapMapStringToStringScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*mapStringToStringWrapper )(dst .(*map [string ]string )))
}
type wrapByte16ScanPlan struct {
next ScanPlan
}
func (plan *wrapByte16ScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapByte16ScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*byte16Wrapper )(dst .(*[16 ]byte )))
}
type wrapByteSliceScanPlan struct {
next ScanPlan
}
func (plan *wrapByteSliceScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapByteSliceScanPlan ) Scan (src []byte , dst any ) error {
return plan .next .Scan (src , (*byteSliceWrapper )(dst .(*[]byte )))
}
type pointerEmptyInterfaceScanPlan struct {
codec Codec
m *Map
oid uint32
formatCode int16
}
func (plan *pointerEmptyInterfaceScanPlan ) Scan (src []byte , dst any ) error {
value , err := plan .codec .DecodeValue (plan .m , plan .oid , plan .formatCode , src )
if err != nil {
return err
}
ptrAny := dst .(*any )
*ptrAny = value
return nil
}
func TryWrapStructScanPlan (target any ) (plan WrappedScanPlanNextSetter , nextValue any , ok bool ) {
targetValue := reflect .ValueOf (target )
if targetValue .Kind () != reflect .Ptr {
return nil , nil , false
}
var targetElemValue reflect .Value
if targetValue .IsNil () {
targetElemValue = reflect .Zero (targetValue .Type ().Elem ())
} else {
targetElemValue = targetValue .Elem ()
}
targetElemType := targetElemValue .Type ()
if targetElemType .Kind () == reflect .Struct {
exportedFields := getExportedFieldValues (targetElemValue )
if len (exportedFields ) == 0 {
return nil , nil , false
}
w := ptrStructWrapper {
s : target ,
exportedFields : exportedFields ,
}
return &wrapAnyPtrStructScanPlan {}, &w , true
}
return nil , nil , false
}
type wrapAnyPtrStructScanPlan struct {
next ScanPlan
}
func (plan *wrapAnyPtrStructScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapAnyPtrStructScanPlan ) Scan (src []byte , target any ) error {
w := ptrStructWrapper {
s : target ,
exportedFields : getExportedFieldValues (reflect .ValueOf (target ).Elem ()),
}
return plan .next .Scan (src , &w )
}
func TryWrapPtrSliceScanPlan (target any ) (plan WrappedScanPlanNextSetter , nextValue any , ok bool ) {
switch target := target .(type ) {
case *[]int16 :
return &wrapPtrSliceScanPlan [int16 ]{}, (*FlatArray [int16 ])(target ), true
case *[]int32 :
return &wrapPtrSliceScanPlan [int32 ]{}, (*FlatArray [int32 ])(target ), true
case *[]int64 :
return &wrapPtrSliceScanPlan [int64 ]{}, (*FlatArray [int64 ])(target ), true
case *[]float32 :
return &wrapPtrSliceScanPlan [float32 ]{}, (*FlatArray [float32 ])(target ), true
case *[]float64 :
return &wrapPtrSliceScanPlan [float64 ]{}, (*FlatArray [float64 ])(target ), true
case *[]string :
return &wrapPtrSliceScanPlan [string ]{}, (*FlatArray [string ])(target ), true
case *[]time .Time :
return &wrapPtrSliceScanPlan [time .Time ]{}, (*FlatArray [time .Time ])(target ), true
}
targetType := reflect .TypeOf (target )
if targetType .Kind () != reflect .Ptr {
return nil , nil , false
}
targetElemType := targetType .Elem ()
if targetElemType .Kind () == reflect .Slice {
slice := reflect .New (targetElemType ).Elem ()
return &wrapPtrSliceReflectScanPlan {}, &anySliceArrayReflect {slice : slice }, true
}
return nil , nil , false
}
type wrapPtrSliceScanPlan[T any ] struct {
next ScanPlan
}
func (plan *wrapPtrSliceScanPlan [T ]) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapPtrSliceScanPlan [T ]) Scan (src []byte , target any ) error {
return plan .next .Scan (src , (*FlatArray [T ])(target .(*[]T )))
}
type wrapPtrSliceReflectScanPlan struct {
next ScanPlan
}
func (plan *wrapPtrSliceReflectScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapPtrSliceReflectScanPlan ) Scan (src []byte , target any ) error {
return plan .next .Scan (src , &anySliceArrayReflect {slice : reflect .ValueOf (target ).Elem ()})
}
func TryWrapPtrMultiDimSliceScanPlan (target any ) (plan WrappedScanPlanNextSetter , nextValue any , ok bool ) {
targetValue := reflect .ValueOf (target )
if targetValue .Kind () != reflect .Ptr {
return nil , nil , false
}
targetElemValue := targetValue .Elem ()
if targetElemValue .Kind () == reflect .Slice {
elemElemKind := targetElemValue .Type ().Elem ().Kind ()
if elemElemKind == reflect .Slice {
if !isRagged (targetElemValue ) {
return &wrapPtrMultiDimSliceScanPlan {}, &anyMultiDimSliceArray {slice : targetValue .Elem ()}, true
}
}
}
return nil , nil , false
}
type wrapPtrMultiDimSliceScanPlan struct {
next ScanPlan
}
func (plan *wrapPtrMultiDimSliceScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapPtrMultiDimSliceScanPlan ) Scan (src []byte , target any ) error {
return plan .next .Scan (src , &anyMultiDimSliceArray {slice : reflect .ValueOf (target ).Elem ()})
}
func TryWrapPtrArrayScanPlan (target any ) (plan WrappedScanPlanNextSetter , nextValue any , ok bool ) {
targetValue := reflect .ValueOf (target )
if targetValue .Kind () != reflect .Ptr {
return nil , nil , false
}
targetElemValue := targetValue .Elem ()
if targetElemValue .Kind () == reflect .Array {
return &wrapPtrArrayReflectScanPlan {}, &anyArrayArrayReflect {array : targetElemValue }, true
}
return nil , nil , false
}
type wrapPtrArrayReflectScanPlan struct {
next ScanPlan
}
func (plan *wrapPtrArrayReflectScanPlan ) SetNext (next ScanPlan ) { plan .next = next }
func (plan *wrapPtrArrayReflectScanPlan ) Scan (src []byte , target any ) error {
return plan .next .Scan (src , &anyArrayArrayReflect {array : reflect .ValueOf (target ).Elem ()})
}
func (m *Map ) PlanScan (oid uint32 , formatCode int16 , target any ) ScanPlan {
oidMemo := m .memoizedScanPlans [oid ]
if oidMemo == nil {
oidMemo = make (map [reflect .Type ][2 ]ScanPlan )
m .memoizedScanPlans [oid ] = oidMemo
}
targetReflectType := reflect .TypeOf (target )
typeMemo := oidMemo [targetReflectType ]
plan := typeMemo [formatCode ]
if plan == nil {
plan = m .planScan (oid , formatCode , target )
typeMemo [formatCode ] = plan
oidMemo [targetReflectType ] = typeMemo
}
return plan
}
func (m *Map ) planScan (oid uint32 , formatCode int16 , target any ) ScanPlan {
if target == nil {
return &scanPlanFail {m : m , oid : oid , formatCode : formatCode }
}
if _ , ok := target .(*UndecodedBytes ); ok {
return scanPlanAnyToUndecodedBytes {}
}
switch formatCode {
case BinaryFormatCode :
switch target .(type ) {
case *string :
switch oid {
case TextOID , VarcharOID :
return scanPlanString {}
}
}
case TextFormatCode :
switch target .(type ) {
case *string :
return scanPlanString {}
case *[]byte :
if oid != ByteaOID {
return scanPlanAnyTextToBytes {}
}
case TextScanner :
return scanPlanTextAnyToTextScanner {}
}
}
var dt *Type
if dataType , ok := m .TypeForOID (oid ); ok {
dt = dataType
} else if dataType , ok := m .TypeForValue (target ); ok {
dt = dataType
oid = dt .OID
}
if dt != nil {
if plan := dt .Codec .PlanScan (m , oid , formatCode , target ); plan != nil {
return plan
}
}
if _ , ok := target .(sql .Scanner ); ok {
if dt == nil {
return &scanPlanSQLScanner {formatCode : formatCode }
} else {
return &scanPlanCodecSQLScanner {c : dt .Codec , m : m , oid : oid , formatCode : formatCode }
}
}
for _ , f := range m .TryWrapScanPlanFuncs {
if wrapperPlan , nextDst , ok := f (target ); ok {
if nextPlan := m .planScan (oid , formatCode , nextDst ); nextPlan != nil {
if _ , failed := nextPlan .(*scanPlanFail ); !failed {
wrapperPlan .SetNext (nextPlan )
return wrapperPlan
}
}
}
}
if dt != nil {
if _ , ok := target .(*any ); ok {
return &pointerEmptyInterfaceScanPlan {codec : dt .Codec , m : m , oid : oid , formatCode : formatCode }
}
}
return &scanPlanFail {m : m , oid : oid , formatCode : formatCode }
}
func (m *Map ) Scan (oid uint32 , formatCode int16 , src []byte , dst any ) error {
if dst == nil {
return nil
}
plan := m .PlanScan (oid , formatCode , dst )
return plan .Scan (src , dst )
}
var ErrScanTargetTypeChanged = errors .New ("scan target type changed" )
func codecScan(codec Codec , m *Map , oid uint32 , format int16 , src []byte , dst any ) error {
scanPlan := codec .PlanScan (m , oid , format , dst )
if scanPlan == nil {
return fmt .Errorf ("PlanScan did not find a plan" )
}
return scanPlan .Scan (src , dst )
}
func codecDecodeToTextFormat(codec Codec , m *Map , oid uint32 , format int16 , src []byte ) (driver .Value , error ) {
if src == nil {
return nil , nil
}
if format == TextFormatCode {
return string (src ), nil
} else {
value , err := codec .DecodeValue (m , oid , format , src )
if err != nil {
return nil , err
}
buf , err := m .Encode (oid , TextFormatCode , value , nil )
if err != nil {
return nil , err
}
return string (buf ), nil
}
}
func (m *Map ) PlanEncode (oid uint32 , format int16 , value any ) EncodePlan {
oidMemo := m .memoizedEncodePlans [oid ]
if oidMemo == nil {
oidMemo = make (map [reflect .Type ][2 ]EncodePlan )
m .memoizedEncodePlans [oid ] = oidMemo
}
targetReflectType := reflect .TypeOf (value )
typeMemo := oidMemo [targetReflectType ]
plan := typeMemo [format ]
if plan == nil {
plan = m .planEncode (oid , format , value )
typeMemo [format ] = plan
oidMemo [targetReflectType ] = typeMemo
}
return plan
}
func (m *Map ) planEncode (oid uint32 , format int16 , value any ) EncodePlan {
if format == TextFormatCode {
switch value .(type ) {
case string :
return encodePlanStringToAnyTextFormat {}
case TextValuer :
return encodePlanTextValuerToAnyTextFormat {}
}
}
var dt *Type
if dataType , ok := m .TypeForOID (oid ); ok {
dt = dataType
} else {
if dataType , ok := m .TypeForValue (value ); ok {
dt = dataType
oid = dt .OID
}
}
if dt != nil {
if plan := dt .Codec .PlanEncode (m , oid , format , value ); plan != nil {
return plan
}
}
for _ , f := range m .TryWrapEncodePlanFuncs {
if wrapperPlan , nextValue , ok := f (value ); ok {
if nextPlan := m .PlanEncode (oid , format , nextValue ); nextPlan != nil {
wrapperPlan .SetNext (nextPlan )
return wrapperPlan
}
}
}
if _ , ok := value .(driver .Valuer ); ok {
return &encodePlanDriverValuer {m : m , oid : oid , formatCode : format }
}
return nil
}
type encodePlanStringToAnyTextFormat struct {}
func (encodePlanStringToAnyTextFormat ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
s := value .(string )
return append (buf , s ...), nil
}
type encodePlanTextValuerToAnyTextFormat struct {}
func (encodePlanTextValuerToAnyTextFormat ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
t , err := value .(TextValuer ).TextValue ()
if err != nil {
return nil , err
}
if !t .Valid {
return nil , nil
}
return append (buf , t .String ...), nil
}
type encodePlanDriverValuer struct {
m *Map
oid uint32
formatCode int16
}
func (plan *encodePlanDriverValuer ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
dv := value .(driver .Valuer )
if dv == nil {
return nil , nil
}
v , err := dv .Value ()
if err != nil {
return nil , err
}
if v == nil {
return nil , nil
}
newBuf , err = plan .m .Encode (plan .oid , plan .formatCode , v , buf )
if err == nil {
return newBuf , nil
}
s , ok := v .(string )
if !ok {
return nil , err
}
var scannedValue any
scanErr := plan .m .Scan (plan .oid , TextFormatCode , []byte (s ), &scannedValue )
if scanErr != nil {
return nil , err
}
if reflect .TypeOf (value ) == reflect .TypeOf (scannedValue ) {
return nil , fmt .Errorf ("tried to encode %v via encoding to text and scanning but failed due to receiving same type back" , value )
}
var err2 error
newBuf , err2 = plan .m .Encode (plan .oid , BinaryFormatCode , scannedValue , buf )
if err2 != nil {
return nil , err
}
return newBuf , nil
}
type TryWrapEncodePlanFunc func (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool )
type derefPointerEncodePlan struct {
next EncodePlan
}
func (plan *derefPointerEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *derefPointerEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
ptr := reflect .ValueOf (value )
if ptr .IsNil () {
return nil , nil
}
return plan .next .Encode (ptr .Elem ().Interface (), buf )
}
func TryWrapDerefPointerEncodePlan (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool ) {
if _ , ok := value .(driver .Valuer ); ok {
return nil , nil , false
}
if valueType := reflect .TypeOf (value ); valueType != nil && valueType .Kind () == reflect .Ptr {
return &derefPointerEncodePlan {}, reflect .New (valueType .Elem ()).Elem ().Interface (), true
}
return nil , nil , false
}
var kindToTypes map [reflect .Kind ]reflect .Type = map [reflect .Kind ]reflect .Type {
reflect .Int : reflect .TypeOf (int (0 )),
reflect .Int8 : reflect .TypeOf (int8 (0 )),
reflect .Int16 : reflect .TypeOf (int16 (0 )),
reflect .Int32 : reflect .TypeOf (int32 (0 )),
reflect .Int64 : reflect .TypeOf (int64 (0 )),
reflect .Uint : reflect .TypeOf (uint (0 )),
reflect .Uint8 : reflect .TypeOf (uint8 (0 )),
reflect .Uint16 : reflect .TypeOf (uint16 (0 )),
reflect .Uint32 : reflect .TypeOf (uint32 (0 )),
reflect .Uint64 : reflect .TypeOf (uint64 (0 )),
reflect .Float32 : reflect .TypeOf (float32 (0 )),
reflect .Float64 : reflect .TypeOf (float64 (0 )),
reflect .String : reflect .TypeOf ("" ),
reflect .Bool : reflect .TypeOf (false ),
}
type underlyingTypeEncodePlan struct {
nextValueType reflect .Type
next EncodePlan
}
func (plan *underlyingTypeEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *underlyingTypeEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (reflect .ValueOf (value ).Convert (plan .nextValueType ).Interface (), buf )
}
func TryWrapFindUnderlyingTypeEncodePlan (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool ) {
if _ , ok := value .(driver .Valuer ); ok {
return nil , nil , false
}
if _ , ok := value .(SkipUnderlyingTypePlanner ); ok {
return nil , nil , false
}
refValue := reflect .ValueOf (value )
nextValueType := kindToTypes [refValue .Kind ()]
if nextValueType != nil && refValue .Type () != nextValueType {
return &underlyingTypeEncodePlan {nextValueType : nextValueType }, refValue .Convert (nextValueType ).Interface (), true
}
return nil , nil , false
}
type WrappedEncodePlanNextSetter interface {
SetNext (EncodePlan )
EncodePlan
}
func TryWrapBuiltinTypeEncodePlan (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool ) {
if _ , ok := value .(driver .Valuer ); ok {
return nil , nil , false
}
switch value := value .(type ) {
case int8 :
return &wrapInt8EncodePlan {}, int8Wrapper (value ), true
case int16 :
return &wrapInt16EncodePlan {}, int16Wrapper (value ), true
case int32 :
return &wrapInt32EncodePlan {}, int32Wrapper (value ), true
case int64 :
return &wrapInt64EncodePlan {}, int64Wrapper (value ), true
case int :
return &wrapIntEncodePlan {}, intWrapper (value ), true
case uint8 :
return &wrapUint8EncodePlan {}, uint8Wrapper (value ), true
case uint16 :
return &wrapUint16EncodePlan {}, uint16Wrapper (value ), true
case uint32 :
return &wrapUint32EncodePlan {}, uint32Wrapper (value ), true
case uint64 :
return &wrapUint64EncodePlan {}, uint64Wrapper (value ), true
case uint :
return &wrapUintEncodePlan {}, uintWrapper (value ), true
case float32 :
return &wrapFloat32EncodePlan {}, float32Wrapper (value ), true
case float64 :
return &wrapFloat64EncodePlan {}, float64Wrapper (value ), true
case string :
return &wrapStringEncodePlan {}, stringWrapper (value ), true
case time .Time :
return &wrapTimeEncodePlan {}, timeWrapper (value ), true
case time .Duration :
return &wrapDurationEncodePlan {}, durationWrapper (value ), true
case net .IPNet :
return &wrapNetIPNetEncodePlan {}, netIPNetWrapper (value ), true
case net .IP :
return &wrapNetIPEncodePlan {}, netIPWrapper (value ), true
case netip .Prefix :
return &wrapNetipPrefixEncodePlan {}, netipPrefixWrapper (value ), true
case netip .Addr :
return &wrapNetipAddrEncodePlan {}, netipAddrWrapper (value ), true
case map [string ]*string :
return &wrapMapStringToPointerStringEncodePlan {}, mapStringToPointerStringWrapper (value ), true
case map [string ]string :
return &wrapMapStringToStringEncodePlan {}, mapStringToStringWrapper (value ), true
case [16 ]byte :
return &wrapByte16EncodePlan {}, byte16Wrapper (value ), true
case []byte :
return &wrapByteSliceEncodePlan {}, byteSliceWrapper (value ), true
case fmt .Stringer :
return &wrapFmtStringerEncodePlan {}, fmtStringerWrapper {value }, true
}
return nil , nil , false
}
type wrapInt8EncodePlan struct {
next EncodePlan
}
func (plan *wrapInt8EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapInt8EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (int8Wrapper (value .(int8 )), buf )
}
type wrapInt16EncodePlan struct {
next EncodePlan
}
func (plan *wrapInt16EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapInt16EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (int16Wrapper (value .(int16 )), buf )
}
type wrapInt32EncodePlan struct {
next EncodePlan
}
func (plan *wrapInt32EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapInt32EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (int32Wrapper (value .(int32 )), buf )
}
type wrapInt64EncodePlan struct {
next EncodePlan
}
func (plan *wrapInt64EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapInt64EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (int64Wrapper (value .(int64 )), buf )
}
type wrapIntEncodePlan struct {
next EncodePlan
}
func (plan *wrapIntEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapIntEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (intWrapper (value .(int )), buf )
}
type wrapUint8EncodePlan struct {
next EncodePlan
}
func (plan *wrapUint8EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapUint8EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (uint8Wrapper (value .(uint8 )), buf )
}
type wrapUint16EncodePlan struct {
next EncodePlan
}
func (plan *wrapUint16EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapUint16EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (uint16Wrapper (value .(uint16 )), buf )
}
type wrapUint32EncodePlan struct {
next EncodePlan
}
func (plan *wrapUint32EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapUint32EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (uint32Wrapper (value .(uint32 )), buf )
}
type wrapUint64EncodePlan struct {
next EncodePlan
}
func (plan *wrapUint64EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapUint64EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (uint64Wrapper (value .(uint64 )), buf )
}
type wrapUintEncodePlan struct {
next EncodePlan
}
func (plan *wrapUintEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapUintEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (uintWrapper (value .(uint )), buf )
}
type wrapFloat32EncodePlan struct {
next EncodePlan
}
func (plan *wrapFloat32EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapFloat32EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (float32Wrapper (value .(float32 )), buf )
}
type wrapFloat64EncodePlan struct {
next EncodePlan
}
func (plan *wrapFloat64EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapFloat64EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (float64Wrapper (value .(float64 )), buf )
}
type wrapStringEncodePlan struct {
next EncodePlan
}
func (plan *wrapStringEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapStringEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (stringWrapper (value .(string )), buf )
}
type wrapTimeEncodePlan struct {
next EncodePlan
}
func (plan *wrapTimeEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapTimeEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (timeWrapper (value .(time .Time )), buf )
}
type wrapDurationEncodePlan struct {
next EncodePlan
}
func (plan *wrapDurationEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapDurationEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (durationWrapper (value .(time .Duration )), buf )
}
type wrapNetIPNetEncodePlan struct {
next EncodePlan
}
func (plan *wrapNetIPNetEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapNetIPNetEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (netIPNetWrapper (value .(net .IPNet )), buf )
}
type wrapNetIPEncodePlan struct {
next EncodePlan
}
func (plan *wrapNetIPEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapNetIPEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (netIPWrapper (value .(net .IP )), buf )
}
type wrapNetipPrefixEncodePlan struct {
next EncodePlan
}
func (plan *wrapNetipPrefixEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapNetipPrefixEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (netipPrefixWrapper (value .(netip .Prefix )), buf )
}
type wrapNetipAddrEncodePlan struct {
next EncodePlan
}
func (plan *wrapNetipAddrEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapNetipAddrEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (netipAddrWrapper (value .(netip .Addr )), buf )
}
type wrapMapStringToPointerStringEncodePlan struct {
next EncodePlan
}
func (plan *wrapMapStringToPointerStringEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapMapStringToPointerStringEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (mapStringToPointerStringWrapper (value .(map [string ]*string )), buf )
}
type wrapMapStringToStringEncodePlan struct {
next EncodePlan
}
func (plan *wrapMapStringToStringEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapMapStringToStringEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (mapStringToStringWrapper (value .(map [string ]string )), buf )
}
type wrapByte16EncodePlan struct {
next EncodePlan
}
func (plan *wrapByte16EncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapByte16EncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (byte16Wrapper (value .([16 ]byte )), buf )
}
type wrapByteSliceEncodePlan struct {
next EncodePlan
}
func (plan *wrapByteSliceEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapByteSliceEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (byteSliceWrapper (value .([]byte )), buf )
}
type wrapFmtStringerEncodePlan struct {
next EncodePlan
}
func (plan *wrapFmtStringerEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapFmtStringerEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode (fmtStringerWrapper {value .(fmt .Stringer )}, buf )
}
func TryWrapStructEncodePlan (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool ) {
if _ , ok := value .(driver .Valuer ); ok {
return nil , nil , false
}
if valueType := reflect .TypeOf (value ); valueType != nil && valueType .Kind () == reflect .Struct {
exportedFields := getExportedFieldValues (reflect .ValueOf (value ))
if len (exportedFields ) == 0 {
return nil , nil , false
}
w := structWrapper {
s : value ,
exportedFields : exportedFields ,
}
return &wrapAnyStructEncodePlan {}, w , true
}
return nil , nil , false
}
type wrapAnyStructEncodePlan struct {
next EncodePlan
}
func (plan *wrapAnyStructEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapAnyStructEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
w := structWrapper {
s : value ,
exportedFields : getExportedFieldValues (reflect .ValueOf (value )),
}
return plan .next .Encode (w , buf )
}
func getExportedFieldValues(structValue reflect .Value ) []reflect .Value {
structType := structValue .Type ()
exportedFields := make ([]reflect .Value , 0 , structValue .NumField ())
for i := 0 ; i < structType .NumField (); i ++ {
sf := structType .Field (i )
if sf .IsExported () {
exportedFields = append (exportedFields , structValue .Field (i ))
}
}
return exportedFields
}
func TryWrapSliceEncodePlan (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool ) {
if _ , ok := value .(driver .Valuer ); ok {
return nil , nil , false
}
switch value := value .(type ) {
case []int16 :
return &wrapSliceEncodePlan [int16 ]{}, (FlatArray [int16 ])(value ), true
case []int32 :
return &wrapSliceEncodePlan [int32 ]{}, (FlatArray [int32 ])(value ), true
case []int64 :
return &wrapSliceEncodePlan [int64 ]{}, (FlatArray [int64 ])(value ), true
case []float32 :
return &wrapSliceEncodePlan [float32 ]{}, (FlatArray [float32 ])(value ), true
case []float64 :
return &wrapSliceEncodePlan [float64 ]{}, (FlatArray [float64 ])(value ), true
case []string :
return &wrapSliceEncodePlan [string ]{}, (FlatArray [string ])(value ), true
case []time .Time :
return &wrapSliceEncodePlan [time .Time ]{}, (FlatArray [time .Time ])(value ), true
}
if valueType := reflect .TypeOf (value ); valueType != nil && valueType .Kind () == reflect .Slice {
w := anySliceArrayReflect {
slice : reflect .ValueOf (value ),
}
return &wrapSliceEncodeReflectPlan {}, w , true
}
return nil , nil , false
}
type wrapSliceEncodePlan[T any ] struct {
next EncodePlan
}
func (plan *wrapSliceEncodePlan [T ]) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapSliceEncodePlan [T ]) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
return plan .next .Encode ((FlatArray [T ])(value .([]T )), buf )
}
type wrapSliceEncodeReflectPlan struct {
next EncodePlan
}
func (plan *wrapSliceEncodeReflectPlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapSliceEncodeReflectPlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
w := anySliceArrayReflect {
slice : reflect .ValueOf (value ),
}
return plan .next .Encode (w , buf )
}
func TryWrapMultiDimSliceEncodePlan (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool ) {
if _ , ok := value .(driver .Valuer ); ok {
return nil , nil , false
}
sliceValue := reflect .ValueOf (value )
if sliceValue .Kind () == reflect .Slice {
valueElemType := sliceValue .Type ().Elem ()
if valueElemType .Kind () == reflect .Slice {
if !isRagged (sliceValue ) {
w := anyMultiDimSliceArray {
slice : reflect .ValueOf (value ),
}
return &wrapMultiDimSliceEncodePlan {}, &w , true
}
}
}
return nil , nil , false
}
type wrapMultiDimSliceEncodePlan struct {
next EncodePlan
}
func (plan *wrapMultiDimSliceEncodePlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapMultiDimSliceEncodePlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
w := anyMultiDimSliceArray {
slice : reflect .ValueOf (value ),
}
return plan .next .Encode (&w , buf )
}
func TryWrapArrayEncodePlan (value any ) (plan WrappedEncodePlanNextSetter , nextValue any , ok bool ) {
if _ , ok := value .(driver .Valuer ); ok {
return nil , nil , false
}
if valueType := reflect .TypeOf (value ); valueType != nil && valueType .Kind () == reflect .Array {
w := anyArrayArrayReflect {
array : reflect .ValueOf (value ),
}
return &wrapArrayEncodeReflectPlan {}, w , true
}
return nil , nil , false
}
type wrapArrayEncodeReflectPlan struct {
next EncodePlan
}
func (plan *wrapArrayEncodeReflectPlan ) SetNext (next EncodePlan ) { plan .next = next }
func (plan *wrapArrayEncodeReflectPlan ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
w := anyArrayArrayReflect {
array : reflect .ValueOf (value ),
}
return plan .next .Encode (w , buf )
}
func newEncodeError(value any , m *Map , oid uint32 , formatCode int16 , err error ) error {
var format string
switch formatCode {
case TextFormatCode :
format = "text"
case BinaryFormatCode :
format = "binary"
default :
format = fmt .Sprintf ("unknown (%d)" , formatCode )
}
var dataTypeName string
if t , ok := m .TypeForOID (oid ); ok {
dataTypeName = t .Name
} else {
dataTypeName = "unknown type"
}
return fmt .Errorf ("unable to encode %#v into %s format for %s (OID %d): %w" , value , format , dataTypeName , oid , err )
}
func (m *Map ) Encode (oid uint32 , formatCode int16 , value any , buf []byte ) (newBuf []byte , err error ) {
if value == nil {
return nil , nil
}
plan := m .PlanEncode (oid , formatCode , value )
if plan == nil {
return nil , newEncodeError (value , m , oid , formatCode , errors .New ("cannot find encode plan" ))
}
newBuf , err = plan .Encode (value , buf )
if err != nil {
return nil , newEncodeError (value , m , oid , formatCode , err )
}
return newBuf , nil
}
func (m *Map ) SQLScanner (v any ) sql .Scanner {
if s , ok := v .(sql .Scanner ); ok {
return s
}
return &sqlScannerWrapper {m : m , v : v }
}
type sqlScannerWrapper struct {
m *Map
v any
}
func (w *sqlScannerWrapper ) Scan (src any ) error {
t , ok := w .m .TypeForValue (w .v )
if !ok {
return fmt .Errorf ("cannot convert to sql.Scanner: cannot find registered type for %T" , w .v )
}
var bufSrc []byte
if src != nil {
switch src := src .(type ) {
case string :
bufSrc = []byte (src )
case []byte :
bufSrc = src
default :
bufSrc = []byte (fmt .Sprint (bufSrc ))
}
}
return w .m .Scan (t .OID , TextFormatCode , bufSrc , w .v )
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .