Parse a bytea value received from the server. Both "hex" and the legacy "escape" format are supported.
(s []byte)
| 85 | // Parse a bytea value received from the server. Both "hex" and the legacy |
| 86 | // "escape" format are supported. |
| 87 | func parseBytea(s []byte) (result []byte, err error) { |
| 88 | if len(s) >= 2 && bytes.Equal(s[:2], []byte("\\x")) { |
| 89 | // bytea_output = hex |
| 90 | s = s[2:] // trim off leading "\\x" |
| 91 | result = make([]byte, hex.DecodedLen(len(s))) |
| 92 | _, err := hex.Decode(result, s) |
| 93 | if err != nil { |
| 94 | return nil, err |
| 95 | } |
| 96 | } else { |
| 97 | // bytea_output = escape |
| 98 | for len(s) > 0 { |
| 99 | if s[0] == '\\' { |
| 100 | // escaped '\\' |
| 101 | if len(s) >= 2 && s[1] == '\\' { |
| 102 | result = append(result, '\\') |
| 103 | s = s[2:] |
| 104 | continue |
| 105 | } |
| 106 | |
| 107 | // '\\' followed by an octal number |
| 108 | if len(s) < 4 { |
| 109 | return nil, fmt.Errorf("invalid bytea sequence %v", s) |
| 110 | } |
| 111 | r, err := strconv.ParseInt(string(s[1:4]), 8, 9) |
| 112 | if err != nil { |
| 113 | return nil, fmt.Errorf("could not parse bytea value: %s", err.Error()) |
| 114 | } |
| 115 | result = append(result, byte(r)) |
| 116 | s = s[4:] |
| 117 | } else { |
| 118 | // We hit an unescaped, raw byte. Try to read in as many as |
| 119 | // possible in one go. |
| 120 | i := bytes.IndexByte(s, '\\') |
| 121 | if i == -1 { |
| 122 | result = append(result, s...) |
| 123 | break |
| 124 | } |
| 125 | result = append(result, s[:i]...) |
| 126 | s = s[i:] |
| 127 | } |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | return result, nil |
| 132 | } |
| 133 | |
| 134 | func encodeBytea(serverVersion int, v []byte) (result []byte) { |
| 135 | if serverVersion >= 90000 { |