github.com/segmentio/encoding@v0.4.0/json/encode.go (about) 1 package json 2 3 import ( 4 "encoding" 5 "fmt" 6 "math" 7 "reflect" 8 "sort" 9 "strconv" 10 "sync" 11 "time" 12 "unicode/utf8" 13 "unsafe" 14 15 "github.com/segmentio/asm/base64" 16 ) 17 18 const hex = "0123456789abcdef" 19 20 func (e encoder) encodeNull(b []byte, p unsafe.Pointer) ([]byte, error) { 21 return append(b, "null"...), nil 22 } 23 24 func (e encoder) encodeBool(b []byte, p unsafe.Pointer) ([]byte, error) { 25 if *(*bool)(p) { 26 return append(b, "true"...), nil 27 } 28 return append(b, "false"...), nil 29 } 30 31 func (e encoder) encodeInt(b []byte, p unsafe.Pointer) ([]byte, error) { 32 return appendInt(b, int64(*(*int)(p))), nil 33 } 34 35 func (e encoder) encodeInt8(b []byte, p unsafe.Pointer) ([]byte, error) { 36 return appendInt(b, int64(*(*int8)(p))), nil 37 } 38 39 func (e encoder) encodeInt16(b []byte, p unsafe.Pointer) ([]byte, error) { 40 return appendInt(b, int64(*(*int16)(p))), nil 41 } 42 43 func (e encoder) encodeInt32(b []byte, p unsafe.Pointer) ([]byte, error) { 44 return appendInt(b, int64(*(*int32)(p))), nil 45 } 46 47 func (e encoder) encodeInt64(b []byte, p unsafe.Pointer) ([]byte, error) { 48 return appendInt(b, *(*int64)(p)), nil 49 } 50 51 func (e encoder) encodeUint(b []byte, p unsafe.Pointer) ([]byte, error) { 52 return appendUint(b, uint64(*(*uint)(p))), nil 53 } 54 55 func (e encoder) encodeUintptr(b []byte, p unsafe.Pointer) ([]byte, error) { 56 return appendUint(b, uint64(*(*uintptr)(p))), nil 57 } 58 59 func (e encoder) encodeUint8(b []byte, p unsafe.Pointer) ([]byte, error) { 60 return appendUint(b, uint64(*(*uint8)(p))), nil 61 } 62 63 func (e encoder) encodeUint16(b []byte, p unsafe.Pointer) ([]byte, error) { 64 return appendUint(b, uint64(*(*uint16)(p))), nil 65 } 66 67 func (e encoder) encodeUint32(b []byte, p unsafe.Pointer) ([]byte, error) { 68 return appendUint(b, uint64(*(*uint32)(p))), nil 69 } 70 71 func (e encoder) encodeUint64(b []byte, p unsafe.Pointer) ([]byte, error) { 72 return appendUint(b, *(*uint64)(p)), nil 73 } 74 75 func (e encoder) encodeFloat32(b []byte, p unsafe.Pointer) ([]byte, error) { 76 return e.encodeFloat(b, float64(*(*float32)(p)), 32) 77 } 78 79 func (e encoder) encodeFloat64(b []byte, p unsafe.Pointer) ([]byte, error) { 80 return e.encodeFloat(b, *(*float64)(p), 64) 81 } 82 83 func (e encoder) encodeFloat(b []byte, f float64, bits int) ([]byte, error) { 84 switch { 85 case math.IsNaN(f): 86 return b, &UnsupportedValueError{Value: reflect.ValueOf(f), Str: "NaN"} 87 case math.IsInf(f, 0): 88 return b, &UnsupportedValueError{Value: reflect.ValueOf(f), Str: "inf"} 89 } 90 91 // Convert as if by ES6 number to string conversion. 92 // This matches most other JSON generators. 93 // See golang.org/issue/6384 and golang.org/issue/14135. 94 // Like fmt %g, but the exponent cutoffs are different 95 // and exponents themselves are not padded to two digits. 96 abs := math.Abs(f) 97 fmt := byte('f') 98 // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. 99 if abs != 0 { 100 if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) { 101 fmt = 'e' 102 } 103 } 104 105 b = strconv.AppendFloat(b, f, fmt, -1, int(bits)) 106 107 if fmt == 'e' { 108 // clean up e-09 to e-9 109 n := len(b) 110 if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' { 111 b[n-2] = b[n-1] 112 b = b[:n-1] 113 } 114 } 115 116 return b, nil 117 } 118 119 func (e encoder) encodeNumber(b []byte, p unsafe.Pointer) ([]byte, error) { 120 n := *(*Number)(p) 121 if n == "" { 122 n = "0" 123 } 124 125 d := decoder{} 126 _, _, _, err := d.parseNumber(stringToBytes(string(n))) 127 if err != nil { 128 return b, err 129 } 130 131 return append(b, n...), nil 132 } 133 134 func (e encoder) encodeString(b []byte, p unsafe.Pointer) ([]byte, error) { 135 s := *(*string)(p) 136 if len(s) == 0 { 137 return append(b, `""`...), nil 138 } 139 i := 0 140 j := 0 141 escapeHTML := (e.flags & EscapeHTML) != 0 142 143 b = append(b, '"') 144 145 if len(s) >= 8 { 146 if j = escapeIndex(s, escapeHTML); j < 0 { 147 return append(append(b, s...), '"'), nil 148 } 149 } 150 151 for j < len(s) { 152 c := s[j] 153 154 if c >= 0x20 && c <= 0x7f && c != '\\' && c != '"' && (!escapeHTML || (c != '<' && c != '>' && c != '&')) { 155 // fast path: most of the time, printable ascii characters are used 156 j++ 157 continue 158 } 159 160 switch c { 161 case '\\', '"': 162 b = append(b, s[i:j]...) 163 b = append(b, '\\', c) 164 i = j + 1 165 j = j + 1 166 continue 167 168 case '\n': 169 b = append(b, s[i:j]...) 170 b = append(b, '\\', 'n') 171 i = j + 1 172 j = j + 1 173 continue 174 175 case '\r': 176 b = append(b, s[i:j]...) 177 b = append(b, '\\', 'r') 178 i = j + 1 179 j = j + 1 180 continue 181 182 case '\t': 183 b = append(b, s[i:j]...) 184 b = append(b, '\\', 't') 185 i = j + 1 186 j = j + 1 187 continue 188 189 case '<', '>', '&': 190 b = append(b, s[i:j]...) 191 b = append(b, `\u00`...) 192 b = append(b, hex[c>>4], hex[c&0xF]) 193 i = j + 1 194 j = j + 1 195 continue 196 } 197 198 // This encodes bytes < 0x20 except for \t, \n and \r. 199 if c < 0x20 { 200 b = append(b, s[i:j]...) 201 b = append(b, `\u00`...) 202 b = append(b, hex[c>>4], hex[c&0xF]) 203 i = j + 1 204 j = j + 1 205 continue 206 } 207 208 r, size := utf8.DecodeRuneInString(s[j:]) 209 210 if r == utf8.RuneError && size == 1 { 211 b = append(b, s[i:j]...) 212 b = append(b, `\ufffd`...) 213 i = j + size 214 j = j + size 215 continue 216 } 217 218 switch r { 219 case '\u2028', '\u2029': 220 // U+2028 is LINE SEPARATOR. 221 // U+2029 is PARAGRAPH SEPARATOR. 222 // They are both technically valid characters in JSON strings, 223 // but don't work in JSONP, which has to be evaluated as JavaScript, 224 // and can lead to security holes there. It is valid JSON to 225 // escape them, so we do so unconditionally. 226 // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. 227 b = append(b, s[i:j]...) 228 b = append(b, `\u202`...) 229 b = append(b, hex[r&0xF]) 230 i = j + size 231 j = j + size 232 continue 233 } 234 235 j += size 236 } 237 238 b = append(b, s[i:]...) 239 b = append(b, '"') 240 return b, nil 241 } 242 243 func (e encoder) encodeToString(b []byte, p unsafe.Pointer, encode encodeFunc) ([]byte, error) { 244 i := len(b) 245 246 b, err := encode(e, b, p) 247 if err != nil { 248 return b, err 249 } 250 251 j := len(b) 252 s := b[i:] 253 254 if b, err = e.encodeString(b, unsafe.Pointer(&s)); err != nil { 255 return b, err 256 } 257 258 n := copy(b[i:], b[j:]) 259 return b[:i+n], nil 260 } 261 262 func (e encoder) encodeBytes(b []byte, p unsafe.Pointer) ([]byte, error) { 263 v := *(*[]byte)(p) 264 if v == nil { 265 return append(b, "null"...), nil 266 } 267 268 n := base64.StdEncoding.EncodedLen(len(v)) + 2 269 270 if avail := cap(b) - len(b); avail < n { 271 newB := make([]byte, cap(b)+(n-avail)) 272 copy(newB, b) 273 b = newB[:len(b)] 274 } 275 276 i := len(b) 277 j := len(b) + n 278 279 b = b[:j] 280 b[i] = '"' 281 base64.StdEncoding.Encode(b[i+1:j-1], v) 282 b[j-1] = '"' 283 return b, nil 284 } 285 286 func (e encoder) encodeDuration(b []byte, p unsafe.Pointer) ([]byte, error) { 287 b = append(b, '"') 288 b = appendDuration(b, *(*time.Duration)(p)) 289 b = append(b, '"') 290 return b, nil 291 } 292 293 func (e encoder) encodeTime(b []byte, p unsafe.Pointer) ([]byte, error) { 294 t := *(*time.Time)(p) 295 b = append(b, '"') 296 b = t.AppendFormat(b, time.RFC3339Nano) 297 b = append(b, '"') 298 return b, nil 299 } 300 301 func (e encoder) encodeArray(b []byte, p unsafe.Pointer, n int, size uintptr, t reflect.Type, encode encodeFunc) ([]byte, error) { 302 var start = len(b) 303 var err error 304 b = append(b, '[') 305 306 for i := 0; i < n; i++ { 307 if i != 0 { 308 b = append(b, ',') 309 } 310 if b, err = encode(e, b, unsafe.Pointer(uintptr(p)+(uintptr(i)*size))); err != nil { 311 return b[:start], err 312 } 313 } 314 315 b = append(b, ']') 316 return b, nil 317 } 318 319 func (e encoder) encodeSlice(b []byte, p unsafe.Pointer, size uintptr, t reflect.Type, encode encodeFunc) ([]byte, error) { 320 s := (*slice)(p) 321 322 if s.data == nil && s.len == 0 && s.cap == 0 { 323 return append(b, "null"...), nil 324 } 325 326 return e.encodeArray(b, s.data, s.len, size, t, encode) 327 } 328 329 func (e encoder) encodeMap(b []byte, p unsafe.Pointer, t reflect.Type, encodeKey, encodeValue encodeFunc, sortKeys sortFunc) ([]byte, error) { 330 m := reflect.NewAt(t, p).Elem() 331 if m.IsNil() { 332 return append(b, "null"...), nil 333 } 334 335 keys := m.MapKeys() 336 if sortKeys != nil && (e.flags&SortMapKeys) != 0 { 337 sortKeys(keys) 338 } 339 340 var start = len(b) 341 var err error 342 b = append(b, '{') 343 344 for i, k := range keys { 345 v := m.MapIndex(k) 346 347 if i != 0 { 348 b = append(b, ',') 349 } 350 351 if b, err = encodeKey(e, b, (*iface)(unsafe.Pointer(&k)).ptr); err != nil { 352 return b[:start], err 353 } 354 355 b = append(b, ':') 356 357 if b, err = encodeValue(e, b, (*iface)(unsafe.Pointer(&v)).ptr); err != nil { 358 return b[:start], err 359 } 360 } 361 362 b = append(b, '}') 363 return b, nil 364 } 365 366 type element struct { 367 key string 368 val interface{} 369 raw RawMessage 370 } 371 372 type mapslice struct { 373 elements []element 374 } 375 376 func (m *mapslice) Len() int { return len(m.elements) } 377 func (m *mapslice) Less(i, j int) bool { return m.elements[i].key < m.elements[j].key } 378 func (m *mapslice) Swap(i, j int) { m.elements[i], m.elements[j] = m.elements[j], m.elements[i] } 379 380 var mapslicePool = sync.Pool{ 381 New: func() interface{} { return new(mapslice) }, 382 } 383 384 func (e encoder) encodeMapStringInterface(b []byte, p unsafe.Pointer) ([]byte, error) { 385 m := *(*map[string]interface{})(p) 386 if m == nil { 387 return append(b, "null"...), nil 388 } 389 390 if (e.flags & SortMapKeys) == 0 { 391 // Optimized code path when the program does not need the map keys to be 392 // sorted. 393 b = append(b, '{') 394 395 if len(m) != 0 { 396 var err error 397 var i = 0 398 399 for k, v := range m { 400 if i != 0 { 401 b = append(b, ',') 402 } 403 404 b, _ = e.encodeString(b, unsafe.Pointer(&k)) 405 b = append(b, ':') 406 407 b, err = Append(b, v, e.flags) 408 if err != nil { 409 return b, err 410 } 411 412 i++ 413 } 414 } 415 416 b = append(b, '}') 417 return b, nil 418 } 419 420 s := mapslicePool.Get().(*mapslice) 421 if cap(s.elements) < len(m) { 422 s.elements = make([]element, 0, align(10, uintptr(len(m)))) 423 } 424 for key, val := range m { 425 s.elements = append(s.elements, element{key: key, val: val}) 426 } 427 sort.Sort(s) 428 429 var start = len(b) 430 var err error 431 b = append(b, '{') 432 433 for i, elem := range s.elements { 434 if i != 0 { 435 b = append(b, ',') 436 } 437 438 b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) 439 b = append(b, ':') 440 441 b, err = Append(b, elem.val, e.flags) 442 if err != nil { 443 break 444 } 445 } 446 447 for i := range s.elements { 448 s.elements[i] = element{} 449 } 450 451 s.elements = s.elements[:0] 452 mapslicePool.Put(s) 453 454 if err != nil { 455 return b[:start], err 456 } 457 458 b = append(b, '}') 459 return b, nil 460 } 461 462 func (e encoder) encodeMapStringRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) { 463 m := *(*map[string]RawMessage)(p) 464 if m == nil { 465 return append(b, "null"...), nil 466 } 467 468 if (e.flags & SortMapKeys) == 0 { 469 // Optimized code path when the program does not need the map keys to be 470 // sorted. 471 b = append(b, '{') 472 473 if len(m) != 0 { 474 var err error 475 var i = 0 476 477 for k, v := range m { 478 if i != 0 { 479 b = append(b, ',') 480 } 481 482 // encodeString doesn't return errors so we ignore it here 483 b, _ = e.encodeString(b, unsafe.Pointer(&k)) 484 b = append(b, ':') 485 486 b, err = e.encodeRawMessage(b, unsafe.Pointer(&v)) 487 if err != nil { 488 break 489 } 490 491 i++ 492 } 493 } 494 495 b = append(b, '}') 496 return b, nil 497 } 498 499 s := mapslicePool.Get().(*mapslice) 500 if cap(s.elements) < len(m) { 501 s.elements = make([]element, 0, align(10, uintptr(len(m)))) 502 } 503 for key, raw := range m { 504 s.elements = append(s.elements, element{key: key, raw: raw}) 505 } 506 sort.Sort(s) 507 508 var start = len(b) 509 var err error 510 b = append(b, '{') 511 512 for i, elem := range s.elements { 513 if i != 0 { 514 b = append(b, ',') 515 } 516 517 b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) 518 b = append(b, ':') 519 520 b, err = e.encodeRawMessage(b, unsafe.Pointer(&elem.raw)) 521 if err != nil { 522 break 523 } 524 } 525 526 for i := range s.elements { 527 s.elements[i] = element{} 528 } 529 530 s.elements = s.elements[:0] 531 mapslicePool.Put(s) 532 533 if err != nil { 534 return b[:start], err 535 } 536 537 b = append(b, '}') 538 return b, nil 539 } 540 541 func (e encoder) encodeMapStringString(b []byte, p unsafe.Pointer) ([]byte, error) { 542 m := *(*map[string]string)(p) 543 if m == nil { 544 return append(b, "null"...), nil 545 } 546 547 if (e.flags & SortMapKeys) == 0 { 548 // Optimized code path when the program does not need the map keys to be 549 // sorted. 550 b = append(b, '{') 551 552 if len(m) != 0 { 553 var i = 0 554 555 for k, v := range m { 556 if i != 0 { 557 b = append(b, ',') 558 } 559 560 // encodeString never returns an error so we ignore it here 561 b, _ = e.encodeString(b, unsafe.Pointer(&k)) 562 b = append(b, ':') 563 b, _ = e.encodeString(b, unsafe.Pointer(&v)) 564 565 i++ 566 } 567 } 568 569 b = append(b, '}') 570 return b, nil 571 } 572 573 s := mapslicePool.Get().(*mapslice) 574 if cap(s.elements) < len(m) { 575 s.elements = make([]element, 0, align(10, uintptr(len(m)))) 576 } 577 for key, val := range m { 578 v := val 579 s.elements = append(s.elements, element{key: key, val: &v}) 580 } 581 sort.Sort(s) 582 583 b = append(b, '{') 584 585 for i, elem := range s.elements { 586 if i != 0 { 587 b = append(b, ',') 588 } 589 590 // encodeString never returns an error so we ignore it here 591 b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) 592 b = append(b, ':') 593 b, _ = e.encodeString(b, unsafe.Pointer(elem.val.(*string))) 594 } 595 596 for i := range s.elements { 597 s.elements[i] = element{} 598 } 599 600 s.elements = s.elements[:0] 601 mapslicePool.Put(s) 602 603 b = append(b, '}') 604 return b, nil 605 } 606 607 func (e encoder) encodeMapStringStringSlice(b []byte, p unsafe.Pointer) ([]byte, error) { 608 m := *(*map[string][]string)(p) 609 if m == nil { 610 return append(b, "null"...), nil 611 } 612 613 var stringSize = unsafe.Sizeof("") 614 615 if (e.flags & SortMapKeys) == 0 { 616 // Optimized code path when the program does not need the map keys to be 617 // sorted. 618 b = append(b, '{') 619 620 if len(m) != 0 { 621 var err error 622 var i = 0 623 624 for k, v := range m { 625 if i != 0 { 626 b = append(b, ',') 627 } 628 629 b, _ = e.encodeString(b, unsafe.Pointer(&k)) 630 b = append(b, ':') 631 632 b, err = e.encodeSlice(b, unsafe.Pointer(&v), stringSize, sliceStringType, encoder.encodeString) 633 if err != nil { 634 return b, err 635 } 636 637 i++ 638 } 639 } 640 641 b = append(b, '}') 642 return b, nil 643 } 644 645 s := mapslicePool.Get().(*mapslice) 646 if cap(s.elements) < len(m) { 647 s.elements = make([]element, 0, align(10, uintptr(len(m)))) 648 } 649 for key, val := range m { 650 v := val 651 s.elements = append(s.elements, element{key: key, val: &v}) 652 } 653 sort.Sort(s) 654 655 var start = len(b) 656 var err error 657 b = append(b, '{') 658 659 for i, elem := range s.elements { 660 if i != 0 { 661 b = append(b, ',') 662 } 663 664 b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) 665 b = append(b, ':') 666 667 b, err = e.encodeSlice(b, unsafe.Pointer(elem.val.(*[]string)), stringSize, sliceStringType, encoder.encodeString) 668 if err != nil { 669 break 670 } 671 } 672 673 for i := range s.elements { 674 s.elements[i] = element{} 675 } 676 677 s.elements = s.elements[:0] 678 mapslicePool.Put(s) 679 680 if err != nil { 681 return b[:start], err 682 } 683 684 b = append(b, '}') 685 return b, nil 686 } 687 688 func (e encoder) encodeMapStringBool(b []byte, p unsafe.Pointer) ([]byte, error) { 689 m := *(*map[string]bool)(p) 690 if m == nil { 691 return append(b, "null"...), nil 692 } 693 694 if (e.flags & SortMapKeys) == 0 { 695 // Optimized code path when the program does not need the map keys to be 696 // sorted. 697 b = append(b, '{') 698 699 if len(m) != 0 { 700 var i = 0 701 702 for k, v := range m { 703 if i != 0 { 704 b = append(b, ',') 705 } 706 707 // encodeString never returns an error so we ignore it here 708 b, _ = e.encodeString(b, unsafe.Pointer(&k)) 709 if v { 710 b = append(b, ":true"...) 711 } else { 712 b = append(b, ":false"...) 713 } 714 715 i++ 716 } 717 } 718 719 b = append(b, '}') 720 return b, nil 721 } 722 723 s := mapslicePool.Get().(*mapslice) 724 if cap(s.elements) < len(m) { 725 s.elements = make([]element, 0, align(10, uintptr(len(m)))) 726 } 727 for key, val := range m { 728 s.elements = append(s.elements, element{key: key, val: val}) 729 } 730 sort.Sort(s) 731 732 b = append(b, '{') 733 734 for i, elem := range s.elements { 735 if i != 0 { 736 b = append(b, ',') 737 } 738 739 // encodeString never returns an error so we ignore it here 740 b, _ = e.encodeString(b, unsafe.Pointer(&elem.key)) 741 if elem.val.(bool) { 742 b = append(b, ":true"...) 743 } else { 744 b = append(b, ":false"...) 745 } 746 } 747 748 for i := range s.elements { 749 s.elements[i] = element{} 750 } 751 752 s.elements = s.elements[:0] 753 mapslicePool.Put(s) 754 755 b = append(b, '}') 756 return b, nil 757 } 758 759 func (e encoder) encodeStruct(b []byte, p unsafe.Pointer, st *structType) ([]byte, error) { 760 var start = len(b) 761 var err error 762 var k string 763 var n int 764 b = append(b, '{') 765 766 escapeHTML := (e.flags & EscapeHTML) != 0 767 768 for i := range st.fields { 769 f := &st.fields[i] 770 v := unsafe.Pointer(uintptr(p) + f.offset) 771 772 if f.omitempty && f.empty(v) { 773 continue 774 } 775 776 if escapeHTML { 777 k = f.html 778 } else { 779 k = f.json 780 } 781 782 lengthBeforeKey := len(b) 783 784 if n != 0 { 785 b = append(b, k...) 786 } else { 787 b = append(b, k[1:]...) 788 } 789 790 if b, err = f.codec.encode(e, b, v); err != nil { 791 if err == (rollback{}) { 792 b = b[:lengthBeforeKey] 793 continue 794 } 795 return b[:start], err 796 } 797 798 n++ 799 } 800 801 b = append(b, '}') 802 return b, nil 803 } 804 805 type rollback struct{} 806 807 func (rollback) Error() string { return "rollback" } 808 809 func (e encoder) encodeEmbeddedStructPointer(b []byte, p unsafe.Pointer, t reflect.Type, unexported bool, offset uintptr, encode encodeFunc) ([]byte, error) { 810 p = *(*unsafe.Pointer)(p) 811 if p == nil { 812 return b, rollback{} 813 } 814 return encode(e, b, unsafe.Pointer(uintptr(p)+offset)) 815 } 816 817 func (e encoder) encodePointer(b []byte, p unsafe.Pointer, t reflect.Type, encode encodeFunc) ([]byte, error) { 818 if p = *(*unsafe.Pointer)(p); p != nil { 819 if e.ptrDepth++; e.ptrDepth >= startDetectingCyclesAfter { 820 if _, seen := e.ptrSeen[p]; seen { 821 // TODO: reconstruct the reflect.Value from p + t so we can set 822 // the erorr's Value field? 823 return b, &UnsupportedValueError{Str: fmt.Sprintf("encountered a cycle via %s", t)} 824 } 825 if e.ptrSeen == nil { 826 e.ptrSeen = make(map[unsafe.Pointer]struct{}) 827 } 828 e.ptrSeen[p] = struct{}{} 829 defer delete(e.ptrSeen, p) 830 } 831 return encode(e, b, p) 832 } 833 return e.encodeNull(b, nil) 834 } 835 836 func (e encoder) encodeInterface(b []byte, p unsafe.Pointer) ([]byte, error) { 837 return Append(b, *(*interface{})(p), e.flags) 838 } 839 840 func (e encoder) encodeMaybeEmptyInterface(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) { 841 return Append(b, reflect.NewAt(t, p).Elem().Interface(), e.flags) 842 } 843 844 func (e encoder) encodeUnsupportedTypeError(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) { 845 return b, &UnsupportedTypeError{Type: t} 846 } 847 848 func (e encoder) encodeRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) { 849 v := *(*RawMessage)(p) 850 851 if v == nil { 852 return append(b, "null"...), nil 853 } 854 855 var s []byte 856 857 if (e.flags & TrustRawMessage) != 0 { 858 s = v 859 } else { 860 var err error 861 v = skipSpaces(v) // don't assume that a RawMessage starts with a token. 862 d := decoder{} 863 s, _, _, err = d.parseValue(v) 864 if err != nil { 865 return b, &UnsupportedValueError{Value: reflect.ValueOf(v), Str: err.Error()} 866 } 867 } 868 869 if (e.flags & EscapeHTML) != 0 { 870 return appendCompactEscapeHTML(b, s), nil 871 } 872 873 return append(b, s...), nil 874 } 875 876 func (e encoder) encodeJSONMarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) { 877 v := reflect.NewAt(t, p) 878 879 if !pointer { 880 v = v.Elem() 881 } 882 883 switch v.Kind() { 884 case reflect.Ptr, reflect.Interface: 885 if v.IsNil() { 886 return append(b, "null"...), nil 887 } 888 } 889 890 j, err := v.Interface().(Marshaler).MarshalJSON() 891 if err != nil { 892 return b, err 893 } 894 895 d := decoder{} 896 s, _, _, err := d.parseValue(j) 897 if err != nil { 898 return b, &MarshalerError{Type: t, Err: err} 899 } 900 901 if (e.flags & EscapeHTML) != 0 { 902 return appendCompactEscapeHTML(b, s), nil 903 } 904 905 return append(b, s...), nil 906 } 907 908 func (e encoder) encodeTextMarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) { 909 v := reflect.NewAt(t, p) 910 911 if !pointer { 912 v = v.Elem() 913 } 914 915 switch v.Kind() { 916 case reflect.Ptr, reflect.Interface: 917 if v.IsNil() { 918 return append(b, `null`...), nil 919 } 920 } 921 922 s, err := v.Interface().(encoding.TextMarshaler).MarshalText() 923 if err != nil { 924 return b, err 925 } 926 927 return e.encodeString(b, unsafe.Pointer(&s)) 928 } 929 930 func appendCompactEscapeHTML(dst []byte, src []byte) []byte { 931 start := 0 932 escape := false 933 inString := false 934 935 for i, c := range src { 936 if !inString { 937 switch c { 938 case '"': // enter string 939 inString = true 940 case ' ', '\n', '\r', '\t': // skip space 941 if start < i { 942 dst = append(dst, src[start:i]...) 943 } 944 start = i + 1 945 } 946 continue 947 } 948 949 if escape { 950 escape = false 951 continue 952 } 953 954 if c == '\\' { 955 escape = true 956 continue 957 } 958 959 if c == '"' { 960 inString = false 961 continue 962 } 963 964 if c == '<' || c == '>' || c == '&' { 965 if start < i { 966 dst = append(dst, src[start:i]...) 967 } 968 dst = append(dst, `\u00`...) 969 dst = append(dst, hex[c>>4], hex[c&0xF]) 970 start = i + 1 971 continue 972 } 973 974 // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9). 975 if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 { 976 if start < i { 977 dst = append(dst, src[start:i]...) 978 } 979 dst = append(dst, `\u202`...) 980 dst = append(dst, hex[src[i+2]&0xF]) 981 start = i + 3 982 continue 983 } 984 } 985 986 if start < len(src) { 987 dst = append(dst, src[start:]...) 988 } 989 990 return dst 991 }