Parse a bytea value received from the server. Both "hex" and the legacy "escape" format are supported.
(s []byte)
| 345 | // Parse a bytea value received from the server. Both "hex" and the legacy |
| 346 | // "escape" format are supported. |
| 347 | func parseBytea(s []byte) (result []byte, err error) { |
| 348 | // Hex format. |
| 349 | if len(s) >= 2 && bytes.Equal(s[:2], []byte("\\x")) { |
| 350 | s = s[2:] // trim off leading "\\x" |
| 351 | result = make([]byte, hex.DecodedLen(len(s))) |
| 352 | _, err := hex.Decode(result, s) |
| 353 | if err != nil { |
| 354 | return nil, err |
| 355 | } |
| 356 | return result, nil |
| 357 | } |
| 358 | |
| 359 | // Escape format. |
| 360 | for len(s) > 0 { |
| 361 | if s[0] == '\\' { |
| 362 | // escaped '\\' |
| 363 | if len(s) >= 2 && s[1] == '\\' { |
| 364 | result = append(result, '\\') |
| 365 | s = s[2:] |
| 366 | continue |
| 367 | } |
| 368 | |
| 369 | // '\\' followed by an octal number |
| 370 | if len(s) < 4 { |
| 371 | return nil, fmt.Errorf("invalid bytea sequence %v", s) |
| 372 | } |
| 373 | r, err := strconv.ParseUint(string(s[1:4]), 8, 8) |
| 374 | if err != nil { |
| 375 | return nil, fmt.Errorf("could not parse bytea value: %w", err) |
| 376 | } |
| 377 | result = append(result, byte(r)) |
| 378 | s = s[4:] |
| 379 | } else { |
| 380 | // We hit an unescaped, raw byte. Try to read in as many as |
| 381 | // possible in one go. |
| 382 | i := bytes.IndexByte(s, '\\') |
| 383 | if i == -1 { |
| 384 | result = append(result, s...) |
| 385 | break |
| 386 | } |
| 387 | result = append(result, s[:i]...) |
| 388 | s = s[i:] |
| 389 | } |
| 390 | } |
| 391 | return result, nil |
| 392 | } |
| 393 | |
| 394 | func encodeBytea(v []byte) (result []byte) { |
| 395 | result = make([]byte, 2+hex.EncodedLen(len(v))) |
no outgoing calls
no test coverage detected
searching dependent graphs…