package decoder

import (
	
	

	
	
)

type mapDecoder struct {
	mapType                 *runtime.Type
	keyType                 *runtime.Type
	valueType               *runtime.Type
	canUseAssignFaststrType bool
	keyDecoder              Decoder
	valueDecoder            Decoder
	structName              string
	fieldName               string
}

func newMapDecoder( *runtime.Type,  *runtime.Type,  Decoder,  *runtime.Type,  Decoder, ,  string) *mapDecoder {
	return &mapDecoder{
		mapType:                 ,
		keyDecoder:              ,
		keyType:                 ,
		canUseAssignFaststrType: canUseAssignFaststrType(, ),
		valueType:               ,
		valueDecoder:            ,
		structName:              ,
		fieldName:               ,
	}
}

const (
	mapMaxElemSize = 128
)

// See detail: https://github.com/goccy/go-json/pull/283
func canUseAssignFaststrType( *runtime.Type,  *runtime.Type) bool {
	 := .Size() > mapMaxElemSize
	if  {
		return false
	}
	return .Kind() == reflect.String
}

//go:linkname makemap reflect.makemap
func makemap(*runtime.Type, int) unsafe.Pointer

//nolint:golint
//go:linkname mapassign_faststr runtime.mapassign_faststr
//go:noescape
func mapassign_faststr( *runtime.Type,  unsafe.Pointer,  string) unsafe.Pointer

//go:linkname mapassign reflect.mapassign
//go:noescape
func mapassign( *runtime.Type,  unsafe.Pointer, ,  unsafe.Pointer)

func ( *mapDecoder) ( *runtime.Type, , ,  unsafe.Pointer) {
	if .canUseAssignFaststrType {
		 := mapassign_faststr(, , *(*string)())
		typedmemmove(.valueType, , )
	} else {
		mapassign(, , , )
	}
}

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

	switch .skipWhiteSpace() {
	case 'n':
		if  := nullBytes();  != nil {
			return 
		}
		**(**unsafe.Pointer)(unsafe.Pointer(&)) = nil
		return nil
	case '{':
	default:
		return errors.ErrExpected("{ character for map value", .totalOffset())
	}
	 := *(*unsafe.Pointer)()
	if  == nil {
		 = makemap(.mapType, 0)
	}
	.cursor++
	if .skipWhiteSpace() == '}' {
		*(*unsafe.Pointer)() = 
		.cursor++
		return nil
	}
	for {
		 := unsafe_New(.keyType)
		if  := .keyDecoder.DecodeStream(, , );  != nil {
			return 
		}
		.skipWhiteSpace()
		if !.equalChar(':') {
			return errors.ErrExpected("colon after object key", .totalOffset())
		}
		.cursor++
		 := unsafe_New(.valueType)
		if  := .valueDecoder.DecodeStream(, , );  != nil {
			return 
		}
		.mapassign(.mapType, , , )
		.skipWhiteSpace()
		if .equalChar('}') {
			**(**unsafe.Pointer)(unsafe.Pointer(&)) = 
			.cursor++
			return nil
		}
		if !.equalChar(',') {
			return errors.ErrExpected("comma after object value", .totalOffset())
		}
		.cursor++
	}
}

func ( *mapDecoder) ( *RuntimeContext, ,  int64,  unsafe.Pointer) (int64, error) {
	 := .Buf
	++
	if  > maxDecodeNestingDepth {
		return 0, errors.ErrExceededMaxDepth([], )
	}

	 = skipWhiteSpace(, )
	 := int64(len())
	if  < 2 {
		return 0, errors.ErrExpected("{} for map", )
	}
	switch [] {
	case 'n':
		if  := validateNull(, );  != nil {
			return 0, 
		}
		 += 4
		**(**unsafe.Pointer)(unsafe.Pointer(&)) = nil
		return , nil
	case '{':
	default:
		return 0, errors.ErrExpected("{ character for map value", )
	}
	++
	 = skipWhiteSpace(, )
	 := *(*unsafe.Pointer)()
	if  == nil {
		 = makemap(.mapType, 0)
	}
	if [] == '}' {
		**(**unsafe.Pointer)(unsafe.Pointer(&)) = 
		++
		return , nil
	}
	for {
		 := unsafe_New(.keyType)
		,  := .keyDecoder.Decode(, , , )
		if  != nil {
			return 0, 
		}
		 = skipWhiteSpace(, )
		if [] != ':' {
			return 0, errors.ErrExpected("colon after object key", )
		}
		++
		 := unsafe_New(.valueType)
		,  := .valueDecoder.Decode(, , , )
		if  != nil {
			return 0, 
		}
		.mapassign(.mapType, , , )
		 = skipWhiteSpace(, )
		if [] == '}' {
			**(**unsafe.Pointer)(unsafe.Pointer(&)) = 
			++
			return , nil
		}
		if [] != ',' {
			return 0, errors.ErrExpected("comma after object value", )
		}
		++
	}
}

func ( *mapDecoder) ( *RuntimeContext, ,  int64) ([][]byte, int64, error) {
	 := .Buf
	++
	if  > maxDecodeNestingDepth {
		return nil, 0, errors.ErrExceededMaxDepth([], )
	}

	 = skipWhiteSpace(, )
	 := int64(len())
	if  < 2 {
		return nil, 0, errors.ErrExpected("{} for map", )
	}
	switch [] {
	case 'n':
		if  := validateNull(, );  != nil {
			return nil, 0, 
		}
		 += 4
		return [][]byte{nullbytes}, , nil
	case '{':
	default:
		return nil, 0, errors.ErrExpected("{ character for map value", )
	}
	++
	 = skipWhiteSpace(, )
	if [] == '}' {
		++
		return nil, , nil
	}
	,  := .keyDecoder.(*stringDecoder)
	if ! {
		return nil, 0, &errors.UnmarshalTypeError{
			Value:  "string",
			Type:   reflect.TypeOf(""),
			Offset: ,
			Struct: .structName,
			Field:  .fieldName,
		}
	}
	 := [][]byte{}
	for {
		, ,  := .decodeByte(, )
		if  != nil {
			return nil, 0, 
		}
		 = skipWhiteSpace(, )
		if [] != ':' {
			return nil, 0, errors.ErrExpected("colon after object key", )
		}
		++
		, ,  := .Option.Path.Field(string())
		if  != nil {
			return nil, 0, 
		}
		if  {
			if  != nil {
				 := .Option.Path.node
				.Option.Path.node = 
				, ,  := .valueDecoder.DecodePath(, , )
				if  != nil {
					return nil, 0, 
				}
				.Option.Path.node = 
				 = append(, ...)
				 = 
			} else {
				 := 
				,  := skipValue(, , )
				if  != nil {
					return nil, 0, 
				}
				 = append(, [:])
				 = 
			}
		} else {
			,  := skipValue(, , )
			if  != nil {
				return nil, 0, 
			}
			 = 
		}
		 = skipWhiteSpace(, )
		if [] == '}' {
			++
			return , , nil
		}
		if [] != ',' {
			return nil, 0, errors.ErrExpected("comma after object value", )
		}
		++
	}
}