package jsoniter

import (
	
	
	
	
	
	
	
)

var typeDecoders = map[string]ValDecoder{}
var fieldDecoders = map[string]ValDecoder{}
var typeEncoders = map[string]ValEncoder{}
var fieldEncoders = map[string]ValEncoder{}
var extensions = []Extension{}

// StructDescriptor describe how should we encode/decode the struct
type StructDescriptor struct {
	Type   reflect2.Type
	Fields []*Binding
}

// GetField get one field from the descriptor by its name.
// Can not use map here to keep field orders.
func ( *StructDescriptor) ( string) *Binding {
	for ,  := range .Fields {
		if .Field.Name() ==  {
			return 
		}
	}
	return nil
}

// Binding describe how should we encode/decode the struct field
type Binding struct {
	levels    []int
	Field     reflect2.StructField
	FromNames []string
	ToNames   []string
	Encoder   ValEncoder
	Decoder   ValDecoder
}

// Extension the one for all SPI. Customize encoding/decoding by specifying alternate encoder/decoder.
// Can also rename fields by UpdateStructDescriptor.
type Extension interface {
	UpdateStructDescriptor(structDescriptor *StructDescriptor)
	CreateMapKeyDecoder(typ reflect2.Type) ValDecoder
	CreateMapKeyEncoder(typ reflect2.Type) ValEncoder
	CreateDecoder(typ reflect2.Type) ValDecoder
	CreateEncoder(typ reflect2.Type) ValEncoder
	DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder
	DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder
}

// DummyExtension embed this type get dummy implementation for all methods of Extension
type DummyExtension struct {
}

// UpdateStructDescriptor No-op
func ( *DummyExtension) ( *StructDescriptor) {
}

// CreateMapKeyDecoder No-op
func ( *DummyExtension) ( reflect2.Type) ValDecoder {
	return nil
}

// CreateMapKeyEncoder No-op
func ( *DummyExtension) ( reflect2.Type) ValEncoder {
	return nil
}

// CreateDecoder No-op
func ( *DummyExtension) ( reflect2.Type) ValDecoder {
	return nil
}

// CreateEncoder No-op
func ( *DummyExtension) ( reflect2.Type) ValEncoder {
	return nil
}

// DecorateDecoder No-op
func ( *DummyExtension) ( reflect2.Type,  ValDecoder) ValDecoder {
	return 
}

// DecorateEncoder No-op
func ( *DummyExtension) ( reflect2.Type,  ValEncoder) ValEncoder {
	return 
}

type EncoderExtension map[reflect2.Type]ValEncoder

// UpdateStructDescriptor No-op
func ( EncoderExtension) ( *StructDescriptor) {
}

// CreateDecoder No-op
func ( EncoderExtension) ( reflect2.Type) ValDecoder {
	return nil
}

// CreateEncoder get encoder from map
func ( EncoderExtension) ( reflect2.Type) ValEncoder {
	return []
}

// CreateMapKeyDecoder No-op
func ( EncoderExtension) ( reflect2.Type) ValDecoder {
	return nil
}

// CreateMapKeyEncoder No-op
func ( EncoderExtension) ( reflect2.Type) ValEncoder {
	return nil
}

// DecorateDecoder No-op
func ( EncoderExtension) ( reflect2.Type,  ValDecoder) ValDecoder {
	return 
}

// DecorateEncoder No-op
func ( EncoderExtension) ( reflect2.Type,  ValEncoder) ValEncoder {
	return 
}

type DecoderExtension map[reflect2.Type]ValDecoder

// UpdateStructDescriptor No-op
func ( DecoderExtension) ( *StructDescriptor) {
}

// CreateMapKeyDecoder No-op
func ( DecoderExtension) ( reflect2.Type) ValDecoder {
	return nil
}

// CreateMapKeyEncoder No-op
func ( DecoderExtension) ( reflect2.Type) ValEncoder {
	return nil
}

// CreateDecoder get decoder from map
func ( DecoderExtension) ( reflect2.Type) ValDecoder {
	return []
}

// CreateEncoder No-op
func ( DecoderExtension) ( reflect2.Type) ValEncoder {
	return nil
}

// DecorateDecoder No-op
func ( DecoderExtension) ( reflect2.Type,  ValDecoder) ValDecoder {
	return 
}

// DecorateEncoder No-op
func ( DecoderExtension) ( reflect2.Type,  ValEncoder) ValEncoder {
	return 
}

type funcDecoder struct {
	fun DecoderFunc
}

func ( *funcDecoder) ( unsafe.Pointer,  *Iterator) {
	.fun(, )
}

type funcEncoder struct {
	fun         EncoderFunc
	isEmptyFunc func(ptr unsafe.Pointer) bool
}

func ( *funcEncoder) ( unsafe.Pointer,  *Stream) {
	.fun(, )
}

func ( *funcEncoder) ( unsafe.Pointer) bool {
	if .isEmptyFunc == nil {
		return false
	}
	return .isEmptyFunc()
}

// DecoderFunc the function form of TypeDecoder
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)

// EncoderFunc the function form of TypeEncoder
type EncoderFunc func(ptr unsafe.Pointer, stream *Stream)

// RegisterTypeDecoderFunc register TypeDecoder for a type with function
func ( string,  DecoderFunc) {
	typeDecoders[] = &funcDecoder{}
}

// RegisterTypeDecoder register TypeDecoder for a typ
func ( string,  ValDecoder) {
	typeDecoders[] = 
}

// RegisterFieldDecoderFunc register TypeDecoder for a struct field with function
func ( string,  string,  DecoderFunc) {
	RegisterFieldDecoder(, , &funcDecoder{})
}

// RegisterFieldDecoder register TypeDecoder for a struct field
func ( string,  string,  ValDecoder) {
	fieldDecoders[fmt.Sprintf("%s/%s", , )] = 
}

// RegisterTypeEncoderFunc register TypeEncoder for a type with encode/isEmpty function
func ( string,  EncoderFunc,  func(unsafe.Pointer) bool) {
	typeEncoders[] = &funcEncoder{, }
}

// RegisterTypeEncoder register TypeEncoder for a type
func ( string,  ValEncoder) {
	typeEncoders[] = 
}

// RegisterFieldEncoderFunc register TypeEncoder for a struct field with encode/isEmpty function
func ( string,  string,  EncoderFunc,  func(unsafe.Pointer) bool) {
	RegisterFieldEncoder(, , &funcEncoder{, })
}

// RegisterFieldEncoder register TypeEncoder for a struct field
func ( string,  string,  ValEncoder) {
	fieldEncoders[fmt.Sprintf("%s/%s", , )] = 
}

// RegisterExtension register extension
func ( Extension) {
	extensions = append(extensions, )
}

func getTypeDecoderFromExtension( *ctx,  reflect2.Type) ValDecoder {
	 := _getTypeDecoderFromExtension(, )
	if  != nil {
		for ,  := range extensions {
			 = .DecorateDecoder(, )
		}
		 = .decoderExtension.DecorateDecoder(, )
		for ,  := range .extraExtensions {
			 = .DecorateDecoder(, )
		}
	}
	return 
}
func _getTypeDecoderFromExtension( *ctx,  reflect2.Type) ValDecoder {
	for ,  := range extensions {
		 := .CreateDecoder()
		if  != nil {
			return 
		}
	}
	 := .decoderExtension.CreateDecoder()
	if  != nil {
		return 
	}
	for ,  := range .extraExtensions {
		 := .CreateDecoder()
		if  != nil {
			return 
		}
	}
	 := .String()
	 = typeDecoders[]
	if  != nil {
		return 
	}
	if .Kind() == reflect.Ptr {
		 := .(*reflect2.UnsafePtrType)
		 := typeDecoders[.Elem().String()]
		if  != nil {
			return &OptionalDecoder{.Elem(), }
		}
	}
	return nil
}

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

func _getTypeEncoderFromExtension( *ctx,  reflect2.Type) ValEncoder {
	for ,  := range extensions {
		 := .CreateEncoder()
		if  != nil {
			return 
		}
	}
	 := .encoderExtension.CreateEncoder()
	if  != nil {
		return 
	}
	for ,  := range .extraExtensions {
		 := .CreateEncoder()
		if  != nil {
			return 
		}
	}
	 := .String()
	 = typeEncoders[]
	if  != nil {
		return 
	}
	if .Kind() == reflect.Ptr {
		 := .(*reflect2.UnsafePtrType)
		 := typeEncoders[.Elem().String()]
		if  != nil {
			return &OptionalEncoder{}
		}
	}
	return nil
}

func describeStruct( *ctx,  reflect2.Type) *StructDescriptor {
	 := .(*reflect2.UnsafeStructType)
	 := []*Binding{}
	 := []*Binding{}
	for  := 0;  < .NumField(); ++ {
		 := .Field()
		,  := .Tag().Lookup(.getTagKey())
		if .onlyTaggedField && ! && !.Anonymous() {
			continue
		}
		if  == "-" || .Name() == "_" {
			continue
		}
		 := strings.Split(, ",")
		if .Anonymous() && ( == "" || [0] == "") {
			if .Type().Kind() == reflect.Struct {
				 := (, .Type())
				for ,  := range .Fields {
					.levels = append([]int{}, .levels...)
					 := .Encoder.(*structFieldEncoder).omitempty
					.Encoder = &structFieldEncoder{, .Encoder, }
					.Decoder = &structFieldDecoder{, .Decoder}
					 = append(, )
				}
				continue
			} else if .Type().Kind() == reflect.Ptr {
				 := .Type().(*reflect2.UnsafePtrType)
				if .Elem().Kind() == reflect.Struct {
					 := (, .Elem())
					for ,  := range .Fields {
						.levels = append([]int{}, .levels...)
						 := .Encoder.(*structFieldEncoder).omitempty
						.Encoder = &dereferenceEncoder{.Encoder}
						.Encoder = &structFieldEncoder{, .Encoder, }
						.Decoder = &dereferenceDecoder{.Elem(), .Decoder}
						.Decoder = &structFieldDecoder{, .Decoder}
						 = append(, )
					}
					continue
				}
			}
		}
		 := calcFieldNames(.Name(), [0], )
		 := fmt.Sprintf("%s/%s", .String(), .Name())
		 := fieldDecoders[]
		if  == nil {
			 = decoderOfType(.append(.Name()), .Type())
		}
		 := fieldEncoders[]
		if  == nil {
			 = encoderOfType(.append(.Name()), .Type())
		}
		 := &Binding{
			Field:     ,
			FromNames: ,
			ToNames:   ,
			Decoder:   ,
			Encoder:   ,
		}
		.levels = []int{}
		 = append(, )
	}
	return createStructDescriptor(, , , )
}
func createStructDescriptor( *ctx,  reflect2.Type,  []*Binding,  []*Binding) *StructDescriptor {
	 := &StructDescriptor{
		Type:   ,
		Fields: ,
	}
	for ,  := range extensions {
		.UpdateStructDescriptor()
	}
	.encoderExtension.UpdateStructDescriptor()
	.decoderExtension.UpdateStructDescriptor()
	for ,  := range .extraExtensions {
		.UpdateStructDescriptor()
	}
	processTags(, .frozenConfig)
	// merge normal & embedded bindings & sort with original order
	 := sortableBindings(append(, .Fields...))
	sort.Sort()
	.Fields = 
	return 
}

type sortableBindings []*Binding

func ( sortableBindings) () int {
	return len()
}

func ( sortableBindings) (,  int) bool {
	 := [].levels
	 := [].levels
	 := 0
	for {
		if [] < [] {
			return true
		} else if [] > [] {
			return false
		}
		++
	}
}

func ( sortableBindings) (,  int) {
	[], [] = [], []
}

func processTags( *StructDescriptor,  *frozenConfig) {
	for ,  := range .Fields {
		 := false
		 := strings.Split(.Field.Tag().Get(.getTagKey()), ",")
		for ,  := range [1:] {
			if  == "omitempty" {
				 = true
			} else if  == "string" {
				if .Field.Type().Kind() == reflect.String {
					.Decoder = &stringModeStringDecoder{.Decoder, }
					.Encoder = &stringModeStringEncoder{.Encoder, }
				} else {
					.Decoder = &stringModeNumberDecoder{.Decoder}
					.Encoder = &stringModeNumberEncoder{.Encoder}
				}
			}
		}
		.Decoder = &structFieldDecoder{.Field, .Decoder}
		.Encoder = &structFieldEncoder{.Field, .Encoder, }
	}
}

func calcFieldNames( string,  string,  string) []string {
	// ignore?
	if  == "-" {
		return []string{}
	}
	// rename?
	var  []string
	if  == "" {
		 = []string{}
	} else {
		 = []string{}
	}
	// private?
	 := unicode.IsLower(rune([0])) || [0] == '_'
	if  {
		 = []string{}
	}
	return 
}