package decoder

import (
	
	
	
	
	
	
	
	

	
)

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  := 0;  < 256; ++ {
		 := 
		if 'A' <=  &&  <= 'Z' {
			 += 'a' - 'A'
		}
		largeToSmallTable[] = byte()
	}
}

func toASCIILower( string) string {
	 := []byte()
	for  := range  {
		[] = largeToSmallTable[[]]
	}
	return string()
}

func newStructDecoder(,  string,  map[string]*structFieldSet) *structDecoder {
	return &structDecoder{
		fieldMap:         ,
		stringDecoder:    newStringDecoder(, ),
		structName:       ,
		fieldName:        ,
		keyDecoder:       decodeKey,
		keyStreamDecoder: decodeKeyStream,
	}
}

const (
	allowOptimizeMaxKeyLen   = 64
	allowOptimizeMaxFieldLen = 16
)

func ( *structDecoder) () {
	 := map[string]int{}
	 := -1
	for ,  := range .fieldMap {
		 := strings.ToLower()
		,  := []
		if  {
			.fieldIdx = 
		} else {
			++
			.fieldIdx = 
		}
		[] = 
	}
	.fieldUniqueNameNum = len()

	if .isTriedOptimize {
		return
	}
	 := map[string]*structFieldSet{}
	 := map[string]struct{}{}
	for ,  := range .fieldMap {
		 := strings.ToLower()
		if  !=  {
			if  != toASCIILower() {
				.isTriedOptimize = true
				return
			}
			// already exists same key (e.g. Hello and HELLO has same lower case key
			if ,  := [];  {
				.isTriedOptimize = true
				return
			}
			[] = struct{}{}
		}
		if ,  := [];  {
			if  !=  {
				.isTriedOptimize = true
				return
			}
		}
		[] = 
	}

	if len() > allowOptimizeMaxFieldLen {
		.isTriedOptimize = true
		return
	}

	var  int
	 := []string{}
	for  := range  {
		 := len()
		if  > allowOptimizeMaxKeyLen {
			.isTriedOptimize = true
			return
		}
		if  <  {
			 = 
		}
		 = append(, )
	}
	sort.Strings()

	// 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.
	 :=  + 1
	if len() <= 8 {
		 := make([][256]uint8, )
		for ,  := range  {
			for  := 0;  < len(); ++ {
				 := []
				[][] |= (1 << uint())
			}
			.sortedFieldSets = append(.sortedFieldSets, [])
		}
		.keyBitmapUint8 = 
		.keyDecoder = decodeKeyByBitmapUint8
		.keyStreamDecoder = decodeKeyByBitmapUint8Stream
	} else {
		 := make([][256]uint16, )
		for ,  := range  {
			for  := 0;  < len(); ++ {
				 := []
				[][] |= (1 << uint())
			}
			.sortedFieldSets = append(.sortedFieldSets, [])
		}
		.keyBitmapUint16 = 
		.keyDecoder = decodeKeyByBitmapUint16
		.keyStreamDecoder = decodeKeyByBitmapUint16Stream
	}
}

// decode from '\uXXXX'
func decodeKeyCharByUnicodeRune( []byte,  int64) ([]byte, int64, error) {
	const  = 4
	const  = 6

	if + >= int64(len()) {
		return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", )
	}

	 := unicodeToRune([ : +])
	if utf16.IsSurrogate() {
		 += 
		if + >= int64(len()) || [] != '\\' || [+1] != 'u' {
			return []byte(string(unicode.ReplacementChar)),  +  - 1, nil
		}
		 += 2
		 := unicodeToRune([ : +])
		if  := utf16.DecodeRune(, );  != unicode.ReplacementChar {
			return []byte(string()),  +  - 1, nil
		}
	}
	return []byte(string()),  +  - 1, nil
}

func decodeKeyCharByEscapedChar( []byte,  int64) ([]byte, int64, error) {
	 := []
	++
	switch  {
	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 decodeKeyCharByUnicodeRune(, )
	}
	return nil, , nil
}

func decodeKeyByBitmapUint8( *structDecoder,  []byte,  int64) (int64, *structFieldSet, error) {
	var (
		 uint8 = math.MaxUint8
	)
	 := (*sliceHeader)(unsafe.Pointer(&)).data
	for {
		switch char(, ) {
		case ' ', '\n', '\t', '\r':
			++
		case '"':
			++
			 := char(, )
			switch  {
			case '"':
				++
				return , nil, nil
			case nul:
				return 0, nil, errors.ErrUnexpectedEndOfJSON("string", )
			}
			 := 0
			 := .keyBitmapUint8
			 := 
			for {
				 := char(, )
				switch  {
				case '"':
					 := bits.TrailingZeros8()
					 := .sortedFieldSets[]
					 :=  - 
					++
					if  < .keyLen {
						// early match
						return , nil, nil
					}
					return , , nil
				case nul:
					return 0, nil, errors.ErrUnexpectedEndOfJSON("string", )
				case '\\':
					++
					, ,  := decodeKeyCharByEscapedChar(, )
					if  != nil {
						return 0, nil, 
					}
					for ,  := range  {
						 &= [][largeToSmallTable[]]
						if  == 0 {
							return decodeKeyNotFound(, )
						}
						++
					}
					 = 
				default:
					 &= [][largeToSmallTable[]]
					if  == 0 {
						return decodeKeyNotFound(, )
					}
					++
				}
				++
			}
		default:
			return , nil, errors.ErrInvalidBeginningOfValue(char(, ), )
		}
	}
}

func decodeKeyByBitmapUint16( *structDecoder,  []byte,  int64) (int64, *structFieldSet, error) {
	var (
		 uint16 = math.MaxUint16
	)
	 := (*sliceHeader)(unsafe.Pointer(&)).data
	for {
		switch char(, ) {
		case ' ', '\n', '\t', '\r':
			++
		case '"':
			++
			 := char(, )
			switch  {
			case '"':
				++
				return , nil, nil
			case nul:
				return 0, nil, errors.ErrUnexpectedEndOfJSON("string", )
			}
			 := 0
			 := .keyBitmapUint16
			 := 
			for {
				 := char(, )
				switch  {
				case '"':
					 := bits.TrailingZeros16()
					 := .sortedFieldSets[]
					 :=  - 
					++
					if  < .keyLen {
						// early match
						return , nil, nil
					}
					return , , nil
				case nul:
					return 0, nil, errors.ErrUnexpectedEndOfJSON("string", )
				case '\\':
					++
					, ,  := decodeKeyCharByEscapedChar(, )
					if  != nil {
						return 0, nil, 
					}
					for ,  := range  {
						 &= [][largeToSmallTable[]]
						if  == 0 {
							return decodeKeyNotFound(, )
						}
						++
					}
					 = 
				default:
					 &= [][largeToSmallTable[]]
					if  == 0 {
						return decodeKeyNotFound(, )
					}
					++
				}
				++
			}
		default:
			return , nil, errors.ErrInvalidBeginningOfValue(char(, ), )
		}
	}
}

func decodeKeyNotFound( unsafe.Pointer,  int64) (int64, *structFieldSet, error) {
	for {
		++
		switch char(, ) {
		case '"':
			++
			return , nil, nil
		case '\\':
			++
			if char(, ) == nul {
				return 0, nil, errors.ErrUnexpectedEndOfJSON("string", )
			}
		case nul:
			return 0, nil, errors.ErrUnexpectedEndOfJSON("string", )
		}
	}
}

func decodeKey( *structDecoder,  []byte,  int64) (int64, *structFieldSet, error) {
	, ,  := .stringDecoder.decodeByte(, )
	if  != nil {
		return 0, nil, 
	}
	 = 
	 := *(*string)(unsafe.Pointer(&))
	,  := .fieldMap[]
	if ! {
		return , nil, nil
	}
	return , , nil
}

func decodeKeyByBitmapUint8Stream( *structDecoder,  *Stream) (*structFieldSet, string, error) {
	var (
		 uint8 = math.MaxUint8
	)
	, ,  := .stat()
	for {
		switch char(, ) {
		case ' ', '\n', '\t', '\r':
			++
		case nul:
			.cursor = 
			if .read() {
				_, ,  = .stat()
				continue
			}
			return nil, "", errors.ErrInvalidBeginningOfValue(char(, ), .totalOffset())
		case '"':
			++
		:
			 := 
			switch char(, ) {
			case '"':
				++
				.cursor = 
				return nil, "", nil
			case nul:
				.cursor = 
				if .read() {
					_, ,  = .stat()
					goto 
				}
				return nil, "", errors.ErrUnexpectedEndOfJSON("string", .totalOffset())
			}
			 := 0
			 := .keyBitmapUint8
			for {
				 := char(, )
				switch  {
				case '"':
					 := bits.TrailingZeros8()
					 := .sortedFieldSets[]
					 :=  - 
					++
					.cursor = 
					if  < .keyLen {
						// early match
						return nil, .key, nil
					}
					return , .key, nil
				case nul:
					.cursor = 
					if .read() {
						_, ,  = .stat()
						continue
					}
					return nil, "", errors.ErrUnexpectedEndOfJSON("string", .totalOffset())
				case '\\':
					.cursor =  + 1 // skip '\' char
					,  := decodeKeyCharByEscapeCharStream()
					if  != nil {
						return nil, "", 
					}
					 = .cursor
					for ,  := range  {
						 &= [][largeToSmallTable[]]
						if  == 0 {
							.cursor = 
							return decodeKeyNotFoundStream(, )
						}
						++
					}
				default:
					 &= [][largeToSmallTable[]]
					if  == 0 {
						.cursor = 
						return decodeKeyNotFoundStream(, )
					}
					++
				}
				++
			}
		default:
			return nil, "", errors.ErrInvalidBeginningOfValue(char(, ), .totalOffset())
		}
	}
}

func decodeKeyByBitmapUint16Stream( *structDecoder,  *Stream) (*structFieldSet, string, error) {
	var (
		 uint16 = math.MaxUint16
	)
	, ,  := .stat()
	for {
		switch char(, ) {
		case ' ', '\n', '\t', '\r':
			++
		case nul:
			.cursor = 
			if .read() {
				_, ,  = .stat()
				continue
			}
			return nil, "", errors.ErrInvalidBeginningOfValue(char(, ), .totalOffset())
		case '"':
			++
		:
			 := 
			switch char(, ) {
			case '"':
				++
				.cursor = 
				return nil, "", nil
			case nul:
				.cursor = 
				if .read() {
					_, ,  = .stat()
					goto 
				}
				return nil, "", errors.ErrUnexpectedEndOfJSON("string", .totalOffset())
			}
			 := 0
			 := .keyBitmapUint16
			for {
				 := char(, )
				switch  {
				case '"':
					 := bits.TrailingZeros16()
					 := .sortedFieldSets[]
					 :=  - 
					++
					.cursor = 
					if  < .keyLen {
						// early match
						return nil, .key, nil
					}
					return , .key, nil
				case nul:
					.cursor = 
					if .read() {
						_, ,  = .stat()
						continue
					}
					return nil, "", errors.ErrUnexpectedEndOfJSON("string", .totalOffset())
				case '\\':
					.cursor =  + 1 // skip '\' char
					,  := decodeKeyCharByEscapeCharStream()
					if  != nil {
						return nil, "", 
					}
					 = .cursor
					for ,  := range  {
						 &= [][largeToSmallTable[]]
						if  == 0 {
							.cursor = 
							return decodeKeyNotFoundStream(, )
						}
						++
					}
				default:
					 &= [][largeToSmallTable[]]
					if  == 0 {
						.cursor = 
						return decodeKeyNotFoundStream(, )
					}
					++
				}
				++
			}
		default:
			return nil, "", errors.ErrInvalidBeginningOfValue(char(, ), .totalOffset())
		}
	}
}

// decode from '\uXXXX'
func decodeKeyCharByUnicodeRuneStream( *Stream) ([]byte, error) {
	const  = 4
	const  = 6

	if .cursor+ >= .length {
		if !.read() {
			return nil, errors.ErrInvalidCharacter(.char(), "escaped unicode char", .totalOffset())
		}
	}

	 := unicodeToRune(.buf[.cursor : .cursor+])
	if utf16.IsSurrogate() {
		.cursor += 
		if .cursor+ >= .length {
			.read()
		}
		if .cursor+ >= .length || .buf[.cursor] != '\\' || .buf[.cursor+1] != 'u' {
			.cursor +=  - 1
			return []byte(string(unicode.ReplacementChar)), nil
		}
		 := unicodeToRune(.buf[.cursor++2 : .cursor+])
		if  := utf16.DecodeRune(, );  != unicode.ReplacementChar {
			.cursor +=  - 1
			return []byte(string()), nil
		}
	}
	.cursor +=  - 1
	return []byte(string()), nil
}

func decodeKeyCharByEscapeCharStream( *Stream) ([]byte, error) {
	 := .buf[.cursor]
	.cursor++
:
	switch  {
	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()
	case nul:
		if !.read() {
			return nil, errors.ErrInvalidCharacter(.char(), "escaped char", .totalOffset())
		}
		goto 
	default:
		return nil, errors.ErrUnexpectedEndOfJSON("struct field", .totalOffset())
	}
}

func decodeKeyNotFoundStream( *Stream,  int64) (*structFieldSet, string, error) {
	, ,  := .stat()
	for {
		++
		switch char(, ) {
		case '"':
			 := [:]
			 := *(*string)(unsafe.Pointer(&))
			++
			.cursor = 
			return nil, , nil
		case '\\':
			++
			if char(, ) == nul {
				.cursor = 
				if !.read() {
					return nil, "", errors.ErrUnexpectedEndOfJSON("string", .totalOffset())
				}
				, ,  = .statForRetry()
			}
		case nul:
			.cursor = 
			if !.read() {
				return nil, "", errors.ErrUnexpectedEndOfJSON("string", .totalOffset())
			}
			, ,  = .statForRetry()
		}
	}
}

func decodeKeyStream( *structDecoder,  *Stream) (*structFieldSet, string, error) {
	,  := .stringDecoder.decodeStreamByte()
	if  != nil {
		return nil, "", 
	}
	 := *(*string)(unsafe.Pointer(&))
	return .fieldMap[], , nil
}

func ( *structDecoder) ( *Stream,  int64,  unsafe.Pointer) error {
	++
	if  > maxDecodeNestingDepth {
		return errors.ErrExceededMaxDepth(.char(), .cursor)
	}

	 := .skipWhiteSpace()
	switch  {
	case 'n':
		if  := nullBytes();  != nil {
			return 
		}
		return nil
	default:
		if .char() != '{' {
			return errors.ErrInvalidBeginningOfValue(.char(), .totalOffset())
		}
	}
	.cursor++
	if .skipWhiteSpace() == '}' {
		.cursor++
		return nil
	}
	var (
		   map[int]struct{}
		 int
	)
	 := (.Option.Flags & FirstWinOption) != 0
	if  {
		 = make(map[int]struct{}, .fieldUniqueNameNum)
	}
	for {
		.reset()
		, ,  := .keyStreamDecoder(, )
		if  != nil {
			return 
		}
		if .skipWhiteSpace() != ':' {
			return errors.ErrExpected("colon after object key", .totalOffset())
		}
		.cursor++
		if  != nil {
			if .err != nil {
				return .err
			}
			if  {
				if ,  := [.fieldIdx];  {
					if  := .skipValue();  != nil {
						return 
					}
				} else {
					if  := .dec.DecodeStream(, , unsafe.Pointer(uintptr()+.offset));  != nil {
						return 
					}
					++
					if .fieldUniqueNameNum <=  {
						return .skipObject()
					}
					[.fieldIdx] = struct{}{}
				}
			} else {
				if  := .dec.DecodeStream(, , unsafe.Pointer(uintptr()+.offset));  != nil {
					return 
				}
			}
		} else if .DisallowUnknownFields {
			return fmt.Errorf("json: unknown field %q", )
		} else {
			if  := .skipValue();  != nil {
				return 
			}
		}
		 := .skipWhiteSpace()
		if  == '}' {
			.cursor++
			return nil
		}
		if  != ',' {
			return errors.ErrExpected("comma after object element", .totalOffset())
		}
		.cursor++
	}
}

func ( *structDecoder) ( *RuntimeContext, ,  int64,  unsafe.Pointer) (int64, error) {
	 := .Buf
	++
	if  > maxDecodeNestingDepth {
		return 0, errors.ErrExceededMaxDepth([], )
	}
	 := int64(len())
	 = skipWhiteSpace(, )
	 := (*sliceHeader)(unsafe.Pointer(&)).data
	switch char(, ) {
	case 'n':
		if  := validateNull(, );  != nil {
			return 0, 
		}
		 += 4
		return , nil
	case '{':
	default:
		return 0, errors.ErrInvalidBeginningOfValue(char(, ), )
	}
	++
	 = skipWhiteSpace(, )
	if [] == '}' {
		++
		return , nil
	}
	var (
		   map[int]struct{}
		 int
	)
	 := (.Option.Flags & FirstWinOption) != 0
	if  {
		 = make(map[int]struct{}, .fieldUniqueNameNum)
	}
	for {
		, ,  := .keyDecoder(, , )
		if  != nil {
			return 0, 
		}
		 = skipWhiteSpace(, )
		if char(, ) != ':' {
			return 0, errors.ErrExpected("colon after object key", )
		}
		++
		if  >=  {
			return 0, errors.ErrExpected("object value after colon", )
		}
		if  != nil {
			if .err != nil {
				return 0, .err
			}
			if  {
				if ,  := [.fieldIdx];  {
					,  := skipValue(, , )
					if  != nil {
						return 0, 
					}
					 = 
				} else {
					,  := .dec.Decode(, , , unsafe.Pointer(uintptr()+.offset))
					if  != nil {
						return 0, 
					}
					 = 
					++
					if .fieldUniqueNameNum <=  {
						return skipObject(, , )
					}
					[.fieldIdx] = struct{}{}
				}
			} else {
				,  := .dec.Decode(, , , unsafe.Pointer(uintptr()+.offset))
				if  != nil {
					return 0, 
				}
				 = 
			}
		} else {
			,  := skipValue(, , )
			if  != nil {
				return 0, 
			}
			 = 
		}
		 = skipWhiteSpace(, )
		if char(, ) == '}' {
			++
			return , nil
		}
		if char(, ) != ',' {
			return 0, errors.ErrExpected("comma after object element", )
		}
		++
	}
}

func ( *structDecoder) ( *RuntimeContext, ,  int64) ([][]byte, int64, error) {
	return nil, 0, fmt.Errorf("json: struct decoder does not support decode path")
}