1package decoder
2
3import (
4	"fmt"
5	"math"
6	"math/bits"
7	"sort"
8	"strings"
9	"unicode"
10	"unicode/utf16"
11	"unsafe"
12
13	"github.com/goccy/go-json/internal/errors"
14)
15
16type 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
26type 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
40var (
41	largeToSmallTable [256]byte
42)
43
44func 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
54func 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
65const (
66	allowOptimizeMaxKeyLen   = 64
67	allowOptimizeMaxFieldLen = 16
68)
69
70func (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'
161func 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
180func 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
206func 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
269func 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
332func 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
350func 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
364func 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
451func 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'
539func 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
569func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) {
570	c := s.buf[s.cursor]
571	s.cursor++
572RETRY:
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
602func 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
632func 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
641func (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
725func (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}
820