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