Parse a bytea value received from the server. Both "hex" and the legacy "escape" format are supported.
(s []byte)
| 165 | // Parse a bytea value received from the server. Both "hex" and the legacy |
| 166 | // "escape" format are supported. |
| 167 | func parseBytea(s []byte) (result []byte, err error) { |
| 168 | if len(s) >= 2 && bytes.Equal(s[:2], []byte("\\x")) { |
| 169 | // bytea_output = hex |
| 170 | s = s[2:] // trim off leading "\\x" |
| 171 | result = make([]byte, hex.DecodedLen(len(s))) |
| 172 | _, err := hex.Decode(result, s) |
| 173 | if err != nil { |
| 174 | return nil, err |
| 175 | } |
| 176 | } else { |
| 177 | // bytea_output = escape |
| 178 | for len(s) > 0 { |
| 179 | if s[0] == '\\' { |
| 180 | // escaped '\\' |
| 181 | if len(s) >= 2 && s[1] == '\\' { |
| 182 | result = append(result, '\\') |
| 183 | s = s[2:] |
| 184 | continue |
| 185 | } |
| 186 | |
| 187 | // '\\' followed by an octal number |
| 188 | if len(s) < 4 { |
| 189 | return nil, fmt.Errorf("invalid bytea sequence %v", s) |
| 190 | } |
| 191 | r, err := strconv.ParseUint(string(s[1:4]), 8, 8) |
| 192 | if err != nil { |
| 193 | return nil, fmt.Errorf("could not parse bytea value: %s", err.Error()) |
| 194 | } |
| 195 | result = append(result, byte(r)) |
| 196 | s = s[4:] |
| 197 | } else { |
| 198 | // We hit an unescaped, raw byte. Try to read in as many as |
| 199 | // possible in one go. |
| 200 | i := bytes.IndexByte(s, '\\') |
| 201 | if i == -1 { |
| 202 | result = append(result, s...) |
| 203 | break |
| 204 | } |
| 205 | result = append(result, s[:i]...) |
| 206 | s = s[i:] |
| 207 | } |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | return result, nil |
| 212 | } |
| 213 | |
| 214 | func encodeBytea(serverVersion int, v []byte) (result []byte) { |
| 215 | if serverVersion >= 90000 { |