github.com/night-codes/go-json@v0.9.15/internal/decoder/struct.go (about) 1 package decoder 2 3 import ( 4 "fmt" 5 "math" 6 "math/bits" 7 "sort" 8 "strings" 9 "unicode" 10 "unicode/utf16" 11 "unsafe" 12 13 "github.com/night-codes/go-json/internal/errors" 14 ) 15 16 type structFieldSet struct { 17 dec Decoder 18 offset uintptr 19 isTaggedKey bool 20 fieldIdx int 21 key string 22 keyLen int64 23 err error 24 } 25 26 type structDecoder struct { 27 fieldMap map[string]*structFieldSet 28 fieldUniqueNameNum int 29 stringDecoder *stringDecoder 30 structName string 31 fieldName string 32 isTriedOptimize bool 33 keyBitmapUint8 [][256]uint8 34 keyBitmapUint16 [][256]uint16 35 sortedFieldSets []*structFieldSet 36 keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error) 37 keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error) 38 } 39 40 var ( 41 largeToSmallTable [256]byte 42 ) 43 44 func init() { 45 for i := 0; i < 256; i++ { 46 c := i 47 if 'A' <= c && c <= 'Z' { 48 c += 'a' - 'A' 49 } 50 largeToSmallTable[i] = byte(c) 51 } 52 } 53 54 func newStructDecoder(structName, fieldName string, fieldMap map[string]*structFieldSet) *structDecoder { 55 return &structDecoder{ 56 fieldMap: fieldMap, 57 stringDecoder: newStringDecoder(structName, fieldName), 58 structName: structName, 59 fieldName: fieldName, 60 keyDecoder: decodeKey, 61 keyStreamDecoder: decodeKeyStream, 62 } 63 } 64 65 const ( 66 allowOptimizeMaxKeyLen = 64 67 allowOptimizeMaxFieldLen = 16 68 ) 69 70 func (d *structDecoder) tryOptimize() { 71 fieldUniqueNameMap := map[string]int{} 72 fieldIdx := -1 73 for k, v := range d.fieldMap { 74 lower := strings.ToLower(k) 75 idx, exists := fieldUniqueNameMap[lower] 76 if exists { 77 v.fieldIdx = idx 78 } else { 79 fieldIdx++ 80 v.fieldIdx = fieldIdx 81 } 82 fieldUniqueNameMap[lower] = fieldIdx 83 } 84 d.fieldUniqueNameNum = len(fieldUniqueNameMap) 85 86 if d.isTriedOptimize { 87 return 88 } 89 fieldMap := map[string]*structFieldSet{} 90 conflicted := map[string]struct{}{} 91 for k, v := range d.fieldMap { 92 key := strings.ToLower(k) 93 if key != k { 94 // already exists same key (e.g. Hello and HELLO has same lower case key 95 if _, exists := conflicted[key]; exists { 96 d.isTriedOptimize = true 97 return 98 } 99 conflicted[key] = struct{}{} 100 } 101 if field, exists := fieldMap[key]; exists { 102 if field != v { 103 d.isTriedOptimize = true 104 return 105 } 106 } 107 fieldMap[key] = v 108 } 109 110 if len(fieldMap) > allowOptimizeMaxFieldLen { 111 d.isTriedOptimize = true 112 return 113 } 114 115 var maxKeyLen int 116 sortedKeys := []string{} 117 for key := range fieldMap { 118 keyLen := len(key) 119 if keyLen > allowOptimizeMaxKeyLen { 120 d.isTriedOptimize = true 121 return 122 } 123 if maxKeyLen < keyLen { 124 maxKeyLen = keyLen 125 } 126 sortedKeys = append(sortedKeys, key) 127 } 128 sort.Strings(sortedKeys) 129 130 // By allocating one extra capacity than `maxKeyLen`, 131 // it is possible to avoid the process of comparing the index of the key with the length of the bitmap each time. 132 bitmapLen := maxKeyLen + 1 133 if len(sortedKeys) <= 8 { 134 keyBitmap := make([][256]uint8, bitmapLen) 135 for i, key := range sortedKeys { 136 for j := 0; j < len(key); j++ { 137 c := key[j] 138 keyBitmap[j][c] |= (1 << uint(i)) 139 } 140 d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key]) 141 } 142 d.keyBitmapUint8 = keyBitmap 143 d.keyDecoder = decodeKeyByBitmapUint8 144 d.keyStreamDecoder = decodeKeyByBitmapUint8Stream 145 } else { 146 keyBitmap := make([][256]uint16, bitmapLen) 147 for i, key := range sortedKeys { 148 for j := 0; j < len(key); j++ { 149 c := key[j] 150 keyBitmap[j][c] |= (1 << uint(i)) 151 } 152 d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key]) 153 } 154 d.keyBitmapUint16 = keyBitmap 155 d.keyDecoder = decodeKeyByBitmapUint16 156 d.keyStreamDecoder = decodeKeyByBitmapUint16Stream 157 } 158 } 159 160 // decode from '\uXXXX' 161 func decodeKeyCharByUnicodeRune(buf []byte, cursor int64) ([]byte, int64) { 162 const defaultOffset = 4 163 const surrogateOffset = 6 164 165 r := unicodeToRune(buf[cursor : cursor+defaultOffset]) 166 if utf16.IsSurrogate(r) { 167 cursor += defaultOffset 168 if cursor+surrogateOffset >= int64(len(buf)) || buf[cursor] != '\\' || buf[cursor+1] != 'u' { 169 return []byte(string(unicode.ReplacementChar)), cursor + defaultOffset - 1 170 } 171 cursor += 2 172 r2 := unicodeToRune(buf[cursor : cursor+defaultOffset]) 173 if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar { 174 return []byte(string(r)), cursor + defaultOffset - 1 175 } 176 } 177 return []byte(string(r)), cursor + defaultOffset - 1 178 } 179 180 func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64) { 181 c := buf[cursor] 182 cursor++ 183 switch c { 184 case '"': 185 return []byte{'"'}, cursor 186 case '\\': 187 return []byte{'\\'}, cursor 188 case '/': 189 return []byte{'/'}, cursor 190 case 'b': 191 return []byte{'\b'}, cursor 192 case 'f': 193 return []byte{'\f'}, cursor 194 case 'n': 195 return []byte{'\n'}, cursor 196 case 'r': 197 return []byte{'\r'}, cursor 198 case 't': 199 return []byte{'\t'}, cursor 200 case 'u': 201 return decodeKeyCharByUnicodeRune(buf, cursor) 202 } 203 return nil, cursor 204 } 205 206 func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { 207 var ( 208 curBit uint8 = math.MaxUint8 209 ) 210 b := (*sliceHeader)(unsafe.Pointer(&buf)).data 211 for { 212 switch char(b, cursor) { 213 case ' ', '\n', '\t', '\r': 214 cursor++ 215 case '"': 216 cursor++ 217 c := char(b, cursor) 218 switch c { 219 case '"': 220 cursor++ 221 return cursor, nil, nil 222 case nul: 223 return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) 224 } 225 keyIdx := 0 226 bitmap := d.keyBitmapUint8 227 start := cursor 228 for { 229 c := char(b, cursor) 230 switch c { 231 case '"': 232 fieldSetIndex := bits.TrailingZeros8(curBit) 233 field := d.sortedFieldSets[fieldSetIndex] 234 keyLen := cursor - start 235 cursor++ 236 if keyLen < field.keyLen { 237 // early match 238 return cursor, nil, nil 239 } 240 return cursor, field, nil 241 case nul: 242 return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) 243 case '\\': 244 cursor++ 245 chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor) 246 for _, c := range chars { 247 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 248 if curBit == 0 { 249 return decodeKeyNotFound(b, cursor) 250 } 251 keyIdx++ 252 } 253 cursor = nextCursor 254 default: 255 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 256 if curBit == 0 { 257 return decodeKeyNotFound(b, cursor) 258 } 259 keyIdx++ 260 } 261 cursor++ 262 } 263 default: 264 return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor) 265 } 266 } 267 } 268 269 func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { 270 var ( 271 curBit uint16 = math.MaxUint16 272 ) 273 b := (*sliceHeader)(unsafe.Pointer(&buf)).data 274 for { 275 switch char(b, cursor) { 276 case ' ', '\n', '\t', '\r': 277 cursor++ 278 case '"': 279 cursor++ 280 c := char(b, cursor) 281 switch c { 282 case '"': 283 cursor++ 284 return cursor, nil, nil 285 case nul: 286 return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) 287 } 288 keyIdx := 0 289 bitmap := d.keyBitmapUint16 290 start := cursor 291 for { 292 c := char(b, cursor) 293 switch c { 294 case '"': 295 fieldSetIndex := bits.TrailingZeros16(curBit) 296 field := d.sortedFieldSets[fieldSetIndex] 297 keyLen := cursor - start 298 cursor++ 299 if keyLen < field.keyLen { 300 // early match 301 return cursor, nil, nil 302 } 303 return cursor, field, nil 304 case nul: 305 return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) 306 case '\\': 307 cursor++ 308 chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor) 309 for _, c := range chars { 310 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 311 if curBit == 0 { 312 return decodeKeyNotFound(b, cursor) 313 } 314 keyIdx++ 315 } 316 cursor = nextCursor 317 default: 318 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 319 if curBit == 0 { 320 return decodeKeyNotFound(b, cursor) 321 } 322 keyIdx++ 323 } 324 cursor++ 325 } 326 default: 327 return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor) 328 } 329 } 330 } 331 332 func decodeKeyNotFound(b unsafe.Pointer, cursor int64) (int64, *structFieldSet, error) { 333 for { 334 cursor++ 335 switch char(b, cursor) { 336 case '"': 337 cursor++ 338 return cursor, nil, nil 339 case '\\': 340 cursor++ 341 if char(b, cursor) == nul { 342 return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) 343 } 344 case nul: 345 return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) 346 } 347 } 348 } 349 350 func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { 351 key, c, err := d.stringDecoder.decodeByte(buf, cursor) 352 if err != nil { 353 return 0, nil, err 354 } 355 cursor = c 356 k := *(*string)(unsafe.Pointer(&key)) 357 field, exists := d.fieldMap[k] 358 if !exists { 359 return cursor, nil, nil 360 } 361 return cursor, field, nil 362 } 363 364 func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) { 365 var ( 366 curBit uint8 = math.MaxUint8 367 ) 368 _, cursor, p := s.stat() 369 for { 370 switch char(p, cursor) { 371 case ' ', '\n', '\t', '\r': 372 cursor++ 373 case nul: 374 s.cursor = cursor 375 if s.read() { 376 _, cursor, p = s.stat() 377 continue 378 } 379 return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) 380 case '"': 381 cursor++ 382 FIRST_CHAR: 383 start := cursor 384 switch char(p, cursor) { 385 case '"': 386 cursor++ 387 s.cursor = cursor 388 return nil, "", nil 389 case nul: 390 s.cursor = cursor 391 if s.read() { 392 _, cursor, p = s.stat() 393 goto FIRST_CHAR 394 } 395 return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) 396 } 397 keyIdx := 0 398 bitmap := d.keyBitmapUint8 399 for { 400 c := char(p, cursor) 401 switch c { 402 case '"': 403 fieldSetIndex := bits.TrailingZeros8(curBit) 404 field := d.sortedFieldSets[fieldSetIndex] 405 keyLen := cursor - start 406 cursor++ 407 s.cursor = cursor 408 if keyLen < field.keyLen { 409 // early match 410 return nil, field.key, nil 411 } 412 return field, field.key, nil 413 case nul: 414 s.cursor = cursor 415 if s.read() { 416 _, cursor, p = s.stat() 417 continue 418 } 419 return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) 420 case '\\': 421 s.cursor = cursor + 1 // skip '\' char 422 chars, err := decodeKeyCharByEscapeCharStream(s) 423 if err != nil { 424 return nil, "", err 425 } 426 cursor = s.cursor 427 for _, c := range chars { 428 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 429 if curBit == 0 { 430 s.cursor = cursor 431 return decodeKeyNotFoundStream(s, start) 432 } 433 keyIdx++ 434 } 435 default: 436 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 437 if curBit == 0 { 438 s.cursor = cursor 439 return decodeKeyNotFoundStream(s, start) 440 } 441 keyIdx++ 442 } 443 cursor++ 444 } 445 default: 446 return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) 447 } 448 } 449 } 450 451 func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) { 452 var ( 453 curBit uint16 = math.MaxUint16 454 ) 455 _, cursor, p := s.stat() 456 for { 457 switch char(p, cursor) { 458 case ' ', '\n', '\t', '\r': 459 cursor++ 460 case nul: 461 s.cursor = cursor 462 if s.read() { 463 _, cursor, p = s.stat() 464 continue 465 } 466 return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) 467 case '"': 468 cursor++ 469 FIRST_CHAR: 470 start := cursor 471 switch char(p, cursor) { 472 case '"': 473 cursor++ 474 s.cursor = cursor 475 return nil, "", nil 476 case nul: 477 s.cursor = cursor 478 if s.read() { 479 _, cursor, p = s.stat() 480 goto FIRST_CHAR 481 } 482 return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) 483 } 484 keyIdx := 0 485 bitmap := d.keyBitmapUint16 486 for { 487 c := char(p, cursor) 488 switch c { 489 case '"': 490 fieldSetIndex := bits.TrailingZeros16(curBit) 491 field := d.sortedFieldSets[fieldSetIndex] 492 keyLen := cursor - start 493 cursor++ 494 s.cursor = cursor 495 if keyLen < field.keyLen { 496 // early match 497 return nil, field.key, nil 498 } 499 return field, field.key, nil 500 case nul: 501 s.cursor = cursor 502 if s.read() { 503 _, cursor, p = s.stat() 504 continue 505 } 506 return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) 507 case '\\': 508 s.cursor = cursor + 1 // skip '\' char 509 chars, err := decodeKeyCharByEscapeCharStream(s) 510 if err != nil { 511 return nil, "", err 512 } 513 cursor = s.cursor 514 for _, c := range chars { 515 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 516 if curBit == 0 { 517 s.cursor = cursor 518 return decodeKeyNotFoundStream(s, start) 519 } 520 keyIdx++ 521 } 522 default: 523 curBit &= bitmap[keyIdx][largeToSmallTable[c]] 524 if curBit == 0 { 525 s.cursor = cursor 526 return decodeKeyNotFoundStream(s, start) 527 } 528 keyIdx++ 529 } 530 cursor++ 531 } 532 default: 533 return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) 534 } 535 } 536 } 537 538 // decode from '\uXXXX' 539 func decodeKeyCharByUnicodeRuneStream(s *Stream) ([]byte, error) { 540 const defaultOffset = 4 541 const surrogateOffset = 6 542 543 if s.cursor+defaultOffset >= s.length { 544 if !s.read() { 545 return nil, errors.ErrInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset()) 546 } 547 } 548 549 r := unicodeToRune(s.buf[s.cursor : s.cursor+defaultOffset]) 550 if utf16.IsSurrogate(r) { 551 s.cursor += defaultOffset 552 if s.cursor+surrogateOffset >= s.length { 553 s.read() 554 } 555 if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor] != '\\' || s.buf[s.cursor+1] != 'u' { 556 s.cursor += defaultOffset - 1 557 return []byte(string(unicode.ReplacementChar)), nil 558 } 559 r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset]) 560 if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar { 561 s.cursor += defaultOffset - 1 562 return []byte(string(r)), nil 563 } 564 } 565 s.cursor += defaultOffset - 1 566 return []byte(string(r)), nil 567 } 568 569 func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) { 570 c := s.buf[s.cursor] 571 s.cursor++ 572 RETRY: 573 switch c { 574 case '"': 575 return []byte{'"'}, nil 576 case '\\': 577 return []byte{'\\'}, nil 578 case '/': 579 return []byte{'/'}, nil 580 case 'b': 581 return []byte{'\b'}, nil 582 case 'f': 583 return []byte{'\f'}, nil 584 case 'n': 585 return []byte{'\n'}, nil 586 case 'r': 587 return []byte{'\r'}, nil 588 case 't': 589 return []byte{'\t'}, nil 590 case 'u': 591 return decodeKeyCharByUnicodeRuneStream(s) 592 case nul: 593 if !s.read() { 594 return nil, errors.ErrInvalidCharacter(s.char(), "escaped char", s.totalOffset()) 595 } 596 goto RETRY 597 default: 598 return nil, errors.ErrUnexpectedEndOfJSON("struct field", s.totalOffset()) 599 } 600 } 601 602 func decodeKeyNotFoundStream(s *Stream, start int64) (*structFieldSet, string, error) { 603 buf, cursor, p := s.stat() 604 for { 605 cursor++ 606 switch char(p, cursor) { 607 case '"': 608 b := buf[start:cursor] 609 key := *(*string)(unsafe.Pointer(&b)) 610 cursor++ 611 s.cursor = cursor 612 return nil, key, nil 613 case '\\': 614 cursor++ 615 if char(p, cursor) == nul { 616 s.cursor = cursor 617 if !s.read() { 618 return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) 619 } 620 buf, cursor, p = s.statForRetry() 621 } 622 case nul: 623 s.cursor = cursor 624 if !s.read() { 625 return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) 626 } 627 buf, cursor, p = s.statForRetry() 628 } 629 } 630 } 631 632 func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) { 633 key, err := d.stringDecoder.decodeStreamByte(s) 634 if err != nil { 635 return nil, "", err 636 } 637 k := *(*string)(unsafe.Pointer(&key)) 638 return d.fieldMap[k], k, nil 639 } 640 641 func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { 642 depth++ 643 if depth > maxDecodeNestingDepth { 644 return errors.ErrExceededMaxDepth(s.char(), s.cursor) 645 } 646 647 c := s.skipWhiteSpace() 648 switch c { 649 case 'n': 650 if err := nullBytes(s); err != nil { 651 return err 652 } 653 return nil 654 default: 655 if s.char() != '{' { 656 return errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset()) 657 } 658 } 659 s.cursor++ 660 if s.skipWhiteSpace() == '}' { 661 s.cursor++ 662 return nil 663 } 664 var ( 665 seenFields map[int]struct{} 666 seenFieldNum int 667 ) 668 firstWin := (s.Option.Flags & FirstWinOption) != 0 669 if firstWin { 670 seenFields = make(map[int]struct{}, d.fieldUniqueNameNum) 671 } 672 for { 673 s.reset() 674 field, key, err := d.keyStreamDecoder(d, s) 675 if err != nil { 676 return err 677 } 678 if s.skipWhiteSpace() != ':' { 679 return errors.ErrExpected("colon after object key", s.totalOffset()) 680 } 681 s.cursor++ 682 if field != nil { 683 if field.err != nil { 684 return field.err 685 } 686 if firstWin { 687 if _, exists := seenFields[field.fieldIdx]; exists { 688 if err := s.skipValue(depth); err != nil { 689 return err 690 } 691 } else { 692 if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil { 693 return err 694 } 695 seenFieldNum++ 696 if d.fieldUniqueNameNum <= seenFieldNum { 697 return s.skipObject(depth) 698 } 699 seenFields[field.fieldIdx] = struct{}{} 700 } 701 } else { 702 if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil { 703 return err 704 } 705 } 706 } else if s.DisallowUnknownFields { 707 return fmt.Errorf("json: unknown field %q", key) 708 } else { 709 if err := s.skipValue(depth); err != nil { 710 return err 711 } 712 } 713 c := s.skipWhiteSpace() 714 if c == '}' { 715 s.cursor++ 716 return nil 717 } 718 if c != ',' { 719 return errors.ErrExpected("comma after object element", s.totalOffset()) 720 } 721 s.cursor++ 722 } 723 } 724 725 func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 726 buf := ctx.Buf 727 depth++ 728 if depth > maxDecodeNestingDepth { 729 return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) 730 } 731 buflen := int64(len(buf)) 732 cursor = skipWhiteSpace(buf, cursor) 733 b := (*sliceHeader)(unsafe.Pointer(&buf)).data 734 switch char(b, cursor) { 735 case 'n': 736 if err := validateNull(buf, cursor); err != nil { 737 return 0, err 738 } 739 cursor += 4 740 return cursor, nil 741 case '{': 742 default: 743 return 0, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor) 744 } 745 cursor++ 746 cursor = skipWhiteSpace(buf, cursor) 747 if buf[cursor] == '}' { 748 cursor++ 749 return cursor, nil 750 } 751 var ( 752 seenFields map[int]struct{} 753 seenFieldNum int 754 ) 755 firstWin := (ctx.Option.Flags & FirstWinOption) != 0 756 if firstWin { 757 seenFields = make(map[int]struct{}, d.fieldUniqueNameNum) 758 } 759 for { 760 c, field, err := d.keyDecoder(d, buf, cursor) 761 if err != nil { 762 return 0, err 763 } 764 cursor = skipWhiteSpace(buf, c) 765 if char(b, cursor) != ':' { 766 return 0, errors.ErrExpected("colon after object key", cursor) 767 } 768 cursor++ 769 if cursor >= buflen { 770 return 0, errors.ErrExpected("object value after colon", cursor) 771 } 772 if field != nil { 773 if field.err != nil { 774 return 0, field.err 775 } 776 if firstWin { 777 if _, exists := seenFields[field.fieldIdx]; exists { 778 c, err := skipValue(buf, cursor, depth) 779 if err != nil { 780 return 0, err 781 } 782 cursor = c 783 } else { 784 c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset)) 785 if err != nil { 786 return 0, err 787 } 788 cursor = c 789 seenFieldNum++ 790 if d.fieldUniqueNameNum <= seenFieldNum { 791 return skipObject(buf, cursor, depth) 792 } 793 seenFields[field.fieldIdx] = struct{}{} 794 } 795 } else { 796 c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset)) 797 if err != nil { 798 return 0, err 799 } 800 cursor = c 801 } 802 } else { 803 c, err := skipValue(buf, cursor, depth) 804 if err != nil { 805 return 0, err 806 } 807 cursor = c 808 } 809 cursor = skipWhiteSpace(buf, cursor) 810 if char(b, cursor) == '}' { 811 cursor++ 812 return cursor, nil 813 } 814 if char(b, cursor) != ',' { 815 return 0, errors.ErrExpected("comma after object element", cursor) 816 } 817 cursor++ 818 } 819 }