1 package pgtype
2
3 import (
4 "database/sql/driver"
5 "encoding/hex"
6 "fmt"
7 )
8
9 type BytesScanner interface {
10
11 ScanBytes(v []byte) error
12 }
13
14 type BytesValuer interface {
15
16 BytesValue() ([]byte, error)
17 }
18
19
20
21
22 type DriverBytes []byte
23
24 func (b *DriverBytes) ScanBytes(v []byte) error {
25 *b = v
26 return nil
27 }
28
29
30
31 type PreallocBytes []byte
32
33 func (b *PreallocBytes) ScanBytes(v []byte) error {
34 if v == nil {
35 *b = nil
36 return nil
37 }
38
39 if len(v) <= len(*b) {
40 *b = (*b)[:len(v)]
41 } else {
42 *b = make(PreallocBytes, len(v))
43 }
44 copy(*b, v)
45 return nil
46 }
47
48
49 type UndecodedBytes []byte
50
51 type scanPlanAnyToUndecodedBytes struct{}
52
53 func (scanPlanAnyToUndecodedBytes) Scan(src []byte, dst any) error {
54 dstBuf := dst.(*UndecodedBytes)
55 if src == nil {
56 *dstBuf = nil
57 return nil
58 }
59
60 *dstBuf = make([]byte, len(src))
61 copy(*dstBuf, src)
62 return nil
63 }
64
65 type ByteaCodec struct{}
66
67 func (ByteaCodec) FormatSupported(format int16) bool {
68 return format == TextFormatCode || format == BinaryFormatCode
69 }
70
71 func (ByteaCodec) PreferredFormat() int16 {
72 return BinaryFormatCode
73 }
74
75 func (ByteaCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
76 switch format {
77 case BinaryFormatCode:
78 switch value.(type) {
79 case []byte:
80 return encodePlanBytesCodecBinaryBytes{}
81 case BytesValuer:
82 return encodePlanBytesCodecBinaryBytesValuer{}
83 }
84 case TextFormatCode:
85 switch value.(type) {
86 case []byte:
87 return encodePlanBytesCodecTextBytes{}
88 case BytesValuer:
89 return encodePlanBytesCodecTextBytesValuer{}
90 }
91 }
92
93 return nil
94 }
95
96 type encodePlanBytesCodecBinaryBytes struct{}
97
98 func (encodePlanBytesCodecBinaryBytes) Encode(value any, buf []byte) (newBuf []byte, err error) {
99 b := value.([]byte)
100 if b == nil {
101 return nil, nil
102 }
103
104 return append(buf, b...), nil
105 }
106
107 type encodePlanBytesCodecBinaryBytesValuer struct{}
108
109 func (encodePlanBytesCodecBinaryBytesValuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
110 b, err := value.(BytesValuer).BytesValue()
111 if err != nil {
112 return nil, err
113 }
114 if b == nil {
115 return nil, nil
116 }
117
118 return append(buf, b...), nil
119 }
120
121 type encodePlanBytesCodecTextBytes struct{}
122
123 func (encodePlanBytesCodecTextBytes) Encode(value any, buf []byte) (newBuf []byte, err error) {
124 b := value.([]byte)
125 if b == nil {
126 return nil, nil
127 }
128
129 buf = append(buf, `\x`...)
130 buf = append(buf, hex.EncodeToString(b)...)
131 return buf, nil
132 }
133
134 type encodePlanBytesCodecTextBytesValuer struct{}
135
136 func (encodePlanBytesCodecTextBytesValuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
137 b, err := value.(BytesValuer).BytesValue()
138 if err != nil {
139 return nil, err
140 }
141 if b == nil {
142 return nil, nil
143 }
144
145 buf = append(buf, `\x`...)
146 buf = append(buf, hex.EncodeToString(b)...)
147 return buf, nil
148 }
149
150 func (ByteaCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
151
152 switch format {
153 case BinaryFormatCode:
154 switch target.(type) {
155 case *[]byte:
156 return scanPlanBinaryBytesToBytes{}
157 case BytesScanner:
158 return scanPlanBinaryBytesToBytesScanner{}
159 }
160 case TextFormatCode:
161 switch target.(type) {
162 case *[]byte:
163 return scanPlanTextByteaToBytes{}
164 case BytesScanner:
165 return scanPlanTextByteaToBytesScanner{}
166 }
167 }
168
169 return nil
170 }
171
172 type scanPlanBinaryBytesToBytes struct{}
173
174 func (scanPlanBinaryBytesToBytes) Scan(src []byte, dst any) error {
175 dstBuf := dst.(*[]byte)
176 if src == nil {
177 *dstBuf = nil
178 return nil
179 }
180
181 *dstBuf = make([]byte, len(src))
182 copy(*dstBuf, src)
183 return nil
184 }
185
186 type scanPlanBinaryBytesToBytesScanner struct{}
187
188 func (scanPlanBinaryBytesToBytesScanner) Scan(src []byte, dst any) error {
189 scanner := (dst).(BytesScanner)
190 return scanner.ScanBytes(src)
191 }
192
193 type scanPlanTextByteaToBytes struct{}
194
195 func (scanPlanTextByteaToBytes) Scan(src []byte, dst any) error {
196 dstBuf := dst.(*[]byte)
197 if src == nil {
198 *dstBuf = nil
199 return nil
200 }
201
202 buf, err := decodeHexBytea(src)
203 if err != nil {
204 return err
205 }
206 *dstBuf = buf
207
208 return nil
209 }
210
211 type scanPlanTextByteaToBytesScanner struct{}
212
213 func (scanPlanTextByteaToBytesScanner) Scan(src []byte, dst any) error {
214 scanner := (dst).(BytesScanner)
215 buf, err := decodeHexBytea(src)
216 if err != nil {
217 return err
218 }
219 return scanner.ScanBytes(buf)
220 }
221
222 func decodeHexBytea(src []byte) ([]byte, error) {
223 if src == nil {
224 return nil, nil
225 }
226
227 if len(src) < 2 || src[0] != '\\' || src[1] != 'x' {
228 return nil, fmt.Errorf("invalid hex format")
229 }
230
231 buf := make([]byte, (len(src)-2)/2)
232 _, err := hex.Decode(buf, src[2:])
233 if err != nil {
234 return nil, err
235 }
236
237 return buf, nil
238 }
239
240 func (c ByteaCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
241 return c.DecodeValue(m, oid, format, src)
242 }
243
244 func (c ByteaCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
245 if src == nil {
246 return nil, nil
247 }
248
249 var buf []byte
250 err := codecScan(c, m, oid, format, src, &buf)
251 if err != nil {
252 return nil, err
253 }
254 return buf, nil
255 }
256
View as plain text