123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845 |
- package decoder
- import (
- "fmt"
- "math"
- "math/bits"
- "sort"
- "strings"
- "unicode"
- "unicode/utf16"
- "unsafe"
- "github.com/goccy/go-json/internal/errors"
- )
- type structFieldSet struct {
- dec Decoder
- offset uintptr
- isTaggedKey bool
- fieldIdx int
- key string
- keyLen int64
- err error
- }
- type structDecoder struct {
- fieldMap map[string]*structFieldSet
- fieldUniqueNameNum int
- stringDecoder *stringDecoder
- structName string
- fieldName string
- isTriedOptimize bool
- keyBitmapUint8 [][256]uint8
- keyBitmapUint16 [][256]uint16
- sortedFieldSets []*structFieldSet
- keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
- keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error)
- }
- var (
- largeToSmallTable [256]byte
- )
- func init() {
- for i := 0; i < 256; i++ {
- c := i
- if 'A' <= c && c <= 'Z' {
- c += 'a' - 'A'
- }
- largeToSmallTable[i] = byte(c)
- }
- }
- func toASCIILower(s string) string {
- b := []byte(s)
- for i := range b {
- b[i] = largeToSmallTable[b[i]]
- }
- return string(b)
- }
- func newStructDecoder(structName, fieldName string, fieldMap map[string]*structFieldSet) *structDecoder {
- return &structDecoder{
- fieldMap: fieldMap,
- stringDecoder: newStringDecoder(structName, fieldName),
- structName: structName,
- fieldName: fieldName,
- keyDecoder: decodeKey,
- keyStreamDecoder: decodeKeyStream,
- }
- }
- const (
- allowOptimizeMaxKeyLen = 64
- allowOptimizeMaxFieldLen = 16
- )
- func (d *structDecoder) tryOptimize() {
- fieldUniqueNameMap := map[string]int{}
- fieldIdx := -1
- for k, v := range d.fieldMap {
- lower := strings.ToLower(k)
- idx, exists := fieldUniqueNameMap[lower]
- if exists {
- v.fieldIdx = idx
- } else {
- fieldIdx++
- v.fieldIdx = fieldIdx
- }
- fieldUniqueNameMap[lower] = fieldIdx
- }
- d.fieldUniqueNameNum = len(fieldUniqueNameMap)
- if d.isTriedOptimize {
- return
- }
- fieldMap := map[string]*structFieldSet{}
- conflicted := map[string]struct{}{}
- for k, v := range d.fieldMap {
- key := strings.ToLower(k)
- if key != k {
- if key != toASCIILower(k) {
- d.isTriedOptimize = true
- return
- }
- // already exists same key (e.g. Hello and HELLO has same lower case key
- if _, exists := conflicted[key]; exists {
- d.isTriedOptimize = true
- return
- }
- conflicted[key] = struct{}{}
- }
- if field, exists := fieldMap[key]; exists {
- if field != v {
- d.isTriedOptimize = true
- return
- }
- }
- fieldMap[key] = v
- }
- if len(fieldMap) > allowOptimizeMaxFieldLen {
- d.isTriedOptimize = true
- return
- }
- var maxKeyLen int
- sortedKeys := []string{}
- for key := range fieldMap {
- keyLen := len(key)
- if keyLen > allowOptimizeMaxKeyLen {
- d.isTriedOptimize = true
- return
- }
- if maxKeyLen < keyLen {
- maxKeyLen = keyLen
- }
- sortedKeys = append(sortedKeys, key)
- }
- sort.Strings(sortedKeys)
- // By allocating one extra capacity than `maxKeyLen`,
- // it is possible to avoid the process of comparing the index of the key with the length of the bitmap each time.
- bitmapLen := maxKeyLen + 1
- if len(sortedKeys) <= 8 {
- keyBitmap := make([][256]uint8, bitmapLen)
- for i, key := range sortedKeys {
- for j := 0; j < len(key); j++ {
- c := key[j]
- keyBitmap[j][c] |= (1 << uint(i))
- }
- d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
- }
- d.keyBitmapUint8 = keyBitmap
- d.keyDecoder = decodeKeyByBitmapUint8
- d.keyStreamDecoder = decodeKeyByBitmapUint8Stream
- } else {
- keyBitmap := make([][256]uint16, bitmapLen)
- for i, key := range sortedKeys {
- for j := 0; j < len(key); j++ {
- c := key[j]
- keyBitmap[j][c] |= (1 << uint(i))
- }
- d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
- }
- d.keyBitmapUint16 = keyBitmap
- d.keyDecoder = decodeKeyByBitmapUint16
- d.keyStreamDecoder = decodeKeyByBitmapUint16Stream
- }
- }
- // decode from '\uXXXX'
- func decodeKeyCharByUnicodeRune(buf []byte, cursor int64) ([]byte, int64, error) {
- const defaultOffset = 4
- const surrogateOffset = 6
- if cursor+defaultOffset >= int64(len(buf)) {
- return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
- }
- r := unicodeToRune(buf[cursor : cursor+defaultOffset])
- if utf16.IsSurrogate(r) {
- cursor += defaultOffset
- if cursor+surrogateOffset >= int64(len(buf)) || buf[cursor] != '\\' || buf[cursor+1] != 'u' {
- return []byte(string(unicode.ReplacementChar)), cursor + defaultOffset - 1, nil
- }
- cursor += 2
- r2 := unicodeToRune(buf[cursor : cursor+defaultOffset])
- if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
- return []byte(string(r)), cursor + defaultOffset - 1, nil
- }
- }
- return []byte(string(r)), cursor + defaultOffset - 1, nil
- }
- func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64, error) {
- c := buf[cursor]
- cursor++
- switch c {
- case '"':
- return []byte{'"'}, cursor, nil
- case '\\':
- return []byte{'\\'}, cursor, nil
- case '/':
- return []byte{'/'}, cursor, nil
- case 'b':
- return []byte{'\b'}, cursor, nil
- case 'f':
- return []byte{'\f'}, cursor, nil
- case 'n':
- return []byte{'\n'}, cursor, nil
- case 'r':
- return []byte{'\r'}, cursor, nil
- case 't':
- return []byte{'\t'}, cursor, nil
- case 'u':
- return decodeKeyCharByUnicodeRune(buf, cursor)
- }
- return nil, cursor, nil
- }
- func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
- var (
- curBit uint8 = math.MaxUint8
- )
- b := (*sliceHeader)(unsafe.Pointer(&buf)).data
- for {
- switch char(b, cursor) {
- case ' ', '\n', '\t', '\r':
- cursor++
- case '"':
- cursor++
- c := char(b, cursor)
- switch c {
- case '"':
- cursor++
- return cursor, nil, nil
- case nul:
- return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
- }
- keyIdx := 0
- bitmap := d.keyBitmapUint8
- start := cursor
- for {
- c := char(b, cursor)
- switch c {
- case '"':
- fieldSetIndex := bits.TrailingZeros8(curBit)
- field := d.sortedFieldSets[fieldSetIndex]
- keyLen := cursor - start
- cursor++
- if keyLen < field.keyLen {
- // early match
- return cursor, nil, nil
- }
- return cursor, field, nil
- case nul:
- return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
- case '\\':
- cursor++
- chars, nextCursor, err := decodeKeyCharByEscapedChar(buf, cursor)
- if err != nil {
- return 0, nil, err
- }
- for _, c := range chars {
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- return decodeKeyNotFound(b, cursor)
- }
- keyIdx++
- }
- cursor = nextCursor
- default:
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- return decodeKeyNotFound(b, cursor)
- }
- keyIdx++
- }
- cursor++
- }
- default:
- return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
- }
- }
- }
- func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
- var (
- curBit uint16 = math.MaxUint16
- )
- b := (*sliceHeader)(unsafe.Pointer(&buf)).data
- for {
- switch char(b, cursor) {
- case ' ', '\n', '\t', '\r':
- cursor++
- case '"':
- cursor++
- c := char(b, cursor)
- switch c {
- case '"':
- cursor++
- return cursor, nil, nil
- case nul:
- return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
- }
- keyIdx := 0
- bitmap := d.keyBitmapUint16
- start := cursor
- for {
- c := char(b, cursor)
- switch c {
- case '"':
- fieldSetIndex := bits.TrailingZeros16(curBit)
- field := d.sortedFieldSets[fieldSetIndex]
- keyLen := cursor - start
- cursor++
- if keyLen < field.keyLen {
- // early match
- return cursor, nil, nil
- }
- return cursor, field, nil
- case nul:
- return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
- case '\\':
- cursor++
- chars, nextCursor, err := decodeKeyCharByEscapedChar(buf, cursor)
- if err != nil {
- return 0, nil, err
- }
- for _, c := range chars {
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- return decodeKeyNotFound(b, cursor)
- }
- keyIdx++
- }
- cursor = nextCursor
- default:
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- return decodeKeyNotFound(b, cursor)
- }
- keyIdx++
- }
- cursor++
- }
- default:
- return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
- }
- }
- }
- func decodeKeyNotFound(b unsafe.Pointer, cursor int64) (int64, *structFieldSet, error) {
- for {
- cursor++
- switch char(b, cursor) {
- case '"':
- cursor++
- return cursor, nil, nil
- case '\\':
- cursor++
- if char(b, cursor) == nul {
- return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
- }
- case nul:
- return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
- }
- }
- }
- func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
- key, c, err := d.stringDecoder.decodeByte(buf, cursor)
- if err != nil {
- return 0, nil, err
- }
- cursor = c
- k := *(*string)(unsafe.Pointer(&key))
- field, exists := d.fieldMap[k]
- if !exists {
- return cursor, nil, nil
- }
- return cursor, field, nil
- }
- func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
- var (
- curBit uint8 = math.MaxUint8
- )
- _, cursor, p := s.stat()
- for {
- switch char(p, cursor) {
- case ' ', '\n', '\t', '\r':
- cursor++
- case nul:
- s.cursor = cursor
- if s.read() {
- _, cursor, p = s.stat()
- continue
- }
- return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
- case '"':
- cursor++
- FIRST_CHAR:
- start := cursor
- switch char(p, cursor) {
- case '"':
- cursor++
- s.cursor = cursor
- return nil, "", nil
- case nul:
- s.cursor = cursor
- if s.read() {
- _, cursor, p = s.stat()
- goto FIRST_CHAR
- }
- return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
- }
- keyIdx := 0
- bitmap := d.keyBitmapUint8
- for {
- c := char(p, cursor)
- switch c {
- case '"':
- fieldSetIndex := bits.TrailingZeros8(curBit)
- field := d.sortedFieldSets[fieldSetIndex]
- keyLen := cursor - start
- cursor++
- s.cursor = cursor
- if keyLen < field.keyLen {
- // early match
- return nil, field.key, nil
- }
- return field, field.key, nil
- case nul:
- s.cursor = cursor
- if s.read() {
- _, cursor, p = s.stat()
- continue
- }
- return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
- case '\\':
- s.cursor = cursor + 1 // skip '\' char
- chars, err := decodeKeyCharByEscapeCharStream(s)
- if err != nil {
- return nil, "", err
- }
- cursor = s.cursor
- for _, c := range chars {
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- s.cursor = cursor
- return decodeKeyNotFoundStream(s, start)
- }
- keyIdx++
- }
- default:
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- s.cursor = cursor
- return decodeKeyNotFoundStream(s, start)
- }
- keyIdx++
- }
- cursor++
- }
- default:
- return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
- }
- }
- }
- func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
- var (
- curBit uint16 = math.MaxUint16
- )
- _, cursor, p := s.stat()
- for {
- switch char(p, cursor) {
- case ' ', '\n', '\t', '\r':
- cursor++
- case nul:
- s.cursor = cursor
- if s.read() {
- _, cursor, p = s.stat()
- continue
- }
- return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
- case '"':
- cursor++
- FIRST_CHAR:
- start := cursor
- switch char(p, cursor) {
- case '"':
- cursor++
- s.cursor = cursor
- return nil, "", nil
- case nul:
- s.cursor = cursor
- if s.read() {
- _, cursor, p = s.stat()
- goto FIRST_CHAR
- }
- return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
- }
- keyIdx := 0
- bitmap := d.keyBitmapUint16
- for {
- c := char(p, cursor)
- switch c {
- case '"':
- fieldSetIndex := bits.TrailingZeros16(curBit)
- field := d.sortedFieldSets[fieldSetIndex]
- keyLen := cursor - start
- cursor++
- s.cursor = cursor
- if keyLen < field.keyLen {
- // early match
- return nil, field.key, nil
- }
- return field, field.key, nil
- case nul:
- s.cursor = cursor
- if s.read() {
- _, cursor, p = s.stat()
- continue
- }
- return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
- case '\\':
- s.cursor = cursor + 1 // skip '\' char
- chars, err := decodeKeyCharByEscapeCharStream(s)
- if err != nil {
- return nil, "", err
- }
- cursor = s.cursor
- for _, c := range chars {
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- s.cursor = cursor
- return decodeKeyNotFoundStream(s, start)
- }
- keyIdx++
- }
- default:
- curBit &= bitmap[keyIdx][largeToSmallTable[c]]
- if curBit == 0 {
- s.cursor = cursor
- return decodeKeyNotFoundStream(s, start)
- }
- keyIdx++
- }
- cursor++
- }
- default:
- return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
- }
- }
- }
- // decode from '\uXXXX'
- func decodeKeyCharByUnicodeRuneStream(s *Stream) ([]byte, error) {
- const defaultOffset = 4
- const surrogateOffset = 6
- if s.cursor+defaultOffset >= s.length {
- if !s.read() {
- return nil, errors.ErrInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset())
- }
- }
- r := unicodeToRune(s.buf[s.cursor : s.cursor+defaultOffset])
- if utf16.IsSurrogate(r) {
- s.cursor += defaultOffset
- if s.cursor+surrogateOffset >= s.length {
- s.read()
- }
- if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor] != '\\' || s.buf[s.cursor+1] != 'u' {
- s.cursor += defaultOffset - 1
- return []byte(string(unicode.ReplacementChar)), nil
- }
- r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset])
- if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
- s.cursor += defaultOffset - 1
- return []byte(string(r)), nil
- }
- }
- s.cursor += defaultOffset - 1
- return []byte(string(r)), nil
- }
- func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) {
- c := s.buf[s.cursor]
- s.cursor++
- RETRY:
- switch c {
- case '"':
- return []byte{'"'}, nil
- case '\\':
- return []byte{'\\'}, nil
- case '/':
- return []byte{'/'}, nil
- case 'b':
- return []byte{'\b'}, nil
- case 'f':
- return []byte{'\f'}, nil
- case 'n':
- return []byte{'\n'}, nil
- case 'r':
- return []byte{'\r'}, nil
- case 't':
- return []byte{'\t'}, nil
- case 'u':
- return decodeKeyCharByUnicodeRuneStream(s)
- case nul:
- if !s.read() {
- return nil, errors.ErrInvalidCharacter(s.char(), "escaped char", s.totalOffset())
- }
- goto RETRY
- default:
- return nil, errors.ErrUnexpectedEndOfJSON("struct field", s.totalOffset())
- }
- }
- func decodeKeyNotFoundStream(s *Stream, start int64) (*structFieldSet, string, error) {
- buf, cursor, p := s.stat()
- for {
- cursor++
- switch char(p, cursor) {
- case '"':
- b := buf[start:cursor]
- key := *(*string)(unsafe.Pointer(&b))
- cursor++
- s.cursor = cursor
- return nil, key, nil
- case '\\':
- cursor++
- if char(p, cursor) == nul {
- s.cursor = cursor
- if !s.read() {
- return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
- }
- buf, cursor, p = s.statForRetry()
- }
- case nul:
- s.cursor = cursor
- if !s.read() {
- return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
- }
- buf, cursor, p = s.statForRetry()
- }
- }
- }
- func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
- key, err := d.stringDecoder.decodeStreamByte(s)
- if err != nil {
- return nil, "", err
- }
- k := *(*string)(unsafe.Pointer(&key))
- return d.fieldMap[k], k, nil
- }
- func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
- depth++
- if depth > maxDecodeNestingDepth {
- return errors.ErrExceededMaxDepth(s.char(), s.cursor)
- }
- c := s.skipWhiteSpace()
- switch c {
- case 'n':
- if err := nullBytes(s); err != nil {
- return err
- }
- return nil
- default:
- if s.char() != '{' {
- return errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
- }
- }
- s.cursor++
- if s.skipWhiteSpace() == '}' {
- s.cursor++
- return nil
- }
- var (
- seenFields map[int]struct{}
- seenFieldNum int
- )
- firstWin := (s.Option.Flags & FirstWinOption) != 0
- if firstWin {
- seenFields = make(map[int]struct{}, d.fieldUniqueNameNum)
- }
- for {
- s.reset()
- field, key, err := d.keyStreamDecoder(d, s)
- if err != nil {
- return err
- }
- if s.skipWhiteSpace() != ':' {
- return errors.ErrExpected("colon after object key", s.totalOffset())
- }
- s.cursor++
- if field != nil {
- if field.err != nil {
- return field.err
- }
- if firstWin {
- if _, exists := seenFields[field.fieldIdx]; exists {
- if err := s.skipValue(depth); err != nil {
- return err
- }
- } else {
- if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
- return err
- }
- seenFieldNum++
- if d.fieldUniqueNameNum <= seenFieldNum {
- return s.skipObject(depth)
- }
- seenFields[field.fieldIdx] = struct{}{}
- }
- } else {
- if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
- return err
- }
- }
- } else if s.DisallowUnknownFields {
- return fmt.Errorf("json: unknown field %q", key)
- } else {
- if err := s.skipValue(depth); err != nil {
- return err
- }
- }
- c := s.skipWhiteSpace()
- if c == '}' {
- s.cursor++
- return nil
- }
- if c != ',' {
- return errors.ErrExpected("comma after object element", s.totalOffset())
- }
- s.cursor++
- }
- }
- func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
- buf := ctx.Buf
- depth++
- if depth > maxDecodeNestingDepth {
- return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
- }
- buflen := int64(len(buf))
- cursor = skipWhiteSpace(buf, cursor)
- b := (*sliceHeader)(unsafe.Pointer(&buf)).data
- switch char(b, cursor) {
- case 'n':
- if err := validateNull(buf, cursor); err != nil {
- return 0, err
- }
- cursor += 4
- return cursor, nil
- case '{':
- default:
- return 0, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
- }
- cursor++
- cursor = skipWhiteSpace(buf, cursor)
- if buf[cursor] == '}' {
- cursor++
- return cursor, nil
- }
- var (
- seenFields map[int]struct{}
- seenFieldNum int
- )
- firstWin := (ctx.Option.Flags & FirstWinOption) != 0
- if firstWin {
- seenFields = make(map[int]struct{}, d.fieldUniqueNameNum)
- }
- for {
- c, field, err := d.keyDecoder(d, buf, cursor)
- if err != nil {
- return 0, err
- }
- cursor = skipWhiteSpace(buf, c)
- if char(b, cursor) != ':' {
- return 0, errors.ErrExpected("colon after object key", cursor)
- }
- cursor++
- if cursor >= buflen {
- return 0, errors.ErrExpected("object value after colon", cursor)
- }
- if field != nil {
- if field.err != nil {
- return 0, field.err
- }
- if firstWin {
- if _, exists := seenFields[field.fieldIdx]; exists {
- c, err := skipValue(buf, cursor, depth)
- if err != nil {
- return 0, err
- }
- cursor = c
- } else {
- c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
- if err != nil {
- return 0, err
- }
- cursor = c
- seenFieldNum++
- if d.fieldUniqueNameNum <= seenFieldNum {
- return skipObject(buf, cursor, depth)
- }
- seenFields[field.fieldIdx] = struct{}{}
- }
- } else {
- c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
- if err != nil {
- return 0, err
- }
- cursor = c
- }
- } else {
- c, err := skipValue(buf, cursor, depth)
- if err != nil {
- return 0, err
- }
- cursor = c
- }
- cursor = skipWhiteSpace(buf, cursor)
- if char(b, cursor) == '}' {
- cursor++
- return cursor, nil
- }
- if char(b, cursor) != ',' {
- return 0, errors.ErrExpected("comma after object element", cursor)
- }
- cursor++
- }
- }
- func (d *structDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
- return nil, 0, fmt.Errorf("json: struct decoder does not support decode path")
- }
|