github.com/jackc/pgx/v5@v5.5.5/pgtype/uint32.go (about) 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 // Uint32 is the core type that is used to represent PostgreSQL types such as OID, CID, and XID. 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 // Scan implements the database/sql Scanner interface. 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 // Value implements the database/sql/driver Valuer interface. 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 }