parseStringBytes parse unicode escapes and converts utf-16 surrogage pairs into utf-8 sequences. It was copied and modified [with attribution](https://github.com/brimdata/super/blob/main/acknowledgments.txt) from the encoding/json package in the Go source code.
(b *strings.Builder, bytes []byte)
| 338 | // into utf-8 sequences. It was copied and modified [with attribution](https://github.com/brimdata/super/blob/main/acknowledgments.txt) |
| 339 | // from the encoding/json package in the Go source code. |
| 340 | func parseStringBytes(b *strings.Builder, bytes []byte) (string, error) { |
| 341 | k := 0 |
| 342 | for k < len(bytes) { |
| 343 | switch c := bytes[k]; { |
| 344 | case c == '\\': |
| 345 | k++ |
| 346 | if k >= len(bytes) { |
| 347 | panic("can't happen because string scanner would look for next char") |
| 348 | } |
| 349 | switch c := bytes[k]; c { |
| 350 | default: |
| 351 | return "", fmt.Errorf("illegal escape (\\%c) in string", c) |
| 352 | case '"', '\\', '/', '\'': |
| 353 | b.WriteByte(bytes[k]) |
| 354 | k++ |
| 355 | case 'b': |
| 356 | b.WriteByte('\b') |
| 357 | k++ |
| 358 | case 'f': |
| 359 | b.WriteByte('\f') |
| 360 | k++ |
| 361 | case 'n': |
| 362 | b.WriteByte('\n') |
| 363 | k++ |
| 364 | case 'r': |
| 365 | b.WriteByte('\r') |
| 366 | k++ |
| 367 | case 't': |
| 368 | b.WriteByte('\t') |
| 369 | k++ |
| 370 | case 'u': |
| 371 | k++ |
| 372 | r, err := unhexRune(bytes[k:]) |
| 373 | if err != nil { |
| 374 | return "", err |
| 375 | } |
| 376 | k += 4 |
| 377 | if utf16.IsSurrogate(r) { |
| 378 | if len(bytes) < 6 || bytes[0] != '\\' || bytes[1] != 'u' { |
| 379 | return "", errors.New("illegal surrogate utf-16 rune pair") |
| 380 | } |
| 381 | r2, err := unhexRune(bytes[k+2:]) |
| 382 | if err != nil { |
| 383 | return "", err |
| 384 | } |
| 385 | k += 6 |
| 386 | if dec := utf16.DecodeRune(r, r2); dec != unicode.ReplacementChar { |
| 387 | // A valid pair; consume. |
| 388 | if _, err := b.WriteRune(dec); err != nil { |
| 389 | return "", err |
| 390 | } |
| 391 | } |
| 392 | } else if _, err := b.WriteRune(r); err != nil { |
| 393 | return "", err |
| 394 | } |
| 395 | } |
| 396 | case c == '"': |
| 397 | // This would be a bug as the string scanner should not |
no test coverage detected