1 package pgtype
2
3 import (
4 "database/sql/driver"
5 "encoding/binary"
6 "fmt"
7 "math"
8 "strconv"
9
10 "github.com/jackc/pgx/v5/internal/pgio"
11 )
12
13 type Uint32Scanner interface {
14 ScanUint32(v Uint32) error
15 }
16
17 type Uint32Valuer interface {
18 Uint32Value() (Uint32, error)
19 }
20
21
22 type Uint32 struct {
23 Uint32 uint32
24 Valid bool
25 }
26
27 func (n *Uint32) ScanUint32(v Uint32) error {
28 *n = v
29 return nil
30 }
31
32 func (n Uint32) Uint32Value() (Uint32, error) {
33 return n, nil
34 }
35
36
37 func (dst *Uint32) Scan(src any) error {
38 if src == nil {
39 *dst = Uint32{}
40 return nil
41 }
42
43 var n int64
44
45 switch src := src.(type) {
46 case int64:
47 n = src
48 case string:
49 un, err := strconv.ParseUint(src, 10, 32)
50 if err != nil {
51 return err
52 }
53 n = int64(un)
54 default:
55 return fmt.Errorf("cannot scan %T", src)
56 }
57
58 if n < 0 {
59 return fmt.Errorf("%d is less than the minimum value for Uint32", n)
60 }
61 if n > math.MaxUint32 {
62 return fmt.Errorf("%d is greater than maximum value for Uint32", n)
63 }
64
65 *dst = Uint32{Uint32: uint32(n), Valid: true}
66
67 return nil
68 }
69
70
71 func (src Uint32) Value() (driver.Value, error) {
72 if !src.Valid {
73 return nil, nil
74 }
75 return int64(src.Uint32), nil
76 }
77
78 type Uint32Codec struct{}
79
80 func (Uint32Codec) FormatSupported(format int16) bool {
81 return format == TextFormatCode || format == BinaryFormatCode
82 }
83
84 func (Uint32Codec) PreferredFormat() int16 {
85 return BinaryFormatCode
86 }
87
88 func (Uint32Codec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
89 switch format {
90 case BinaryFormatCode:
91 switch value.(type) {
92 case uint32:
93 return encodePlanUint32CodecBinaryUint32{}
94 case Uint32Valuer:
95 return encodePlanUint32CodecBinaryUint32Valuer{}
96 case Int64Valuer:
97 return encodePlanUint32CodecBinaryInt64Valuer{}
98 }
99 case TextFormatCode:
100 switch value.(type) {
101 case uint32:
102 return encodePlanUint32CodecTextUint32{}
103 case Int64Valuer:
104 return encodePlanUint32CodecTextInt64Valuer{}
105 }
106 }
107
108 return nil
109 }
110
111 type encodePlanUint32CodecBinaryUint32 struct{}
112
113 func (encodePlanUint32CodecBinaryUint32) Encode(value any, buf []byte) (newBuf []byte, err error) {
114 v := value.(uint32)
115 return pgio.AppendUint32(buf, v), nil
116 }
117
118 type encodePlanUint32CodecBinaryUint32Valuer struct{}
119
120 func (encodePlanUint32CodecBinaryUint32Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
121 v, err := value.(Uint32Valuer).Uint32Value()
122 if err != nil {
123 return nil, err
124 }
125
126 if !v.Valid {
127 return nil, nil
128 }
129
130 return pgio.AppendUint32(buf, v.Uint32), nil
131 }
132
133 type encodePlanUint32CodecBinaryInt64Valuer struct{}
134
135 func (encodePlanUint32CodecBinaryInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
136 v, err := value.(Int64Valuer).Int64Value()
137 if err != nil {
138 return nil, err
139 }
140
141 if !v.Valid {
142 return nil, nil
143 }
144
145 if v.Int64 < 0 {
146 return nil, fmt.Errorf("%d is less than minimum value for uint32", v.Int64)
147 }
148 if v.Int64 > math.MaxUint32 {
149 return nil, fmt.Errorf("%d is greater than maximum value for uint32", v.Int64)
150 }
151
152 return pgio.AppendUint32(buf, uint32(v.Int64)), nil
153 }
154
155 type encodePlanUint32CodecTextUint32 struct{}
156
157 func (encodePlanUint32CodecTextUint32) Encode(value any, buf []byte) (newBuf []byte, err error) {
158 v := value.(uint32)
159 return append(buf, strconv.FormatUint(uint64(v), 10)...), nil
160 }
161
162 type encodePlanUint32CodecTextUint32Valuer struct{}
163
164 func (encodePlanUint32CodecTextUint32Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
165 v, err := value.(Uint32Valuer).Uint32Value()
166 if err != nil {
167 return nil, err
168 }
169
170 if !v.Valid {
171 return nil, nil
172 }
173
174 return append(buf, strconv.FormatUint(uint64(v.Uint32), 10)...), nil
175 }
176
177 type encodePlanUint32CodecTextInt64Valuer struct{}
178
179 func (encodePlanUint32CodecTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
180 v, err := value.(Int64Valuer).Int64Value()
181 if err != nil {
182 return nil, err
183 }
184
185 if !v.Valid {
186 return nil, nil
187 }
188
189 if v.Int64 < 0 {
190 return nil, fmt.Errorf("%d is less than minimum value for uint32", v.Int64)
191 }
192 if v.Int64 > math.MaxUint32 {
193 return nil, fmt.Errorf("%d is greater than maximum value for uint32", v.Int64)
194 }
195
196 return append(buf, strconv.FormatInt(v.Int64, 10)...), nil
197 }
198
199 func (Uint32Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
200
201 switch format {
202 case BinaryFormatCode:
203 switch target.(type) {
204 case *uint32:
205 return scanPlanBinaryUint32ToUint32{}
206 case Uint32Scanner:
207 return scanPlanBinaryUint32ToUint32Scanner{}
208 }
209 case TextFormatCode:
210 switch target.(type) {
211 case *uint32:
212 return scanPlanTextAnyToUint32{}
213 case Uint32Scanner:
214 return scanPlanTextAnyToUint32Scanner{}
215 }
216 }
217
218 return nil
219 }
220
221 func (c Uint32Codec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
222 if src == nil {
223 return nil, nil
224 }
225
226 var n uint32
227 err := codecScan(c, m, oid, format, src, &n)
228 if err != nil {
229 return nil, err
230 }
231 return int64(n), nil
232 }
233
234 func (c Uint32Codec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
235 if src == nil {
236 return nil, nil
237 }
238
239 var n uint32
240 err := codecScan(c, m, oid, format, src, &n)
241 if err != nil {
242 return nil, err
243 }
244 return n, nil
245 }
246
247 type scanPlanBinaryUint32ToUint32 struct{}
248
249 func (scanPlanBinaryUint32ToUint32) Scan(src []byte, dst any) error {
250 if src == nil {
251 return fmt.Errorf("cannot scan NULL into %T", dst)
252 }
253
254 if len(src) != 4 {
255 return fmt.Errorf("invalid length for uint32: %v", len(src))
256 }
257
258 p := (dst).(*uint32)
259 *p = binary.BigEndian.Uint32(src)
260
261 return nil
262 }
263
264 type scanPlanBinaryUint32ToUint32Scanner struct{}
265
266 func (scanPlanBinaryUint32ToUint32Scanner) Scan(src []byte, dst any) error {
267 s, ok := (dst).(Uint32Scanner)
268 if !ok {
269 return ErrScanTargetTypeChanged
270 }
271
272 if src == nil {
273 return s.ScanUint32(Uint32{})
274 }
275
276 if len(src) != 4 {
277 return fmt.Errorf("invalid length for uint32: %v", len(src))
278 }
279
280 n := binary.BigEndian.Uint32(src)
281
282 return s.ScanUint32(Uint32{Uint32: n, Valid: true})
283 }
284
285 type scanPlanTextAnyToUint32Scanner struct{}
286
287 func (scanPlanTextAnyToUint32Scanner) Scan(src []byte, dst any) error {
288 s, ok := (dst).(Uint32Scanner)
289 if !ok {
290 return ErrScanTargetTypeChanged
291 }
292
293 if src == nil {
294 return s.ScanUint32(Uint32{})
295 }
296
297 n, err := strconv.ParseUint(string(src), 10, 32)
298 if err != nil {
299 return err
300 }
301
302 return s.ScanUint32(Uint32{Uint32: uint32(n), Valid: true})
303 }
304
View as plain text