package encoder

import (
	
	
	
	
	
	
	

	
	
)

type marshalerContext interface {
	MarshalJSON(context.Context) ([]byte, error)
}

var (
	marshalJSONType        = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
	marshalJSONContextType = reflect.TypeOf((*marshalerContext)(nil)).Elem()
	marshalTextType        = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
	jsonNumberType         = reflect.TypeOf(json.Number(""))
	cachedOpcodeSets       []*OpcodeSet
	cachedOpcodeMap        unsafe.Pointer // map[uintptr]*OpcodeSet
	typeAddr               *runtime.TypeAddr
	initEncoderOnce        sync.Once
)

func initEncoder() {
	initEncoderOnce.Do(func() {
		typeAddr = runtime.AnalyzeTypeAddr()
		if typeAddr == nil {
			typeAddr = &runtime.TypeAddr{}
		}
		cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift+1)
	})
}

func loadOpcodeMap() map[uintptr]*OpcodeSet {
	 := atomic.LoadPointer(&cachedOpcodeMap)
	return *(*map[uintptr]*OpcodeSet)(unsafe.Pointer(&))
}

func storeOpcodeSet( uintptr,  *OpcodeSet,  map[uintptr]*OpcodeSet) {
	 := make(map[uintptr]*OpcodeSet, len()+1)
	[] = 

	for ,  := range  {
		[] = 
	}

	atomic.StorePointer(&cachedOpcodeMap, *(*unsafe.Pointer)(unsafe.Pointer(&)))
}

func compileToGetCodeSetSlowPath( uintptr) (*OpcodeSet, error) {
	 := loadOpcodeMap()
	if ,  := [];  {
		return , nil
	}
	,  := newCompiler().compile()
	if  != nil {
		return nil, 
	}
	storeOpcodeSet(, , )
	return , nil
}

func getFilteredCodeSetIfNeeded( *RuntimeContext,  *OpcodeSet) (*OpcodeSet, error) {
	if (.Option.Flag & ContextOption) == 0 {
		return , nil
	}
	 := FieldQueryFromContext(.Option.Context)
	if  == nil {
		return , nil
	}
	.Option.Flag |= FieldQueryOption
	 := .getQueryCache(.Hash())
	if  != nil {
		return , nil
	}
	,  := newCompiler().codeToOpcodeSet(.Type, .Code.Filter())
	if  != nil {
		return nil, 
	}
	.setQueryCache(.Hash(), )
	return , nil
}

type Compiler struct {
	structTypeToCode map[uintptr]*StructCode
}

func newCompiler() *Compiler {
	return &Compiler{
		structTypeToCode: map[uintptr]*StructCode{},
	}
}

func ( *Compiler) ( uintptr) (*OpcodeSet, error) {
	// noescape trick for header.typ ( reflect.*rtype )
	 := *(**runtime.Type)(unsafe.Pointer(&))
	,  := .typeToCode()
	if  != nil {
		return nil, 
	}
	return .codeToOpcodeSet(, )
}

func ( *Compiler) ( *runtime.Type,  Code) (*OpcodeSet, error) {
	 := .codeToOpcode(&compileContext{
		structTypeToCodes: map[uintptr]Opcodes{},
		recursiveCodes:    &Opcodes{},
	}, , )
	if  := .Validate();  != nil {
		return nil, 
	}
	 := .codeToOpcode(&compileContext{
		structTypeToCodes: map[uintptr]Opcodes{},
		recursiveCodes:    &Opcodes{},
		escapeKey:         true,
	}, , )
	 = copyOpcode()
	 = copyOpcode()
	setTotalLengthToInterfaceOp()
	setTotalLengthToInterfaceOp()
	 := copyToInterfaceOpcode()
	 := copyToInterfaceOpcode()
	 := .TotalLength()
	return &OpcodeSet{
		Type:                     ,
		NoescapeKeyCode:          ,
		EscapeKeyCode:            ,
		InterfaceNoescapeKeyCode: ,
		InterfaceEscapeKeyCode:   ,
		CodeLength:               ,
		EndCode:                  ToEndCode(),
		Code:                     ,
		QueryCache:               map[string]*OpcodeSet{},
	}, nil
}

func ( *Compiler) ( *runtime.Type) (Code, error) {
	switch {
	case .implementsMarshalJSON():
		return .marshalJSONCode()
	case .implementsMarshalText():
		return .marshalTextCode()
	}

	 := false
	 := 
	if .Kind() == reflect.Ptr {
		 = .Elem()
		 = true
	}
	switch {
	case .implementsMarshalJSON():
		return .marshalJSONCode()
	case .implementsMarshalText():
		return .marshalTextCode()
	}
	switch .Kind() {
	case reflect.Slice:
		 := .Elem()
		if .Kind() == reflect.Uint8 {
			 := runtime.PtrTo()
			if !.implementsMarshalJSONType() && !.Implements(marshalTextType) {
				return .bytesCode(, )
			}
		}
		return .sliceCode()
	case reflect.Map:
		if  {
			return .ptrCode(runtime.PtrTo())
		}
		return .mapCode()
	case reflect.Struct:
		return .structCode(, )
	case reflect.Int:
		return .intCode(, )
	case reflect.Int8:
		return .int8Code(, )
	case reflect.Int16:
		return .int16Code(, )
	case reflect.Int32:
		return .int32Code(, )
	case reflect.Int64:
		return .int64Code(, )
	case reflect.Uint, reflect.Uintptr:
		return .uintCode(, )
	case reflect.Uint8:
		return .uint8Code(, )
	case reflect.Uint16:
		return .uint16Code(, )
	case reflect.Uint32:
		return .uint32Code(, )
	case reflect.Uint64:
		return .uint64Code(, )
	case reflect.Float32:
		return .float32Code(, )
	case reflect.Float64:
		return .float64Code(, )
	case reflect.String:
		return .stringCode(, )
	case reflect.Bool:
		return .boolCode(, )
	case reflect.Interface:
		return .interfaceCode(, )
	default:
		if  && .Implements(marshalTextType) {
			 = 
		}
		return .typeToCodeWithPtr(, )
	}
}

func ( *Compiler) ( *runtime.Type,  bool) (Code, error) {
	switch {
	case .implementsMarshalJSON():
		return .marshalJSONCode()
	case .implementsMarshalText():
		return .marshalTextCode()
	}
	switch .Kind() {
	case reflect.Ptr:
		return .ptrCode()
	case reflect.Slice:
		 := .Elem()
		if .Kind() == reflect.Uint8 {
			 := runtime.PtrTo()
			if !.implementsMarshalJSONType() && !.Implements(marshalTextType) {
				return .bytesCode(, false)
			}
		}
		return .sliceCode()
	case reflect.Array:
		return .arrayCode()
	case reflect.Map:
		return .mapCode()
	case reflect.Struct:
		return .structCode(, )
	case reflect.Interface:
		return .interfaceCode(, false)
	case reflect.Int:
		return .intCode(, false)
	case reflect.Int8:
		return .int8Code(, false)
	case reflect.Int16:
		return .int16Code(, false)
	case reflect.Int32:
		return .int32Code(, false)
	case reflect.Int64:
		return .int64Code(, false)
	case reflect.Uint:
		return .uintCode(, false)
	case reflect.Uint8:
		return .uint8Code(, false)
	case reflect.Uint16:
		return .uint16Code(, false)
	case reflect.Uint32:
		return .uint32Code(, false)
	case reflect.Uint64:
		return .uint64Code(, false)
	case reflect.Uintptr:
		return .uintCode(, false)
	case reflect.Float32:
		return .float32Code(, false)
	case reflect.Float64:
		return .float64Code(, false)
	case reflect.String:
		return .stringCode(, false)
	case reflect.Bool:
		return .boolCode(, false)
	}
	return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type()}
}

const intSize = 32 << (^uint(0) >> 63)

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*IntCode, error) {
	return &IntCode{typ: , bitSize: intSize, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 8, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 16, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 32, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 64, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*UintCode, error) {
	return &UintCode{typ: , bitSize: intSize, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 8, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 16, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 32, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 64, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*FloatCode, error) {
	return &FloatCode{typ: , bitSize: 32, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*FloatCode, error) {
	return &FloatCode{typ: , bitSize: 64, isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*StringCode, error) {
	return &StringCode{typ: , isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*BoolCode, error) {
	return &BoolCode{typ: , isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*IntCode, error) {
	return &IntCode{typ: , bitSize: intSize, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 8, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 16, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 32, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*IntCode, error) {
	return &IntCode{typ: , bitSize: 64, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*UintCode, error) {
	return &UintCode{typ: , bitSize: intSize, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 8, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 16, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 32, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*UintCode, error) {
	return &UintCode{typ: , bitSize: 64, isString: true}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*BytesCode, error) {
	return &BytesCode{typ: , isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type,  bool) (*InterfaceCode, error) {
	return &InterfaceCode{typ: , isPtr: }, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*MarshalJSONCode, error) {
	return &MarshalJSONCode{
		typ:                ,
		isAddrForMarshaler: .isPtrMarshalJSONType(),
		isNilableType:      .isNilableType(),
		isMarshalerContext: .Implements(marshalJSONContextType) || runtime.PtrTo().Implements(marshalJSONContextType),
	}, nil
}

//nolint:unparam
func ( *Compiler) ( *runtime.Type) (*MarshalTextCode, error) {
	return &MarshalTextCode{
		typ:                ,
		isAddrForMarshaler: .isPtrMarshalTextType(),
		isNilableType:      .isNilableType(),
	}, nil
}

func ( *Compiler) ( *runtime.Type) (*PtrCode, error) {
	,  := .typeToCodeWithPtr(.Elem(), true)
	if  != nil {
		return nil, 
	}
	,  := .(*PtrCode)
	if  {
		return &PtrCode{typ: , value: .value, ptrNum: .ptrNum + 1}, nil
	}
	return &PtrCode{typ: , value: , ptrNum: 1}, nil
}

func ( *Compiler) ( *runtime.Type) (*SliceCode, error) {
	 := .Elem()
	,  := .listElemCode()
	if  != nil {
		return nil, 
	}
	if .Kind() == CodeKindStruct {
		 := .(*StructCode)
		.enableIndirect()
	}
	return &SliceCode{typ: , value: }, nil
}

func ( *Compiler) ( *runtime.Type) (*ArrayCode, error) {
	 := .Elem()
	,  := .listElemCode()
	if  != nil {
		return nil, 
	}
	if .Kind() == CodeKindStruct {
		 := .(*StructCode)
		.enableIndirect()
	}
	return &ArrayCode{typ: , value: }, nil
}

func ( *Compiler) ( *runtime.Type) (*MapCode, error) {
	,  := .mapKeyCode(.Key())
	if  != nil {
		return nil, 
	}
	,  := .mapValueCode(.Elem())
	if  != nil {
		return nil, 
	}
	if .Kind() == CodeKindStruct {
		 := .(*StructCode)
		.enableIndirect()
	}
	return &MapCode{typ: , key: , value: }, nil
}

func ( *Compiler) ( *runtime.Type) (Code, error) {
	switch {
	case .implementsMarshalJSONType() || .implementsMarshalJSONType(runtime.PtrTo()):
		return .marshalJSONCode()
	case !.Implements(marshalTextType) && runtime.PtrTo().Implements(marshalTextType):
		return .marshalTextCode()
	case .Kind() == reflect.Map:
		return .ptrCode(runtime.PtrTo())
	default:
		// isPtr was originally used to indicate whether the type of top level is pointer.
		// However, since the slice/array element is a specification that can get the pointer address, explicitly set isPtr to true.
		// See here for related issues: https://github.com/goccy/go-json/issues/370
		,  := .typeToCodeWithPtr(, true)
		if  != nil {
			return nil, 
		}
		,  := .(*PtrCode)
		if  {
			if .value.Kind() == CodeKindMap {
				.ptrNum++
			}
		}
		return , nil
	}
}

func ( *Compiler) ( *runtime.Type) (Code, error) {
	switch {
	case .implementsMarshalText():
		return .marshalTextCode()
	}
	switch .Kind() {
	case reflect.Ptr:
		return .ptrCode()
	case reflect.String:
		return .stringCode(, false)
	case reflect.Int:
		return .intStringCode()
	case reflect.Int8:
		return .int8StringCode()
	case reflect.Int16:
		return .int16StringCode()
	case reflect.Int32:
		return .int32StringCode()
	case reflect.Int64:
		return .int64StringCode()
	case reflect.Uint:
		return .uintStringCode()
	case reflect.Uint8:
		return .uint8StringCode()
	case reflect.Uint16:
		return .uint16StringCode()
	case reflect.Uint32:
		return .uint32StringCode()
	case reflect.Uint64:
		return .uint64StringCode()
	case reflect.Uintptr:
		return .uintStringCode()
	}
	return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type()}
}

func ( *Compiler) ( *runtime.Type) (Code, error) {
	switch .Kind() {
	case reflect.Map:
		return .ptrCode(runtime.PtrTo())
	default:
		,  := .typeToCodeWithPtr(, false)
		if  != nil {
			return nil, 
		}
		,  := .(*PtrCode)
		if  {
			if .value.Kind() == CodeKindMap {
				.ptrNum++
			}
		}
		return , nil
	}
}

func ( *Compiler) ( *runtime.Type,  bool) (*StructCode, error) {
	 := uintptr(unsafe.Pointer())
	if ,  := .structTypeToCode[];  {
		 := *
		.isRecursive = true
		return &, nil
	}
	 := runtime.IfaceIndir()
	 := &StructCode{typ: , isPtr: , isIndirect: }
	.structTypeToCode[] = 

	 := .NumField()
	 := .typeToStructTags()
	 := []*StructFieldCode{}
	for ,  := range  {
		 :=  == 0 &&  == 1
		,  := .structFieldCode(, , , )
		if  != nil {
			return nil, 
		}
		if .isAnonymous {
			 := .getAnonymousStruct()
			if  != nil {
				.removeFieldsByTags()
				if .isAssignableIndirect(, ) {
					if  {
						.isIndirect = true
					} else {
						.isIndirect = false
					}
				}
			}
		} else {
			 := .getStruct()
			if  != nil {
				if  {
					// if parent is indirect type, set child indirect property to true
					.isIndirect = true
				} else {
					// if parent is not indirect type, set child indirect property to false.
					// but if parent's indirect is false and isPtr is true, then indirect must be true.
					// Do this only if indirectConversion is enabled at the end of compileStruct.
					.isIndirect = false
				}
			}
		}
		 = append(, )
	}
	 := .getFieldMap()
	 := .getDuplicatedFieldMap()
	.fields = .filteredDuplicatedFields(, )
	if !.disableIndirectConversion && ! &&  {
		.enableIndirect()
	}
	delete(.structTypeToCode, )
	return , nil
}

func toElemType( *runtime.Type) *runtime.Type {
	for .Kind() == reflect.Ptr {
		 = .Elem()
	}
	return 
}

func ( *Compiler) ( *StructCode,  *runtime.StructTag, ,  bool) (*StructFieldCode, error) {
	 := .Field
	 := runtime.Type2RType(.Type)
	 :=  && 
	 := &StructFieldCode{
		typ:           ,
		key:           .Key,
		tag:           ,
		offset:        .Offset,
		isAnonymous:   .Anonymous && !.IsTaggedKey && toElemType().Kind() == reflect.Struct,
		isTaggedKey:   .IsTaggedKey,
		isNilableType: .isNilableType(),
		isNilCheck:    true,
	}
	switch {
	case .isMovePointerPositionFromHeadToFirstMarshalJSONFieldCase(, ):
		,  := .marshalJSONCode()
		if  != nil {
			return nil, 
		}
		.value = 
		.isAddrForMarshaler = true
		.isNilCheck = false
		.isIndirect = false
		.disableIndirectConversion = true
	case .isMovePointerPositionFromHeadToFirstMarshalTextFieldCase(, ):
		,  := .marshalTextCode()
		if  != nil {
			return nil, 
		}
		.value = 
		.isAddrForMarshaler = true
		.isNilCheck = false
		.isIndirect = false
		.disableIndirectConversion = true
	case  && .isPtrMarshalJSONType():
		// *struct{ field T }
		// func (*T) MarshalJSON() ([]byte, error)
		,  := .marshalJSONCode()
		if  != nil {
			return nil, 
		}
		.value = 
		.isAddrForMarshaler = true
		.isNilCheck = false
	case  && .isPtrMarshalTextType():
		// *struct{ field T }
		// func (*T) MarshalText() ([]byte, error)
		,  := .marshalTextCode()
		if  != nil {
			return nil, 
		}
		.value = 
		.isAddrForMarshaler = true
		.isNilCheck = false
	default:
		,  := .typeToCodeWithPtr(, )
		if  != nil {
			return nil, 
		}
		switch .Kind() {
		case CodeKindPtr, CodeKindInterface:
			.isNextOpPtrType = true
		}
		.value = 
	}
	return , nil
}

func ( *Compiler) ( *StructFieldCode,  bool) bool {
	if  {
		return false
	}
	 := .value.Kind()
	if  == CodeKindMarshalJSON {
		return false
	}
	if  == CodeKindMarshalText {
		return false
	}
	return true
}

func ( *Compiler) ( []*StructFieldCode) map[string][]*StructFieldCode {
	 := map[string][]*StructFieldCode{}
	for ,  := range  {
		if .isAnonymous {
			for ,  := range .getAnonymousFieldMap() {
				[] = append([], ...)
			}
			continue
		}
		[.key] = append([.key], )
	}
	return 
}

func ( *Compiler) ( *StructFieldCode) map[string][]*StructFieldCode {
	 := map[string][]*StructFieldCode{}
	 := .getAnonymousStruct()
	if  == nil || .isRecursive {
		[.key] = append([.key], )
		return 
	}
	for ,  := range .getFieldMapFromAnonymousParent(.fields) {
		[] = append([], ...)
	}
	return 
}

func ( *Compiler) ( []*StructFieldCode) map[string][]*StructFieldCode {
	 := map[string][]*StructFieldCode{}
	for ,  := range  {
		if .isAnonymous {
			for ,  := range .getAnonymousFieldMap() {
				// Do not handle tagged key when embedding more than once
				for ,  := range  {
					.isTaggedKey = false
				}
				[] = append([], ...)
			}
			continue
		}
		[.key] = append([.key], )
	}
	return 
}

func ( *Compiler) ( map[string][]*StructFieldCode) map[*StructFieldCode]struct{} {
	 := map[*StructFieldCode]struct{}{}
	for ,  := range  {
		if len() == 1 {
			continue
		}
		if .isTaggedKeyOnly() {
			for ,  := range  {
				if .isTaggedKey {
					continue
				}
				[] = struct{}{}
			}
		} else {
			for ,  := range  {
				[] = struct{}{}
			}
		}
	}
	return 
}

func ( *Compiler) ( []*StructFieldCode,  map[*StructFieldCode]struct{}) []*StructFieldCode {
	 := make([]*StructFieldCode, 0, len())
	for ,  := range  {
		if .isAnonymous {
			 := .getAnonymousStruct()
			if  != nil && !.isRecursive {
				.fields = .(.fields, )
				if len(.fields) > 0 {
					 = append(, )
				}
				continue
			}
		}
		if ,  := [];  {
			continue
		}
		 = append(, )
	}
	return 
}

func ( *Compiler) ( []*StructFieldCode) bool {
	var  int
	for ,  := range  {
		if .isTaggedKey {
			++
		}
	}
	return  == 1
}

func ( *Compiler) ( *runtime.Type) runtime.StructTags {
	 := runtime.StructTags{}
	 := .NumField()
	for  := 0;  < ; ++ {
		 := .Field()
		if runtime.IsIgnoredStructField() {
			continue
		}
		 = append(, runtime.StructTagFromField())
	}
	return 
}

// *struct{ field T } => struct { field *T }
// func (*T) MarshalJSON() ([]byte, error)
func ( *Compiler) ( *runtime.Type,  bool) bool {
	return  && !.isNilableType() && .isPtrMarshalJSONType()
}

// *struct{ field T } => struct { field *T }
// func (*T) MarshalText() ([]byte, error)
func ( *Compiler) ( *runtime.Type,  bool) bool {
	return  && !.isNilableType() && .isPtrMarshalTextType()
}

func ( *Compiler) ( *runtime.Type) bool {
	if !.implementsMarshalJSONType() {
		return false
	}
	if .Kind() != reflect.Ptr {
		return true
	}
	// type kind is reflect.Ptr
	if !.implementsMarshalJSONType(.Elem()) {
		return true
	}
	// needs to dereference
	return false
}

func ( *Compiler) ( *runtime.Type) bool {
	if !.Implements(marshalTextType) {
		return false
	}
	if .Kind() != reflect.Ptr {
		return true
	}
	// type kind is reflect.Ptr
	if !.Elem().Implements(marshalTextType) {
		return true
	}
	// needs to dereference
	return false
}

func ( *Compiler) ( *runtime.Type) bool {
	if !runtime.IfaceIndir() {
		return true
	}
	switch .Kind() {
	case reflect.Ptr:
		return true
	case reflect.Map:
		return true
	case reflect.Func:
		return true
	default:
		return false
	}
}

func ( *Compiler) ( *runtime.Type) bool {
	return .Implements(marshalJSONType) || .Implements(marshalJSONContextType)
}

func ( *Compiler) ( *runtime.Type) bool {
	return !.implementsMarshalJSONType() && .implementsMarshalJSONType(runtime.PtrTo())
}

func ( *Compiler) ( *runtime.Type) bool {
	return !.Implements(marshalTextType) && runtime.PtrTo().Implements(marshalTextType)
}

func ( *Compiler) ( *compileContext,  *runtime.Type,  Code) *Opcode {
	 := .ToOpcode()
	.Last().Next = newEndOp(, )
	.linkRecursiveCode()
	return .First()
}

func ( *Compiler) ( *compileContext) {
	 := map[uintptr]*CompiledCode{}
	for ,  := range *.recursiveCodes {
		 := uintptr(unsafe.Pointer(.Type))
		 := .structTypeToCodes[]
		if ,  := [];  {
			*.Jmp = *
			continue
		}

		 := copyOpcode(.First())
		.Op = .Op.PtrHeadToHead()
		 := newEndOp(&compileContext{}, .Type)
		.Op = OpRecursiveEnd

		// OpRecursiveEnd must set before call TotalLength
		.End.Next = 

		 := .TotalLength()

		// Idx, ElemIdx, Length must set after call TotalLength
		.Idx = uint32(( + 1) * uintptrSize)
		.ElemIdx = .Idx + uintptrSize
		.Length = .Idx + 2*uintptrSize

		// extend length to alloc slot for elemIdx + length
		 := uintptr(.TotalLength()) + 3
		 := uintptr() + 3

		 := .Jmp
		.Code = 
		.CurLen = 
		.NextLen = 
		.Linked = true

		[] = 
	}
}