package jsoniter

import (
	
	
	

	
)

// ValDecoder is an internal type registered to cache as needed.
// Don't confuse jsoniter.ValDecoder with json.Decoder.
// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link).
//
// Reflection on type to create decoders, which is then cached
// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions
// 1. create instance of new value, for example *int will need a int to be allocated
// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New
// 3. assignment to map, both key and value will be reflect.Value
// For a simple struct binding, it will be reflect.Value free and allocation free
type ValDecoder interface {
	Decode(ptr unsafe.Pointer, iter *Iterator)
}

// ValEncoder is an internal type registered to cache as needed.
// Don't confuse jsoniter.ValEncoder with json.Encoder.
// For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link).
type ValEncoder interface {
	IsEmpty(ptr unsafe.Pointer) bool
	Encode(ptr unsafe.Pointer, stream *Stream)
}

type checkIsEmpty interface {
	IsEmpty(ptr unsafe.Pointer) bool
}

type ctx struct {
	*frozenConfig
	prefix   string
	encoders map[reflect2.Type]ValEncoder
	decoders map[reflect2.Type]ValDecoder
}

func ( *ctx) () bool {
	if .frozenConfig == nil {
		// default is case-insensitive
		return false
	}
	return .frozenConfig.caseSensitive
}

func ( *ctx) ( string) *ctx {
	return &ctx{
		frozenConfig: .frozenConfig,
		prefix:       .prefix + " " + ,
		encoders:     .encoders,
		decoders:     .decoders,
	}
}

// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
func ( *Iterator) ( interface{}) {
	 := .depth
	 := reflect2.RTypeOf()
	 := .cfg.getDecoderFromCache()
	if  == nil {
		 := reflect2.TypeOf()
		if  == nil || .Kind() != reflect.Ptr {
			.ReportError("ReadVal", "can only unmarshal into pointer")
			return
		}
		 = .cfg.DecoderOf()
	}
	 := reflect2.PtrOf()
	if  == nil {
		.ReportError("ReadVal", "can not read into nil pointer")
		return
	}
	.Decode(, )
	if .depth !=  {
		.ReportError("ReadVal", "unexpected mismatched nesting")
		return
	}
}

// WriteVal copy the go interface into underlying JSON, same as json.Marshal
func ( *Stream) ( interface{}) {
	if nil ==  {
		.WriteNil()
		return
	}
	 := reflect2.RTypeOf()
	 := .cfg.getEncoderFromCache()
	if  == nil {
		 := reflect2.TypeOf()
		 = .cfg.EncoderOf()
	}
	.Encode(reflect2.PtrOf(), )
}

func ( *frozenConfig) ( reflect2.Type) ValDecoder {
	 := .RType()
	 := .getDecoderFromCache()
	if  != nil {
		return 
	}
	 := &ctx{
		frozenConfig: ,
		prefix:       "",
		decoders:     map[reflect2.Type]ValDecoder{},
		encoders:     map[reflect2.Type]ValEncoder{},
	}
	 := .(*reflect2.UnsafePtrType)
	 = decoderOfType(, .Elem())
	.addDecoderToCache(, )
	return 
}

func decoderOfType( *ctx,  reflect2.Type) ValDecoder {
	 := getTypeDecoderFromExtension(, )
	if  != nil {
		return 
	}
	 = createDecoderOfType(, )
	for ,  := range extensions {
		 = .DecorateDecoder(, )
	}
	 = .decoderExtension.DecorateDecoder(, )
	for ,  := range .extraExtensions {
		 = .DecorateDecoder(, )
	}
	return 
}

func createDecoderOfType( *ctx,  reflect2.Type) ValDecoder {
	 := .decoders[]
	if  != nil {
		return 
	}
	 := &placeholderDecoder{}
	.decoders[] = 
	 = _createDecoderOfType(, )
	.decoder = 
	return 
}

func _createDecoderOfType( *ctx,  reflect2.Type) ValDecoder {
	 := createDecoderOfJsonRawMessage(, )
	if  != nil {
		return 
	}
	 = createDecoderOfJsonNumber(, )
	if  != nil {
		return 
	}
	 = createDecoderOfMarshaler(, )
	if  != nil {
		return 
	}
	 = createDecoderOfAny(, )
	if  != nil {
		return 
	}
	 = createDecoderOfNative(, )
	if  != nil {
		return 
	}
	switch .Kind() {
	case reflect.Interface:
		,  := .(*reflect2.UnsafeIFaceType)
		if  {
			return &ifaceDecoder{valType: }
		}
		return &efaceDecoder{}
	case reflect.Struct:
		return decoderOfStruct(, )
	case reflect.Array:
		return decoderOfArray(, )
	case reflect.Slice:
		return decoderOfSlice(, )
	case reflect.Map:
		return decoderOfMap(, )
	case reflect.Ptr:
		return decoderOfOptional(, )
	default:
		return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", .prefix, .String())}
	}
}

func ( *frozenConfig) ( reflect2.Type) ValEncoder {
	 := .RType()
	 := .getEncoderFromCache()
	if  != nil {
		return 
	}
	 := &ctx{
		frozenConfig: ,
		prefix:       "",
		decoders:     map[reflect2.Type]ValDecoder{},
		encoders:     map[reflect2.Type]ValEncoder{},
	}
	 = encoderOfType(, )
	if .LikePtr() {
		 = &onePtrEncoder{}
	}
	.addEncoderToCache(, )
	return 
}

type onePtrEncoder struct {
	encoder ValEncoder
}

func ( *onePtrEncoder) ( unsafe.Pointer) bool {
	return .encoder.IsEmpty(unsafe.Pointer(&))
}

func ( *onePtrEncoder) ( unsafe.Pointer,  *Stream) {
	.encoder.Encode(unsafe.Pointer(&), )
}

func encoderOfType( *ctx,  reflect2.Type) ValEncoder {
	 := getTypeEncoderFromExtension(, )
	if  != nil {
		return 
	}
	 = createEncoderOfType(, )
	for ,  := range extensions {
		 = .DecorateEncoder(, )
	}
	 = .encoderExtension.DecorateEncoder(, )
	for ,  := range .extraExtensions {
		 = .DecorateEncoder(, )
	}
	return 
}

func createEncoderOfType( *ctx,  reflect2.Type) ValEncoder {
	 := .encoders[]
	if  != nil {
		return 
	}
	 := &placeholderEncoder{}
	.encoders[] = 
	 = _createEncoderOfType(, )
	.encoder = 
	return 
}
func _createEncoderOfType( *ctx,  reflect2.Type) ValEncoder {
	 := createEncoderOfJsonRawMessage(, )
	if  != nil {
		return 
	}
	 = createEncoderOfJsonNumber(, )
	if  != nil {
		return 
	}
	 = createEncoderOfMarshaler(, )
	if  != nil {
		return 
	}
	 = createEncoderOfAny(, )
	if  != nil {
		return 
	}
	 = createEncoderOfNative(, )
	if  != nil {
		return 
	}
	 := .Kind()
	switch  {
	case reflect.Interface:
		return &dynamicEncoder{}
	case reflect.Struct:
		return encoderOfStruct(, )
	case reflect.Array:
		return encoderOfArray(, )
	case reflect.Slice:
		return encoderOfSlice(, )
	case reflect.Map:
		return encoderOfMap(, )
	case reflect.Ptr:
		return encoderOfOptional(, )
	default:
		return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", .prefix, .String())}
	}
}

type lazyErrorDecoder struct {
	err error
}

func ( *lazyErrorDecoder) ( unsafe.Pointer,  *Iterator) {
	if .WhatIsNext() != NilValue {
		if .Error == nil {
			.Error = .err
		}
	} else {
		.Skip()
	}
}

type lazyErrorEncoder struct {
	err error
}

func ( *lazyErrorEncoder) ( unsafe.Pointer,  *Stream) {
	if  == nil {
		.WriteNil()
	} else if .Error == nil {
		.Error = .err
	}
}

func ( *lazyErrorEncoder) ( unsafe.Pointer) bool {
	return false
}

type placeholderDecoder struct {
	decoder ValDecoder
}

func ( *placeholderDecoder) ( unsafe.Pointer,  *Iterator) {
	.decoder.Decode(, )
}

type placeholderEncoder struct {
	encoder ValEncoder
}

func ( *placeholderEncoder) ( unsafe.Pointer,  *Stream) {
	.encoder.Encode(, )
}

func ( *placeholderEncoder) ( unsafe.Pointer) bool {
	return .encoder.IsEmpty()
}