github.com/goccy/go-json@v0.10.3-0.20240509105655-5e2ae3f23c1d/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/goccy/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  }