1 package pgtype
2
3 import (
4 "database/sql/driver"
5 "fmt"
6 "math"
7 )
8
9
10
11
12
13
14
15 type QCharCodec struct{}
16
17 func (QCharCodec) FormatSupported(format int16) bool {
18 return format == TextFormatCode || format == BinaryFormatCode
19 }
20
21 func (QCharCodec) PreferredFormat() int16 {
22 return BinaryFormatCode
23 }
24
25 func (QCharCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
26 switch format {
27 case TextFormatCode, BinaryFormatCode:
28 switch value.(type) {
29 case byte:
30 return encodePlanQcharCodecByte{}
31 case rune:
32 return encodePlanQcharCodecRune{}
33 }
34 }
35
36 return nil
37 }
38
39 type encodePlanQcharCodecByte struct{}
40
41 func (encodePlanQcharCodecByte) Encode(value any, buf []byte) (newBuf []byte, err error) {
42 b := value.(byte)
43 buf = append(buf, b)
44 return buf, nil
45 }
46
47 type encodePlanQcharCodecRune struct{}
48
49 func (encodePlanQcharCodecRune) Encode(value any, buf []byte) (newBuf []byte, err error) {
50 r := value.(rune)
51 if r > math.MaxUint8 {
52 return nil, fmt.Errorf(`%v cannot be encoded to "char"`, r)
53 }
54 b := byte(r)
55 buf = append(buf, b)
56 return buf, nil
57 }
58
59 func (QCharCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
60 switch format {
61 case TextFormatCode, BinaryFormatCode:
62 switch target.(type) {
63 case *byte:
64 return scanPlanQcharCodecByte{}
65 case *rune:
66 return scanPlanQcharCodecRune{}
67 }
68 }
69
70 return nil
71 }
72
73 type scanPlanQcharCodecByte struct{}
74
75 func (scanPlanQcharCodecByte) Scan(src []byte, dst any) error {
76 if src == nil {
77 return fmt.Errorf("cannot scan NULL into %T", dst)
78 }
79
80 if len(src) > 1 {
81 return fmt.Errorf(`invalid length for "char": %v`, len(src))
82 }
83
84 b := dst.(*byte)
85
86 if len(src) == 0 {
87 *b = 0
88 } else {
89 *b = src[0]
90 }
91
92 return nil
93 }
94
95 type scanPlanQcharCodecRune struct{}
96
97 func (scanPlanQcharCodecRune) Scan(src []byte, dst any) error {
98 if src == nil {
99 return fmt.Errorf("cannot scan NULL into %T", dst)
100 }
101
102 if len(src) > 1 {
103 return fmt.Errorf(`invalid length for "char": %v`, len(src))
104 }
105
106 r := dst.(*rune)
107
108 if len(src) == 0 {
109 *r = 0
110 } else {
111 *r = rune(src[0])
112 }
113
114 return nil
115 }
116
117 func (c QCharCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
118 if src == nil {
119 return nil, nil
120 }
121
122 var r rune
123 err := codecScan(c, m, oid, format, src, &r)
124 if err != nil {
125 return nil, err
126 }
127 return string(r), nil
128 }
129
130 func (c QCharCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
131 if src == nil {
132 return nil, nil
133 }
134
135 var r rune
136 err := codecScan(c, m, oid, format, src, &r)
137 if err != nil {
138 return nil, err
139 }
140 return r, nil
141 }
142
View as plain text