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  }